Kernel Lifecycle

When the kernel.Launch() function is called from the Bootstrap it starts an instance of the microkernel which then goes through each stage of its lifecycle.

It exits when either the entire sequence has been completed or if a service fails part way though, at which point it will return the error the failed service has returned.

The following is an overview of this sequence. The details of each stage is described in full under the Services section of the documentation, however a Service does not have to implement any of them, they are all optional.

Inject & Init

This is the initial stage which is split into two parts.

The first part is Injection where dependencies are injected into the service (v1.1.0 or later).

The second part is Init where services can declare they depend on other services by implementing the InitialisableService. They can also define any command line flags they want to use via either mechanism.

Once this stage completes no new services can be added to the kernel.

PostInit

The second stage is PostInit which allows a service to check it has everything it needs. Usually this is to check that any command line flags are valid or mandatory ones are present.

Start

The third stage is Start. A service can implement the StartableService interface so that it can perform any initialisation it requires. For example, it could load a configuration file, open a database.

Once a service has started it can be safely used by any dependents.

If a service fails to start the kernel will skip to the Stop stage to stop any previously started service before exiting with the error of the failure.

Run

When the kernel reaches the Run stage, every service has now been started.

The kernel will then go though every deployed service and if they implement the RunnableService interface it will the Run function. If that function returns an error then the kernel will stop and enter the Stop stage to stop any previously started service before exiting with the error of the failure.

Be aware that it is possible for a single service to never exit from this stage. An example of this is the rest web server service provided by the kernel. As this has to run forever the RunnableService implementation never returns keeping the application running.

For this reason the RunnableService interface is usually used for command line tools. For Server Daemons like a rest service this interface should not be used as you cannot guarantee it will ever be called.

In the majority of purposes, applications would use the worker task Queue instead of implementing Run as it allows for more flexible task scheduling within the application.

Stop

Stop is the final stage where every service that implements the StoppableService interface that has also passed through the Start stage will have their Stop function called. This allows a service to release any resources it has open.

Note: this will call those services in reverse order. Specifically, the most recently started service will be stopped first. This is done so that services are stopped in the correct sequence.

Also, a StoppableService does not need to implement StartableService. It is perfectly fine to implement just Stop() and not Start().

This stage can be invoked at various stages:

  1. When a service's Start() method returns an error
  2. When a service's Run() method returns an error
  3. When the Run stage completes
  4. The process receives a SIGINT(2) or SIGTERM(15) signal