From 79bd5e6ccc2d4c0719a1137dbf99983e8aa65eea Mon Sep 17 00:00:00 2001 From: Arye Kogan Date: Thu, 5 Feb 2026 12:35:42 +0200 Subject: [PATCH 1/9] 143: track provider initialization order for io.Closer --- modkit/kernel/bootstrap.go | 6 ++++ modkit/kernel/container.go | 15 +++++++++ modkit/kernel/container_test.go | 58 +++++++++++++++++++++++++++++++++ 3 files changed, 79 insertions(+) diff --git a/modkit/kernel/bootstrap.go b/modkit/kernel/bootstrap.go index cfd19f9..176170d 100644 --- a/modkit/kernel/bootstrap.go +++ b/modkit/kernel/bootstrap.go @@ -2,6 +2,7 @@ package kernel import ( "context" + "io" "github.com/go-modkit/modkit/modkit/module" ) @@ -73,3 +74,8 @@ func (a *App) Get(token module.Token) (any, error) { func (a *App) CleanupHooks() []func(context.Context) error { return a.container.cleanupHooksLIFO() } + +// Closers returns provider closers in build order. +func (a *App) Closers() []io.Closer { + return a.container.closersInBuildOrder() +} diff --git a/modkit/kernel/container.go b/modkit/kernel/container.go index ea6603d..64b7fa4 100644 --- a/modkit/kernel/container.go +++ b/modkit/kernel/container.go @@ -2,6 +2,7 @@ package kernel import ( "context" + "io" "sync" "github.com/go-modkit/modkit/modkit/module" @@ -20,6 +21,7 @@ type Container struct { locks map[module.Token]*sync.Mutex waitingOn map[module.Token]module.Token cleanupHooks []func(context.Context) error + closers []io.Closer mu sync.Mutex } @@ -48,6 +50,7 @@ func newContainer(graph *Graph, visibility Visibility) (*Container, error) { locks: make(map[module.Token]*sync.Mutex), waitingOn: make(map[module.Token]module.Token), cleanupHooks: make([]func(context.Context) error, 0), + closers: make([]io.Closer, 0), }, nil } @@ -110,6 +113,9 @@ func (c *Container) getWithStack(token module.Token, requester string, stack []m if entry.cleanup != nil { c.cleanupHooks = append(c.cleanupHooks, entry.cleanup) } + if closer, ok := instance.(io.Closer); ok { + c.closers = append(c.closers, closer) + } c.mu.Unlock() return instance, nil } @@ -125,6 +131,15 @@ func (c *Container) cleanupHooksLIFO() []func(context.Context) error { return hooks } +func (c *Container) closersInBuildOrder() []io.Closer { + c.mu.Lock() + defer c.mu.Unlock() + + closers := make([]io.Closer, len(c.closers)) + copy(closers, c.closers) + return closers +} + type moduleResolver struct { container *Container moduleName string diff --git a/modkit/kernel/container_test.go b/modkit/kernel/container_test.go index b6fbb72..92e6dff 100644 --- a/modkit/kernel/container_test.go +++ b/modkit/kernel/container_test.go @@ -379,3 +379,61 @@ func TestContainerGetRegistersCleanupHooks(t *testing.T) { t.Fatalf("expected cleanup to be called") } } + +func TestContainerRecordsClosersInBuildOrder(t *testing.T) { + closerA := module.Token("closer.a") + closerB := module.Token("closer.b") + + modA := mod("A", nil, + []module.ProviderDef{{ + Token: closerA, + Build: func(r module.Resolver) (any, error) { + return &testCloser{name: "a"}, nil + }, + }, { + Token: closerB, + Build: func(r module.Resolver) (any, error) { + return &testCloser{name: "b"}, nil + }, + }}, + nil, + nil, + ) + + app, err := kernel.Bootstrap(modA) + if err != nil { + t.Fatalf("Bootstrap failed: %v", err) + } + + _, _ = app.Get(closerA) + _, _ = app.Get(closerB) + + closers := app.Closers() + if len(closers) != 2 { + t.Fatalf("expected 2 closers, got %d", len(closers)) + } + + first, ok := closers[0].(*testCloser) + if !ok { + t.Fatalf("expected *testCloser, got %T", closers[0]) + } + second, ok := closers[1].(*testCloser) + if !ok { + t.Fatalf("expected *testCloser, got %T", closers[1]) + } + if first.Name() != "a" || second.Name() != "b" { + t.Fatalf("unexpected order: %v", closers) + } +} + +type testCloser struct { + name string +} + +func (c *testCloser) Close() error { + return nil +} + +func (c *testCloser) Name() string { + return c.name +} From 3b33bd504912df8a78a7815bb2bfb04bd86c3feb Mon Sep 17 00:00:00 2001 From: Arye Kogan Date: Thu, 5 Feb 2026 12:38:32 +0200 Subject: [PATCH 2/9] 143: track provider initialization order for io.Closer --- modkit/kernel/container.go | 12 ++++ modkit/kernel/container_internal_test.go | 70 ++++++++++++++++++++++++ 2 files changed, 82 insertions(+) create mode 100644 modkit/kernel/container_internal_test.go diff --git a/modkit/kernel/container.go b/modkit/kernel/container.go index 64b7fa4..2ed1232 100644 --- a/modkit/kernel/container.go +++ b/modkit/kernel/container.go @@ -22,6 +22,7 @@ type Container struct { waitingOn map[module.Token]module.Token cleanupHooks []func(context.Context) error closers []io.Closer + buildOrder []module.Token mu sync.Mutex } @@ -51,6 +52,7 @@ func newContainer(graph *Graph, visibility Visibility) (*Container, error) { waitingOn: make(map[module.Token]module.Token), cleanupHooks: make([]func(context.Context) error, 0), closers: make([]io.Closer, 0), + buildOrder: make([]module.Token, 0), }, nil } @@ -116,6 +118,7 @@ func (c *Container) getWithStack(token module.Token, requester string, stack []m if closer, ok := instance.(io.Closer); ok { c.closers = append(c.closers, closer) } + c.buildOrder = append(c.buildOrder, token) c.mu.Unlock() return instance, nil } @@ -140,6 +143,15 @@ func (c *Container) closersInBuildOrder() []io.Closer { return closers } +func (c *Container) providerBuildOrder() []module.Token { + c.mu.Lock() + defer c.mu.Unlock() + + order := make([]module.Token, len(c.buildOrder)) + copy(order, c.buildOrder) + return order +} + type moduleResolver struct { container *Container moduleName string diff --git a/modkit/kernel/container_internal_test.go b/modkit/kernel/container_internal_test.go new file mode 100644 index 0000000..80c70a0 --- /dev/null +++ b/modkit/kernel/container_internal_test.go @@ -0,0 +1,70 @@ +package kernel + +import ( + "testing" + + "github.com/go-modkit/modkit/modkit/module" +) + +type modHelperInternal struct { + def module.ModuleDef +} + +func (m *modHelperInternal) Definition() module.ModuleDef { + return m.def +} + +func modInternal( + name string, + imports []module.Module, + providers []module.ProviderDef, + controllers []module.ControllerDef, + exports []module.Token, +) module.Module { + return &modHelperInternal{ + def: module.ModuleDef{ + Name: name, + Imports: imports, + Providers: providers, + Controllers: controllers, + Exports: exports, + }, + } +} + +func TestContainerRecordsProviderBuildOrder(t *testing.T) { + first := module.Token("provider.first") + second := module.Token("provider.second") + + modA := modInternal("A", nil, + []module.ProviderDef{{ + Token: first, + Build: func(r module.Resolver) (any, error) { + return "first", nil + }, + }, { + Token: second, + Build: func(r module.Resolver) (any, error) { + return "second", nil + }, + }}, + nil, + nil, + ) + + app, err := Bootstrap(modA) + if err != nil { + t.Fatalf("Bootstrap failed: %v", err) + } + + _, _ = app.Get(second) + _, _ = app.Get(first) + + order := app.container.providerBuildOrder() + if len(order) != 2 { + t.Fatalf("expected 2 providers, got %d", len(order)) + } + if order[0] != second || order[1] != first { + t.Fatalf("unexpected order: %v", order) + } +} From 62969c9e632dc9de72ee3cebd499dc9f1790f1ce Mon Sep 17 00:00:00 2001 From: Arye Kogan Date: Thu, 5 Feb 2026 12:44:26 +0200 Subject: [PATCH 3/9] 143: keep closer tests internal --- modkit/kernel/bootstrap.go | 5 -- modkit/kernel/container_internal_test.go | 58 ++++++++++++++++++++++++ modkit/kernel/container_test.go | 57 ----------------------- 3 files changed, 58 insertions(+), 62 deletions(-) diff --git a/modkit/kernel/bootstrap.go b/modkit/kernel/bootstrap.go index 176170d..0982063 100644 --- a/modkit/kernel/bootstrap.go +++ b/modkit/kernel/bootstrap.go @@ -2,7 +2,6 @@ package kernel import ( "context" - "io" "github.com/go-modkit/modkit/modkit/module" ) @@ -75,7 +74,3 @@ func (a *App) CleanupHooks() []func(context.Context) error { return a.container.cleanupHooksLIFO() } -// Closers returns provider closers in build order. -func (a *App) Closers() []io.Closer { - return a.container.closersInBuildOrder() -} diff --git a/modkit/kernel/container_internal_test.go b/modkit/kernel/container_internal_test.go index 80c70a0..e60a581 100644 --- a/modkit/kernel/container_internal_test.go +++ b/modkit/kernel/container_internal_test.go @@ -68,3 +68,61 @@ func TestContainerRecordsProviderBuildOrder(t *testing.T) { t.Fatalf("unexpected order: %v", order) } } + +func TestContainerRecordsClosersInBuildOrder(t *testing.T) { + closerA := module.Token("closer.a") + closerB := module.Token("closer.b") + + modA := modInternal("A", nil, + []module.ProviderDef{{ + Token: closerA, + Build: func(r module.Resolver) (any, error) { + return &testCloser{name: "a"}, nil + }, + }, { + Token: closerB, + Build: func(r module.Resolver) (any, error) { + return &testCloser{name: "b"}, nil + }, + }}, + nil, + nil, + ) + + app, err := Bootstrap(modA) + if err != nil { + t.Fatalf("Bootstrap failed: %v", err) + } + + _, _ = app.Get(closerA) + _, _ = app.Get(closerB) + + closers := app.container.closersInBuildOrder() + if len(closers) != 2 { + t.Fatalf("expected 2 closers, got %d", len(closers)) + } + + first, ok := closers[0].(*testCloser) + if !ok { + t.Fatalf("expected *testCloser, got %T", closers[0]) + } + second, ok := closers[1].(*testCloser) + if !ok { + t.Fatalf("expected *testCloser, got %T", closers[1]) + } + if first.Name() != "a" || second.Name() != "b" { + t.Fatalf("unexpected order: %v", closers) + } +} + +type testCloser struct { + name string +} + +func (c *testCloser) Close() error { + return nil +} + +func (c *testCloser) Name() string { + return c.name +} diff --git a/modkit/kernel/container_test.go b/modkit/kernel/container_test.go index 92e6dff..ffcd68f 100644 --- a/modkit/kernel/container_test.go +++ b/modkit/kernel/container_test.go @@ -380,60 +380,3 @@ func TestContainerGetRegistersCleanupHooks(t *testing.T) { } } -func TestContainerRecordsClosersInBuildOrder(t *testing.T) { - closerA := module.Token("closer.a") - closerB := module.Token("closer.b") - - modA := mod("A", nil, - []module.ProviderDef{{ - Token: closerA, - Build: func(r module.Resolver) (any, error) { - return &testCloser{name: "a"}, nil - }, - }, { - Token: closerB, - Build: func(r module.Resolver) (any, error) { - return &testCloser{name: "b"}, nil - }, - }}, - nil, - nil, - ) - - app, err := kernel.Bootstrap(modA) - if err != nil { - t.Fatalf("Bootstrap failed: %v", err) - } - - _, _ = app.Get(closerA) - _, _ = app.Get(closerB) - - closers := app.Closers() - if len(closers) != 2 { - t.Fatalf("expected 2 closers, got %d", len(closers)) - } - - first, ok := closers[0].(*testCloser) - if !ok { - t.Fatalf("expected *testCloser, got %T", closers[0]) - } - second, ok := closers[1].(*testCloser) - if !ok { - t.Fatalf("expected *testCloser, got %T", closers[1]) - } - if first.Name() != "a" || second.Name() != "b" { - t.Fatalf("unexpected order: %v", closers) - } -} - -type testCloser struct { - name string -} - -func (c *testCloser) Close() error { - return nil -} - -func (c *testCloser) Name() string { - return c.name -} From 518e48ff2b48b92885746375846bff7b86dae2db Mon Sep 17 00:00:00 2001 From: Arye Kogan Date: Thu, 5 Feb 2026 12:50:04 +0200 Subject: [PATCH 4/9] 144: add App.Close with reverse-order closing --- modkit/kernel/bootstrap.go | 9 +++++++ modkit/kernel/container.go | 11 +++++++++ modkit/kernel/container_test.go | 44 +++++++++++++++++++++++++++++++++ 3 files changed, 64 insertions(+) diff --git a/modkit/kernel/bootstrap.go b/modkit/kernel/bootstrap.go index 0982063..d0f94ea 100644 --- a/modkit/kernel/bootstrap.go +++ b/modkit/kernel/bootstrap.go @@ -74,3 +74,12 @@ func (a *App) CleanupHooks() []func(context.Context) error { return a.container.cleanupHooksLIFO() } +// Close calls Close on all io.Closer providers in reverse build order. +func (a *App) Close() error { + for _, closer := range a.container.closersLIFO() { + if err := closer.Close(); err != nil { + return err + } + } + return nil +} diff --git a/modkit/kernel/container.go b/modkit/kernel/container.go index 2ed1232..36c705e 100644 --- a/modkit/kernel/container.go +++ b/modkit/kernel/container.go @@ -134,6 +134,17 @@ func (c *Container) cleanupHooksLIFO() []func(context.Context) error { return hooks } +func (c *Container) closersLIFO() []io.Closer { + c.mu.Lock() + defer c.mu.Unlock() + + closers := make([]io.Closer, len(c.closers)) + for i, closer := range c.closers { + closers[len(c.closers)-1-i] = closer + } + return closers +} + func (c *Container) closersInBuildOrder() []io.Closer { c.mu.Lock() defer c.mu.Unlock() diff --git a/modkit/kernel/container_test.go b/modkit/kernel/container_test.go index ffcd68f..268275b 100644 --- a/modkit/kernel/container_test.go +++ b/modkit/kernel/container_test.go @@ -12,6 +12,16 @@ import ( "github.com/go-modkit/modkit/modkit/module" ) +type recordingCloser struct { + name string + closed *[]string +} + +func (c *recordingCloser) Close() error { + *c.closed = append(*c.closed, c.name) + return nil +} + func TestAppGetRejectsNotVisibleToken(t *testing.T) { modA := mod("A", nil, nil, nil, nil) @@ -380,3 +390,37 @@ func TestContainerGetRegistersCleanupHooks(t *testing.T) { } } +func TestAppCloseReverseOrder(t *testing.T) { + var closed []string + modA := mod("A", nil, + []module.ProviderDef{{ + Token: "closer.a", + Build: func(r module.Resolver) (any, error) { + return &recordingCloser{name: "a", closed: &closed}, nil + }, + }, { + Token: "closer.b", + Build: func(r module.Resolver) (any, error) { + return &recordingCloser{name: "b", closed: &closed}, nil + }, + }}, + nil, + nil, + ) + + app, err := kernel.Bootstrap(modA) + if err != nil { + t.Fatalf("Bootstrap failed: %v", err) + } + + _, _ = app.Get("closer.a") + _, _ = app.Get("closer.b") + + if err := app.Close(); err != nil { + t.Fatalf("Close failed: %v", err) + } + + if len(closed) != 2 || closed[0] != "b" || closed[1] != "a" { + t.Fatalf("expected reverse close order, got %v", closed) + } +} From 181d53ad32b84d93cf6e73745db414706335c248 Mon Sep 17 00:00:00 2001 From: Arye Kogan Date: Thu, 5 Feb 2026 12:53:25 +0200 Subject: [PATCH 5/9] 144: keep App.Closers alongside Close --- modkit/kernel/bootstrap.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/modkit/kernel/bootstrap.go b/modkit/kernel/bootstrap.go index d0f94ea..f308462 100644 --- a/modkit/kernel/bootstrap.go +++ b/modkit/kernel/bootstrap.go @@ -2,6 +2,7 @@ package kernel import ( "context" + "io" "github.com/go-modkit/modkit/modkit/module" ) @@ -74,6 +75,11 @@ func (a *App) CleanupHooks() []func(context.Context) error { return a.container.cleanupHooksLIFO() } +// Closers returns provider closers in build order. +func (a *App) Closers() []io.Closer { + return a.container.closersInBuildOrder() +} + // Close calls Close on all io.Closer providers in reverse build order. func (a *App) Close() error { for _, closer := range a.container.closersLIFO() { From 64663183f608de35f4aaf68709a55ad309e0f8a8 Mon Sep 17 00:00:00 2001 From: Arye Kogan Date: Thu, 5 Feb 2026 12:59:07 +0200 Subject: [PATCH 6/9] 144: close all providers and return first error --- modkit/kernel/bootstrap.go | 7 +++-- modkit/kernel/container_test.go | 53 +++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 3 deletions(-) diff --git a/modkit/kernel/bootstrap.go b/modkit/kernel/bootstrap.go index f308462..53cbb31 100644 --- a/modkit/kernel/bootstrap.go +++ b/modkit/kernel/bootstrap.go @@ -82,10 +82,11 @@ func (a *App) Closers() []io.Closer { // Close calls Close on all io.Closer providers in reverse build order. func (a *App) Close() error { + var firstErr error for _, closer := range a.container.closersLIFO() { - if err := closer.Close(); err != nil { - return err + if err := closer.Close(); err != nil && firstErr == nil { + firstErr = err } } - return nil + return firstErr } diff --git a/modkit/kernel/container_test.go b/modkit/kernel/container_test.go index 268275b..5454e6d 100644 --- a/modkit/kernel/container_test.go +++ b/modkit/kernel/container_test.go @@ -22,6 +22,17 @@ func (c *recordingCloser) Close() error { return nil } +type erroringCloser struct { + name string + closed *[]string + err error +} + +func (c *erroringCloser) Close() error { + *c.closed = append(*c.closed, c.name) + return c.err +} + func TestAppGetRejectsNotVisibleToken(t *testing.T) { modA := mod("A", nil, nil, nil, nil) @@ -424,3 +435,45 @@ func TestAppCloseReverseOrder(t *testing.T) { t.Fatalf("expected reverse close order, got %v", closed) } } + +func TestAppCloseContinuesAfterError(t *testing.T) { + var closed []string + errB := errors.New("close failed") + modA := mod("A", nil, + []module.ProviderDef{{ + Token: "closer.a", + Build: func(r module.Resolver) (any, error) { + return &recordingCloser{name: "a", closed: &closed}, nil + }, + }, { + Token: "closer.b", + Build: func(r module.Resolver) (any, error) { + return &erroringCloser{name: "b", closed: &closed, err: errB}, nil + }, + }, { + Token: "closer.c", + Build: func(r module.Resolver) (any, error) { + return &recordingCloser{name: "c", closed: &closed}, nil + }, + }}, + nil, + nil, + ) + + app, err := kernel.Bootstrap(modA) + if err != nil { + t.Fatalf("Bootstrap failed: %v", err) + } + + _, _ = app.Get("closer.a") + _, _ = app.Get("closer.b") + _, _ = app.Get("closer.c") + + if err := app.Close(); !errors.Is(err, errB) { + t.Fatalf("expected error %v, got %v", errB, err) + } + + if len(closed) != 3 || closed[0] != "c" || closed[1] != "b" || closed[2] != "a" { + t.Fatalf("expected reverse close order with all closers, got %v", closed) + } +} From 1c55862f4b9eb43a6fe3536b9890f55c44005a2a Mon Sep 17 00:00:00 2001 From: Arye Kogan Date: Thu, 5 Feb 2026 13:02:44 +0200 Subject: [PATCH 7/9] 145: add close ordering unit tests --- modkit/kernel/container_test.go | 44 +++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/modkit/kernel/container_test.go b/modkit/kernel/container_test.go index 5454e6d..390b604 100644 --- a/modkit/kernel/container_test.go +++ b/modkit/kernel/container_test.go @@ -3,6 +3,7 @@ package kernel_test import ( "context" "errors" + "reflect" "sync" "sync/atomic" "testing" @@ -436,6 +437,49 @@ func TestAppCloseReverseOrder(t *testing.T) { } } +func TestAppCloseOrderWithDependencies(t *testing.T) { + var closed []string + + modA := mod("A", nil, + []module.ProviderDef{{ + Token: "closer.a", + Build: func(r module.Resolver) (any, error) { + return &recordingCloser{name: "a", closed: &closed}, nil + }, + }, { + Token: "closer.b", + Build: func(r module.Resolver) (any, error) { + _, _ = r.Get("closer.a") + return &recordingCloser{name: "b", closed: &closed}, nil + }, + }, { + Token: "closer.c", + Build: func(r module.Resolver) (any, error) { + _, _ = r.Get("closer.b") + return &recordingCloser{name: "c", closed: &closed}, nil + }, + }}, + nil, + nil, + ) + + app, err := kernel.Bootstrap(modA) + if err != nil { + t.Fatalf("Bootstrap failed: %v", err) + } + + _, _ = app.Get("closer.c") + + if err := app.Close(); err != nil { + t.Fatalf("Close failed: %v", err) + } + + want := []string{"c", "b", "a"} + if !reflect.DeepEqual(closed, want) { + t.Fatalf("expected %v, got %v", want, closed) + } +} + func TestAppCloseContinuesAfterError(t *testing.T) { var closed []string errB := errors.New("close failed") From 538dbfaa86ef250aef4c53e6a0129195c61d4de1 Mon Sep 17 00:00:00 2001 From: Arye Kogan Date: Thu, 5 Feb 2026 13:07:57 +0200 Subject: [PATCH 8/9] 145: tighten close order test errors --- modkit/kernel/container_test.go | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/modkit/kernel/container_test.go b/modkit/kernel/container_test.go index 390b604..6091a9e 100644 --- a/modkit/kernel/container_test.go +++ b/modkit/kernel/container_test.go @@ -449,13 +449,17 @@ func TestAppCloseOrderWithDependencies(t *testing.T) { }, { Token: "closer.b", Build: func(r module.Resolver) (any, error) { - _, _ = r.Get("closer.a") + if _, err := r.Get("closer.a"); err != nil { + return nil, err + } return &recordingCloser{name: "b", closed: &closed}, nil }, }, { Token: "closer.c", Build: func(r module.Resolver) (any, error) { - _, _ = r.Get("closer.b") + if _, err := r.Get("closer.b"); err != nil { + return nil, err + } return &recordingCloser{name: "c", closed: &closed}, nil }, }}, From f981ac3b35927e01efac263e8f0e4bf854f57ee0 Mon Sep 17 00:00:00 2001 From: Arye Kogan Date: Thu, 5 Feb 2026 13:18:48 +0200 Subject: [PATCH 9/9] test: check errors in shutdown setup --- modkit/kernel/container_internal_test.go | 8 ++++++-- modkit/kernel/container_test.go | 16 ++++++++++++---- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/modkit/kernel/container_internal_test.go b/modkit/kernel/container_internal_test.go index e60a581..2c2c767 100644 --- a/modkit/kernel/container_internal_test.go +++ b/modkit/kernel/container_internal_test.go @@ -57,8 +57,12 @@ func TestContainerRecordsProviderBuildOrder(t *testing.T) { t.Fatalf("Bootstrap failed: %v", err) } - _, _ = app.Get(second) - _, _ = app.Get(first) + if _, err := app.Get(second); err != nil { + t.Fatalf("Get second failed: %v", err) + } + if _, err := app.Get(first); err != nil { + t.Fatalf("Get first failed: %v", err) + } order := app.container.providerBuildOrder() if len(order) != 2 { diff --git a/modkit/kernel/container_test.go b/modkit/kernel/container_test.go index 6091a9e..3f20146 100644 --- a/modkit/kernel/container_test.go +++ b/modkit/kernel/container_test.go @@ -425,8 +425,12 @@ func TestAppCloseReverseOrder(t *testing.T) { t.Fatalf("Bootstrap failed: %v", err) } - _, _ = app.Get("closer.a") - _, _ = app.Get("closer.b") + if _, err := app.Get("closer.a"); err != nil { + t.Fatalf("Get closer.a failed: %v", err) + } + if _, err := app.Get("closer.b"); err != nil { + t.Fatalf("Get closer.b failed: %v", err) + } if err := app.Close(); err != nil { t.Fatalf("Close failed: %v", err) @@ -513,8 +517,12 @@ func TestAppCloseContinuesAfterError(t *testing.T) { t.Fatalf("Bootstrap failed: %v", err) } - _, _ = app.Get("closer.a") - _, _ = app.Get("closer.b") + if _, err := app.Get("closer.a"); err != nil { + t.Fatalf("Get closer.a failed: %v", err) + } + if _, err := app.Get("closer.b"); err != nil { + t.Fatalf("Get closer.b failed: %v", err) + } _, _ = app.Get("closer.c") if err := app.Close(); !errors.Is(err, errB) {