move Context implementations to lib/context sub-package
This commit is contained in:
parent
aec3446d75
commit
34ee4641dc
5 changed files with 157 additions and 144 deletions
|
@ -19,7 +19,7 @@ func Start(ctx lib.Context) {
|
||||||
|
|
||||||
type Base struct {
|
type Base struct {
|
||||||
name string
|
name string
|
||||||
starter lib.StartFct
|
starter lib.StartProc
|
||||||
children []lib.Config
|
children []lib.Config
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@ func (cfg *Base) Name() string {
|
||||||
return cfg.name
|
return cfg.name
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cfg *Base) Starter() lib.StartFct {
|
func (cfg *Base) Starter() lib.StartProc {
|
||||||
return cfg.starter
|
return cfg.starter
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,7 +39,7 @@ func (cfg *Base) Add(child lib.Config) {
|
||||||
cfg.children = append(cfg.children, child)
|
cfg.children = append(cfg.children, child)
|
||||||
}
|
}
|
||||||
|
|
||||||
func MakeBase(name string, starter lib.StartFct) *Base {
|
func MakeBase(name string, starter lib.StartProc) *Base {
|
||||||
return &Base{
|
return &Base{
|
||||||
name: name,
|
name: name,
|
||||||
starter: starter,
|
starter: starter,
|
||||||
|
|
143
lib/context/context.go
Normal file
143
lib/context/context.go
Normal 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
|
||||||
|
}
|
142
lib/lib.go
142
lib/lib.go
|
@ -3,12 +3,11 @@ package lib
|
||||||
import (
|
import (
|
||||||
stdlib_context "context"
|
stdlib_context "context"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Config interface {
|
type Config interface {
|
||||||
Name() string
|
Name() string
|
||||||
Starter() StartFct
|
Starter() StartProc
|
||||||
Children() []Config
|
Children() []Config
|
||||||
Add(Config)
|
Add(Config)
|
||||||
}
|
}
|
||||||
|
@ -32,148 +31,15 @@ type Context interface {
|
||||||
Stop()
|
Stop()
|
||||||
}
|
}
|
||||||
|
|
||||||
type FctCtx = func(Context)
|
type Proc = func(Context)
|
||||||
|
type StartProc = Proc
|
||||||
type StartFct = FctCtx
|
|
||||||
|
|
||||||
// async Runners
|
// async Runners
|
||||||
|
|
||||||
func RunCtx(ctx Context, fct FctCtx) {
|
func RunCtx(ctx Context, fct Proc) {
|
||||||
ctx.WaitGroup().Add(1)
|
ctx.WaitGroup().Add(1)
|
||||||
go func() {
|
go func() {
|
||||||
defer ctx.WaitGroup().Done()
|
defer ctx.WaitGroup().Done()
|
||||||
fct(ctx)
|
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
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,9 +1,12 @@
|
||||||
package scopes
|
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) {
|
func RunApp(cfg lib.Config) {
|
||||||
ctx := lib.AppContext(cfg)
|
ctx := context.AppContext(cfg)
|
||||||
cfg.Starter()(ctx)
|
cfg.Starter()(ctx)
|
||||||
ctx.WaitGroup().Wait()
|
ctx.WaitGroup().Wait()
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@ import (
|
||||||
|
|
||||||
"git.sr.ht/~cco/go-scopes/app"
|
"git.sr.ht/~cco/go-scopes/app"
|
||||||
"git.sr.ht/~cco/go-scopes/lib"
|
"git.sr.ht/~cco/go-scopes/lib"
|
||||||
|
"git.sr.ht/~cco/go-scopes/lib/context"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Start(ctx 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 {
|
func SetUpApp(tbase *testing.T, cfg lib.Config) *T {
|
||||||
t := SetUp(tbase)
|
t := SetUp(tbase)
|
||||||
t.Ctx = lib.AppContext(cfg)
|
t.Ctx = context.AppContext(cfg)
|
||||||
cfg.Starter()(t.Ctx)
|
cfg.Starter()(t.Ctx)
|
||||||
time.Sleep(100 * time.Millisecond)
|
time.Sleep(100 * time.Millisecond)
|
||||||
return t
|
return t
|
||||||
|
|
Loading…
Add table
Reference in a new issue