File size: 3,135 Bytes
61d39e2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
# Puter Backend Boot Sequence

This document describes the boot sequence of Puter's backend.

**Runtime Environment**
  - Configuration directory is determined
  - Runtime directory is determined
  - Mod directory is determined
  - Services are instantiated

**Construction**
  - Data structures are created

**Initialization**
  - Registries are populated
  - Services prepare for next phase

**Consolidation**
  - Service event bus receives first event (`boot.consolidation`)
  - Services perform coordinated setup behaviors
  - Services prepare for next phase

**Activation**
  - Blocking listeners of `boot.consolidation` have resolved
  - HTTP servers start listening

**Ready**
  - Services are informed that Puter is providing service

## Boot Phases

### Construction

Services implement a method called `construct` which initializes members
of an instance. Services do not override the class constructor of
**BaseService**. This makes it possible to use the `new` operator without
invoking a service's constructor behavior during debugging.

The first phase of the boot sequence, "construction", is simply a loop to
call `construct` on all registered services.

The `_construct` override should not:
- call other services
- emit events

### Initialization

At initialization, the `init()` method is called on all services.
The `_init` override can be used to:
- register information with other services, when services don't
  need to register this information in a specific sequence.
  An example of this is registering commands with CommandService.
- perform setup that is required before the consolidation phase starts.

### Consolidation

Consolidation is a phase where services should emit events that
are related to bringing up the system. For example, WebServerService
('web-server') emits an event telling services to install middlewares,
and later emits an event telling services to install routes.

Consolidation starts when Kernel emits `boot.consolidation` to the
services event bus, which happens after `init()` resolves for all
services.

### Activation

Activation is a phase where services begin listening on external
interfaces. For example, this is when the web server starts listening.

Activation starts when Kernel emits `boot.activation`.

### Ready

Ready is a phase where services are informed that everything is up.

Ready starts when Kernel emits `boot.ready`.

## Events and Asynchronous Execution

The services event bus is implemented so you can `await` a call to `.emit()`.
Event listeners can choose to have blocking behavior by returning a promise.

During emission of a particular event, listeners of this event will not
block each other, but all listeners must resolve before the call to
`.emit()` is resolved. (i.e. `emit` uses `Promise.all`)

## Legacy Services

Some services were implemented before the `BaseService` class - which
implements the `init` method - was created. These services are called
"legacy services" and they are instantiated _after_ initialization but
_before_ consolidation.