From 34ee4641dcd7af5c4c327822b343c9905664f3b5 Mon Sep 17 00:00:00 2001 From: Helmut Merz Date: Sun, 4 Jun 2023 12:51:50 +0200 Subject: [PATCH] move Context implementations to lib/context sub-package --- config/config.go | 6 +- lib/context/context.go | 143 +++++++++++++++++++++++++++++++++++++++++ lib/lib.go | 142 ++-------------------------------------- scopes.go | 7 +- testing/testing.go | 3 +- 5 files changed, 157 insertions(+), 144 deletions(-) create mode 100644 lib/context/context.go diff --git a/config/config.go b/config/config.go index 461c0f9..85c6cec 100644 --- a/config/config.go +++ b/config/config.go @@ -19,7 +19,7 @@ func Start(ctx lib.Context) { type Base struct { name string - starter lib.StartFct + starter lib.StartProc children []lib.Config } @@ -27,7 +27,7 @@ func (cfg *Base) Name() string { return cfg.name } -func (cfg *Base) Starter() lib.StartFct { +func (cfg *Base) Starter() lib.StartProc { return cfg.starter } @@ -39,7 +39,7 @@ func (cfg *Base) Add(child lib.Config) { cfg.children = append(cfg.children, child) } -func MakeBase(name string, starter lib.StartFct) *Base { +func MakeBase(name string, starter lib.StartProc) *Base { return &Base{ name: name, starter: starter, diff --git a/lib/context/context.go b/lib/context/context.go new file mode 100644 index 0000000..efcd562 --- /dev/null +++ b/lib/context/context.go @@ -0,0 +1,143 @@ +package context + +import ( + stdlib_context "context" + "sync" + "time" + + "git.sr.ht/~cco/go-scopes/lib" +) + +type Context = lib.Context +type ContextState = lib.ContextState +type Services = lib.Services + +type context struct { + cfg lib.Config + parent Context + children []Context + state ContextState + mailbox chan lib.Message +} + +func (ctx *context) Config() lib.Config { + return ctx.cfg +} + +func (ctx *context) Parent() Context { + return ctx.parent +} + +func (ctx *context) Services() Services { + return ctx.parent.Services() +} + +func (ctx *context) ChildContext(cfg lib.Config) Context { + cctx := makeCtx(cfg, ctx) + ctx.Services()[cfg.Name()] = cctx + ctx.children = append(ctx.children, cctx) + return cctx +} + +func (ctx *context) State() ContextState { + return ctx.state +} + +func (ctx *context) WithState(state ContextState) Context { + ctx.state = state + return ctx +} + +func (ctx *context) Mailbox() chan lib.Message { + return ctx.mailbox +} + +func (ctx *context) WaitGroup() *sync.WaitGroup { + return ctx.parent.WaitGroup() +} + +func (ctx *context) Done() <-chan struct{} { + return ctx.parent.Done() +} + +func (ctx *context) Stop() { + // ctx.Warn("Only application-level service can be stopped +} + +func makeCtx(cfg lib.Config, parent Context) *context { + return &context{ + cfg: cfg, + parent: parent, + mailbox: make(chan lib.Message, 10), + } +} + +// top-level application context + +type appContext struct { + *context + services Services + waitgroup *sync.WaitGroup + doneCh chan struct{} +} + +func (ctx *appContext) ChildContext(cfg lib.Config) Context { + cctx := makeCtx(cfg, ctx) + ctx.services[cfg.Name()] = cctx + ctx.children = append(ctx.children, cctx) + return cctx +} + +func (ctx *appContext) Services() Services { + return ctx.services +} + +func (ctx *appContext) WithState(state ContextState) Context { + ctx.state = state + return ctx +} + +func (ctx *appContext) WaitGroup() *sync.WaitGroup { + return ctx.waitgroup +} + +func (ctx *appContext) Done() <-chan struct{} { + return ctx.doneCh +} + +func (ctx *appContext) Stop() { + close(ctx.doneCh) +} + +func AppContext(cfg lib.Config) Context { + ctx := &appContext{ + context: makeCtx(cfg, nil), + services: Services{}, + waitgroup: &sync.WaitGroup{}, + doneCh: make(chan struct{}), + } + ctx.services[cfg.Name()] = 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 +} diff --git a/lib/lib.go b/lib/lib.go index d8032c7..8f302ce 100644 --- a/lib/lib.go +++ b/lib/lib.go @@ -3,12 +3,11 @@ package lib import ( stdlib_context "context" "sync" - "time" ) type Config interface { Name() string - Starter() StartFct + Starter() StartProc Children() []Config Add(Config) } @@ -32,148 +31,15 @@ type Context interface { Stop() } -type FctCtx = func(Context) - -type StartFct = FctCtx +type Proc = func(Context) +type StartProc = Proc // async Runners -func RunCtx(ctx Context, fct FctCtx) { +func RunCtx(ctx Context, fct Proc) { ctx.WaitGroup().Add(1) go func() { defer ctx.WaitGroup().Done() fct(ctx) }() } - -// Context implementation - -type context struct { - cfg Config - parent Context - children []Context - state ContextState - mailbox chan Message -} - -func (ctx *context) Config() Config { - return ctx.cfg -} - -func (ctx *context) Parent() Context { - return ctx.parent -} - -func (ctx *context) Services() Services { - return ctx.parent.Services() -} - -func (ctx *context) ChildContext(cfg Config) Context { - cctx := makeCtx(cfg, ctx) - ctx.Services()[cfg.Name()] = cctx - ctx.children = append(ctx.children, cctx) - return cctx -} - -func (ctx *context) State() ContextState { - return ctx.state -} - -func (ctx *context) WithState(state ContextState) Context { - ctx.state = state - return ctx -} - -func (ctx *context) Mailbox() chan Message { - return ctx.mailbox -} - -func (ctx *context) WaitGroup() *sync.WaitGroup { - return ctx.parent.WaitGroup() -} - -func (ctx *context) Done() <-chan struct{} { - return ctx.parent.Done() -} - -func (ctx *context) Stop() { - // ctx.Warn("Only application-level service can be stopped -} - -func makeCtx(cfg Config, parent Context) *context { - return &context{ - cfg: cfg, - parent: parent, - mailbox: make(chan Message, 10), - } -} - -// top-level application context - -type appContext struct { - *context - services Services - waitgroup *sync.WaitGroup - doneCh chan struct{} -} - -func (ctx *appContext) ChildContext(cfg Config) Context { - cctx := makeCtx(cfg, ctx) - ctx.services[cfg.Name()] = cctx - ctx.children = append(ctx.children, cctx) - return cctx -} - -func (ctx *appContext) Services() Services { - return ctx.services -} - -func (ctx *appContext) WithState(state ContextState) Context { - ctx.state = state - return ctx -} - -func (ctx *appContext) WaitGroup() *sync.WaitGroup { - return ctx.waitgroup -} - -func (ctx *appContext) Done() <-chan struct{} { - return ctx.doneCh -} - -func (ctx *appContext) Stop() { - close(ctx.doneCh) -} - -func AppContext(cfg Config) Context { - ctx := &appContext{ - context: makeCtx(cfg, nil), - services: Services{}, - waitgroup: &sync.WaitGroup{}, - doneCh: make(chan struct{}), - } - ctx.services[cfg.Name()] = 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 -} diff --git a/scopes.go b/scopes.go index 491b420..02fa95a 100644 --- a/scopes.go +++ b/scopes.go @@ -1,9 +1,12 @@ package scopes -import "git.sr.ht/~cco/go-scopes/lib" +import ( + "git.sr.ht/~cco/go-scopes/lib" + "git.sr.ht/~cco/go-scopes/lib/context" +) func RunApp(cfg lib.Config) { - ctx := lib.AppContext(cfg) + ctx := context.AppContext(cfg) cfg.Starter()(ctx) ctx.WaitGroup().Wait() } diff --git a/testing/testing.go b/testing/testing.go index a297a91..39105cc 100644 --- a/testing/testing.go +++ b/testing/testing.go @@ -10,6 +10,7 @@ import ( "git.sr.ht/~cco/go-scopes/app" "git.sr.ht/~cco/go-scopes/lib" + "git.sr.ht/~cco/go-scopes/lib/context" ) func Start(ctx lib.Context) { @@ -38,7 +39,7 @@ func SetUp(tbase *testing.T) *T { func SetUpApp(tbase *testing.T, cfg lib.Config) *T { t := SetUp(tbase) - t.Ctx = lib.AppContext(cfg) + t.Ctx = context.AppContext(cfg) cfg.Starter()(t.Ctx) time.Sleep(100 * time.Millisecond) return t