Codex-authored docs covering primitives, commands, messaging, lifecycle, subsystems, and getting started — all using the current DTO/Options/Result API with concrete usage examples. Co-Authored-By: Virgil <virgil@lethean.io>
152 lines
3.2 KiB
Markdown
152 lines
3.2 KiB
Markdown
---
|
|
title: Services
|
|
description: Register, inspect, and lock CoreGO services.
|
|
---
|
|
|
|
# Services
|
|
|
|
In CoreGO, a service is a named lifecycle entry stored in the Core registry.
|
|
|
|
## Register a Service
|
|
|
|
```go
|
|
c := core.New()
|
|
|
|
r := c.Service("audit", core.Service{
|
|
OnStart: func() core.Result {
|
|
core.Info("audit started")
|
|
return core.Result{OK: true}
|
|
},
|
|
OnStop: func() core.Result {
|
|
core.Info("audit stopped")
|
|
return core.Result{OK: true}
|
|
},
|
|
})
|
|
```
|
|
|
|
Registration succeeds when:
|
|
|
|
- the name is not empty
|
|
- the registry is not locked
|
|
- the name is not already in use
|
|
|
|
## Read a Service Back
|
|
|
|
```go
|
|
r := c.Service("audit")
|
|
if r.OK {
|
|
svc := r.Value.(*core.Service)
|
|
_ = svc
|
|
}
|
|
```
|
|
|
|
The returned value is `*core.Service`.
|
|
|
|
## List Registered Services
|
|
|
|
```go
|
|
names := c.Services()
|
|
```
|
|
|
|
### Important Detail
|
|
|
|
The current registry is map-backed. `Services()`, `Startables()`, and `Stoppables()` do not promise a stable order.
|
|
|
|
## Lifecycle Snapshots
|
|
|
|
Use these helpers when you want the current set of startable or stoppable services:
|
|
|
|
```go
|
|
startables := c.Startables()
|
|
stoppables := c.Stoppables()
|
|
```
|
|
|
|
They return `[]*core.Service` inside `Result.Value`.
|
|
|
|
## Lock the Registry
|
|
|
|
CoreGO has a service-lock mechanism, but it is explicit.
|
|
|
|
```go
|
|
c := core.New()
|
|
|
|
c.LockEnable()
|
|
c.Service("audit", core.Service{})
|
|
c.Service("cache", core.Service{})
|
|
c.LockApply()
|
|
```
|
|
|
|
After `LockApply`, new registrations fail:
|
|
|
|
```go
|
|
r := c.Service("late", core.Service{})
|
|
fmt.Println(r.OK) // false
|
|
```
|
|
|
|
The default lock name is `"srv"`. You can pass a different name if you need a custom lock namespace.
|
|
|
|
For the service registry itself, use the default `"srv"` lock path. That is the path used by `Core.Service(...)`.
|
|
|
|
## `NewWithFactories`
|
|
|
|
For GUI runtimes or factory-driven setup, CoreGO provides `NewWithFactories`.
|
|
|
|
```go
|
|
r := core.NewWithFactories(nil, map[string]core.ServiceFactory{
|
|
"audit": func() core.Result {
|
|
return core.Result{Value: core.Service{
|
|
OnStart: func() core.Result {
|
|
return core.Result{OK: true}
|
|
},
|
|
}, OK: true}
|
|
},
|
|
"cache": func() core.Result {
|
|
return core.Result{Value: core.Service{}, OK: true}
|
|
},
|
|
})
|
|
```
|
|
|
|
### Important Details
|
|
|
|
- each factory must return a `core.Service` in `Result.Value`
|
|
- factories are executed in sorted key order
|
|
- nil factories are skipped
|
|
- the return value is `*core.Runtime`
|
|
|
|
## `Runtime`
|
|
|
|
`Runtime` is a small wrapper used for external runtimes such as GUI bindings.
|
|
|
|
```go
|
|
r := core.NewRuntime(nil)
|
|
rt := r.Value.(*core.Runtime)
|
|
|
|
_ = rt.ServiceStartup(context.Background(), nil)
|
|
_ = rt.ServiceShutdown(context.Background())
|
|
```
|
|
|
|
`Runtime.ServiceName()` returns `"Core"`.
|
|
|
|
## `ServiceRuntime[T]` for Package Authors
|
|
|
|
If you are writing a package on top of CoreGO, use `ServiceRuntime[T]` to keep a typed options struct and the parent `Core` together.
|
|
|
|
```go
|
|
type repositoryServiceOptions struct {
|
|
BaseDirectory string
|
|
}
|
|
|
|
type repositoryService struct {
|
|
*core.ServiceRuntime[repositoryServiceOptions]
|
|
}
|
|
|
|
func newRepositoryService(c *core.Core) *repositoryService {
|
|
return &repositoryService{
|
|
ServiceRuntime: core.NewServiceRuntime(c, repositoryServiceOptions{
|
|
BaseDirectory: "/srv/repos",
|
|
}),
|
|
}
|
|
}
|
|
```
|
|
|
|
This is a package-authoring helper. It does not replace the `core.Service` registry entry.
|