move Context implementations to lib/context sub-package

This commit is contained in:
Helmut Merz 2023-06-04 12:51:50 +02:00
parent aec3446d75
commit 34ee4641dc
5 changed files with 157 additions and 144 deletions

View file

@ -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,

143
lib/context/context.go Normal file
View file

@ -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
}

View file

@ -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
}

View file

@ -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()
}

View file

@ -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