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 {
|
||||
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
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 (
|
||||
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
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Reference in a new issue