implement Context interface from standard library

This commit is contained in:
Helmut Merz 2023-06-03 17:21:34 +02:00
parent bcbf567a7a
commit d9e109e3a5
2 changed files with 40 additions and 5 deletions

View file

@ -1,6 +1,10 @@
package common package common
import "sync" import (
stdlib_context "context"
"sync"
"time"
)
type Config interface { type Config interface {
Name() string Name() string
@ -16,6 +20,7 @@ type Services map[string]Context
type ContextState interface{} type ContextState interface{}
type Context interface { type Context interface {
stdlib_context.Context
Config() Config Config() Config
Parent() Context Parent() Context
Services() Services Services() Services
@ -23,8 +28,8 @@ type Context interface {
State() ContextState State() ContextState
WithState(ContextState) Context WithState(ContextState) Context
Mailbox() chan Message Mailbox() chan Message
Done() chan struct{}
WaitGroup() *sync.WaitGroup WaitGroup() *sync.WaitGroup
Stop()
} }
type FctCtx = func(Context) type FctCtx = func(Context)
@ -87,10 +92,14 @@ func (ctx *context) WaitGroup() *sync.WaitGroup {
return ctx.parent.WaitGroup() return ctx.parent.WaitGroup()
} }
func (ctx *context) Done() chan struct{} { func (ctx *context) Done() <-chan struct{} {
return ctx.parent.Done() return ctx.parent.Done()
} }
func (ctx *context) Stop() {
// ctx.Warn("Only application-level service can be stopped
}
func makeCtx(cfg Config, parent Context) *context { func makeCtx(cfg Config, parent Context) *context {
return &context{ return &context{
cfg: cfg, cfg: cfg,
@ -128,10 +137,14 @@ func (ctx *appContext) WaitGroup() *sync.WaitGroup {
return ctx.waitgroup return ctx.waitgroup
} }
func (ctx *appContext) Done() chan struct{} { func (ctx *appContext) Done() <-chan struct{} {
return ctx.doneCh return ctx.doneCh
} }
func (ctx *appContext) Stop() {
close(ctx.doneCh)
}
func AppContext(cfg Config) Context { func AppContext(cfg Config) Context {
ctx := &appContext{ ctx := &appContext{
context: makeCtx(cfg, nil), context: makeCtx(cfg, nil),
@ -142,3 +155,25 @@ func AppContext(cfg Config) Context {
ctx.services[cfg.Name()] = ctx ctx.services[cfg.Name()] = ctx
return ctx return ctx
} }
// implement interface context.Context from standard library
func (ctx *context) Deadline() (deadline time.Time, ok bool) {
return time.Time{}, false
}
func (ctx *context) Err() error {
select {
case _, ok := <-ctx.Done():
if !ok {
return stdlib_context.Canceled
}
default:
return nil
}
return nil
}
func (ctx *context) Value(key interface{}) interface{} {
return nil
}

View file

@ -21,7 +21,7 @@ func Start(ctx common.Context) {
} }
func start(ctx common.Context) { func start(ctx common.Context) {
defer close(ctx.Done()) defer ctx.Stop()
for _, cfg := range ctx.Config().Children() { for _, cfg := range ctx.Config().Children() {
cctx := ctx.ChildContext(cfg) cctx := ctx.ChildContext(cfg)
cfg.Starter()(cctx) cfg.Starter()(cctx)