work in progress: use go routines for app (and testing)

This commit is contained in:
Helmut Merz 2023-06-03 14:49:35 +02:00
parent 92cefca3cb
commit 0f0ed437d9
4 changed files with 109 additions and 9 deletions

View file

@ -1,5 +1,7 @@
package common package common
import "sync"
type Config interface { type Config interface {
Name() string Name() string
Starter() StartFct Starter() StartFct
@ -7,6 +9,8 @@ type Config interface {
Add(Config) Add(Config)
} }
type Message interface{}
type Services map[string]Context type Services map[string]Context
type ContextState interface{} type ContextState interface{}
@ -18,6 +22,9 @@ type Context interface {
ChildContext(Config) Context ChildContext(Config) Context
State() ContextState State() ContextState
WithState(ContextState) Context WithState(ContextState) Context
Mailbox() chan Message
Done() chan struct{}
WaitGroup() *sync.WaitGroup
} }
type StartFct = func(Context) type StartFct = func(Context)
@ -29,6 +36,7 @@ type context struct {
parent Context parent Context
children []Context children []Context
state ContextState state ContextState
mailbox chan Message
} }
func (ctx *context) Config() Config { func (ctx *context) Config() Config {
@ -59,10 +67,23 @@ func (ctx *context) WithState(state ContextState) Context {
return ctx 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 makeCtx(cfg Config, parent Context) *context { func makeCtx(cfg Config, parent Context) *context {
return &context{ return &context{
cfg: cfg, cfg: cfg,
parent: parent, parent: parent,
mailbox: make(chan Message, 10),
} }
} }
@ -70,7 +91,9 @@ func makeCtx(cfg Config, parent Context) *context {
type appContext struct { type appContext struct {
*context *context
services Services services Services
waitgroup *sync.WaitGroup
doneCh chan struct{}
} }
func (ctx *appContext) ChildContext(cfg Config) Context { func (ctx *appContext) ChildContext(cfg Config) Context {
@ -84,9 +107,26 @@ func (ctx *appContext) Services() Services {
return ctx.services return ctx.services
} }
func AppContext(cfg Config) Context { func (ctx *appContext) WithState(state ContextState) Context {
return &appContext{ ctx.state = state
context: makeCtx(cfg, nil), return ctx
services: Services{}, }
}
func (ctx *appContext) WaitGroup() *sync.WaitGroup {
return ctx.waitgroup
}
func (ctx *appContext) Done() chan struct{} {
return 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
} }

View file

@ -1,6 +1,11 @@
package scopes package scopes
import ( import (
"fmt"
"os"
"os/signal"
"syscall"
"git.sr.ht/~cco/go-scopes/common" "git.sr.ht/~cco/go-scopes/common"
"git.sr.ht/~cco/go-scopes/config" "git.sr.ht/~cco/go-scopes/config"
) )
@ -15,7 +20,37 @@ func Start(ctx common.Context) {
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)
fmt.Println(cfg.Name(), " started")
} }
fmt.Println("running ", ctx.WaitGroup())
defer func() {
close(ctx.Done())
ctx.WaitGroup().Wait()
fmt.Println("finishing ", ctx.WaitGroup())
//ctx.LogDebug("Dispatcher exited", m.Map{})
}()
sig := make(chan os.Signal, 1)
signal.Notify(sig, syscall.SIGINT, syscall.SIGTERM)
for step(ctx, sig) {
}
}
func step(ctx common.Context, sig <-chan os.Signal) bool {
select {
case <-sig:
fmt.Println("interrupted")
//ctx.LogInfo("Dispatcher interrupted", m.Map{})
return false
case msg := <-ctx.Mailbox():
fmt.Println("message", msg)
//ctx.LogDebug("dispatcherStep", m.Map{"msg": msg})
if msg == "quit" {
//ctx.LogInfo("Dispatcher stopped", m.Map{})
return false
}
//ctx.HandleMsg(&msg)
}
return true
} }
// definitions // definitions

View file

@ -3,15 +3,22 @@
package testing package testing
import ( import (
"fmt"
"regexp" "regexp"
"testing" "testing"
"time"
"git.sr.ht/~cco/go-scopes" "git.sr.ht/~cco/go-scopes"
"git.sr.ht/~cco/go-scopes/common" "git.sr.ht/~cco/go-scopes/common"
) )
func Start(ctx common.Context) { func Start(ctx common.Context) {
scopes.Start(ctx) ctx.WaitGroup().Add(1)
go func() {
scopes.Start(ctx)
ctx.WaitGroup().Done()
}()
time.Sleep(100 * time.Millisecond)
} }
// definitions // definitions
@ -41,6 +48,16 @@ func SetUpApp(tbase *testing.T, cfg common.Config) *T {
return t return t
} }
func (t *T) TearDownApp() {
// give actors time to recieve all messages:
time.Sleep(100 * time.Millisecond)
//t.Check()
t.Ctx.Services()["testing"].Mailbox() <- "quit"
fmt.Println("teardown ", t.Ctx.WaitGroup())
//t.Ctx.WaitGroup().Wait()
//t.AssertNoUncheckedMessages()
}
// testing methods // testing methods
func (t *T) Run(name string, f func(*T)) bool { func (t *T) Run(name string, f func(*T)) bool {

View file

@ -1,6 +1,7 @@
package scopes_test package scopes_test
import ( import (
"fmt"
tbase "testing" tbase "testing"
"git.sr.ht/~cco/go-scopes" "git.sr.ht/~cco/go-scopes"
@ -10,7 +11,14 @@ import (
func TestConfig(tb *tbase.T) { func TestConfig(tb *tbase.T) {
t := testing.SetUpApp(tb, etc.Config()) t := testing.SetUpApp(tb, etc.Config())
t.Run("testing", TestingTest)
t.Run("config", ConfigTest) t.Run("config", ConfigTest)
t.TearDownApp()
}
func TestingTest(t *testing.T) {
ctx := t.Ctx
fmt.Println(ctx.Services())
} }
func ConfigTest(t *testing.T) { func ConfigTest(t *testing.T) {