From 0f0ed437d93d0dc2ff817351f288dc9b959a43b8 Mon Sep 17 00:00:00 2001 From: Helmut Merz Date: Sat, 3 Jun 2023 14:49:35 +0200 Subject: [PATCH] work in progress: use go routines for app (and testing) --- common/common.go | 56 +++++++++++++++++++++++++++++++++++++------- scopes.go | 35 +++++++++++++++++++++++++++ testing/testing.go | 19 ++++++++++++++- tests/scopes_test.go | 8 +++++++ 4 files changed, 109 insertions(+), 9 deletions(-) diff --git a/common/common.go b/common/common.go index 78eeb81..22ab41c 100644 --- a/common/common.go +++ b/common/common.go @@ -1,5 +1,7 @@ package common +import "sync" + type Config interface { Name() string Starter() StartFct @@ -7,6 +9,8 @@ type Config interface { Add(Config) } +type Message interface{} + type Services map[string]Context type ContextState interface{} @@ -18,6 +22,9 @@ type Context interface { ChildContext(Config) Context State() ContextState WithState(ContextState) Context + Mailbox() chan Message + Done() chan struct{} + WaitGroup() *sync.WaitGroup } type StartFct = func(Context) @@ -29,6 +36,7 @@ type context struct { parent Context children []Context state ContextState + mailbox chan Message } func (ctx *context) Config() Config { @@ -59,10 +67,23 @@ func (ctx *context) WithState(state ContextState) Context { 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 { return &context{ - cfg: cfg, - parent: parent, + cfg: cfg, + parent: parent, + mailbox: make(chan Message, 10), } } @@ -70,7 +91,9 @@ func makeCtx(cfg Config, parent Context) *context { type appContext struct { *context - services Services + services Services + waitgroup *sync.WaitGroup + doneCh chan struct{} } func (ctx *appContext) ChildContext(cfg Config) Context { @@ -84,9 +107,26 @@ func (ctx *appContext) Services() Services { return ctx.services } -func AppContext(cfg Config) Context { - return &appContext{ - context: makeCtx(cfg, nil), - services: 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 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 } diff --git a/scopes.go b/scopes.go index 7a27e0f..b864a4c 100644 --- a/scopes.go +++ b/scopes.go @@ -1,6 +1,11 @@ package scopes import ( + "fmt" + "os" + "os/signal" + "syscall" + "git.sr.ht/~cco/go-scopes/common" "git.sr.ht/~cco/go-scopes/config" ) @@ -15,7 +20,37 @@ func Start(ctx common.Context) { for _, cfg := range ctx.Config().Children() { cctx := ctx.ChildContext(cfg) 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 diff --git a/testing/testing.go b/testing/testing.go index 826c7d4..87510fd 100644 --- a/testing/testing.go +++ b/testing/testing.go @@ -3,15 +3,22 @@ package testing import ( + "fmt" "regexp" "testing" + "time" "git.sr.ht/~cco/go-scopes" "git.sr.ht/~cco/go-scopes/common" ) 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 @@ -41,6 +48,16 @@ func SetUpApp(tbase *testing.T, cfg common.Config) *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 func (t *T) Run(name string, f func(*T)) bool { diff --git a/tests/scopes_test.go b/tests/scopes_test.go index 4adedf6..97ed977 100644 --- a/tests/scopes_test.go +++ b/tests/scopes_test.go @@ -1,6 +1,7 @@ package scopes_test import ( + "fmt" tbase "testing" "git.sr.ht/~cco/go-scopes" @@ -10,7 +11,14 @@ import ( func TestConfig(tb *tbase.T) { t := testing.SetUpApp(tb, etc.Config()) + t.Run("testing", TestingTest) t.Run("config", ConfigTest) + t.TearDownApp() +} + +func TestingTest(t *testing.T) { + ctx := t.Ctx + fmt.Println(ctx.Services()) } func ConfigTest(t *testing.T) {