https://github.com/peter-mount/go-kernel
A small microkernel for go applications allowing for features to be reusable services & manages the life cycle of those services.
https://github.com/peter-mount/go-kernel
Last synced: 5 months ago
JSON representation
A small microkernel for go applications allowing for features to be reusable services & manages the life cycle of those services.
- Host: GitHub
- URL: https://github.com/peter-mount/go-kernel
- Owner: peter-mount
- License: apache-2.0
- Created: 2021-01-10T12:34:25.000Z (over 5 years ago)
- Default Branch: main
- Last Pushed: 2025-02-18T19:59:47.000Z (over 1 year ago)
- Last Synced: 2025-02-18T20:43:08.239Z (over 1 year ago)
- Language: Go
- Size: 131 KB
- Stars: 4
- Watchers: 3
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# go-kernel - A service microkernel for golang applications.
go-kernel is a simple microkernel which can run multiple services within the same go runtime. The kernel provides both
lifecycle
support for those services and dependency management so that services start and stop in the correct order.
Each service can declare any dependencies with other services which are then automatically injected
at startup. This ensures that services are started in the correct order.
It also allows for code reuse without most of the required boilerplate code usually required.
Full documentation is available online as [html](https://area51.dev/go/go-kernel/) as well
as [pdf](https://area51.dev/static/book/go-kernel.pdf)
however a brief overview is listed below.
## Services
A service is simply a struct which exposes functions to other services or performs some action during the applications'
lifetime.
package myapp
// An example service
type Example struct {
// Example of injecting another service as a dependency
Config *conf.Config `kernel:"inject"`
// Example of injecting a common task worker queue provided by the kernel
Worker task.Queue `kernel:"worker"`
// Example if declaring an indirect dependency
_ *PostCSS `kernel:"inject"`
// Example of creating a command line parameter
server *bool `kernel:"flag,s,Run hugo in server mode"`
}
// Kernel lifecycle, this gets called during the start phase of the application
// This is optional, as are all of the life cycle functions.
func (s *MyService) Start() error {
return nil
}
// Example of exposed function dependencies can use
func (s *MyService) Lookup( name string ) interface{} {
return nil
}
## Bootstrap
Every application requires a simple bootstrap.
This bootstrap consists of a single call to `kernel.Launch()` providing one or more services that you want to start.
The kernel will then begin with these, injecting any dependencies required.
The order they are listed here will be used to determine which one starts first,
although any dependencies within them will be deployed first and can override this sequence.
The following is an example from the code that generates [area51.dev](https://area51.dev/):
package main
import (
"github.com/peter-mount/documentation/tools/hugo"
"github.com/peter-mount/documentation/tools/pdf"
"github.com/peter-mount/go-kernel/v2"
"log"
)
func main() {
err := kernel.Launch(
&hugo.Hugo{},
&pdf.PDF{},
)
if err != nil {
log.Fatal(err)
}
}
Here it defines two services which must be started. Each one is declared by passing an empty instance of the required
Service's to
the Launch method.
## Lifecycle
This is documented fully in the main documentation, but the following table lists them in the order the kernel will call
them.
All of these are optional.
| Seq | Lifecycle | Description | Example |
| --- |-----------|------------------------------------------------------------------|------------------------------------------------|
| 1 | Inject | Resolve dependencies | field injection with `kernel:inject` tag |
| 2 | Init | Declare command line flags | func (s *Example) Init(k *kernel.Kernel) error |
| 3 | PostInit | Verify state is correct, e.g. check command line flags are valid | func (s *Example) PostInit() error |
| 4 | Start | Starts the service, open any resources like Databases etc | func (s *Service) Start() error |
| 5 | Run | Run any tasks the service requires | func (s *Service) Run() error |
| 6 | Stop | Stops a service | func (s *Service) Stop() |
As the kernel runs through each lifecycle stage, if any method returns an error then the kernel will stop at that point.
If the failure occurs in the Start or Run stages then the Stop stage will be invoked ensuring that any services that
have been started at that point will be stopped.
### Notes
* The `Inject` and `Init` lifecycles are actually the same one but done in that order. I cannot show this in markdown for this page.
* You must *NOT* create any external resources like opening files, databases etc. before the `Start` stage.
* `Start()` is optional. If a service does not implement this function then it's marked as implicitly started.
* `Run()` is deprecated for most purposes. If a service is to perform some task like scan a disk for files it should use the Task api with the worker queue.
* `Stop()` is optional and, it is perfectly valid to implement `Stop()` without a corresponding `Start()` function.
When a service has started (with or without a `Start()` function) it is marked as started so if it implements `Stop()` then that method will be called to clean up the service.