add Lifecycle.RequireUnique methods for load-once deps
This commit is contained in:
23
lifecycle.go
23
lifecycle.go
@@ -123,6 +123,12 @@ func (app *Lifecycle) Require(modules ...*Module) error {
|
||||
return app.RequireL(app.logger, modules...)
|
||||
}
|
||||
|
||||
// RequireUnique is the same as Require, but it returns an error if any requested
|
||||
// module is already set up--rather than ignoring it.
|
||||
func (app *Lifecycle) RequireUnique(modules ...*Module) error {
|
||||
return app.RequireUniqueL(app.logger, modules...)
|
||||
}
|
||||
|
||||
// RequireL adds module(s) to the lifecycle with a specific logger and
|
||||
// immediately runs any setup functions. See Require for more details.
|
||||
// This variation is useful when you need to set up modules with a non-
|
||||
@@ -163,6 +169,23 @@ func (app *Lifecycle) RequireL(logger *slog.Logger, modules ...*Module) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// RequireUniqueL is the same as RequireL, but it returns an error if any requested
|
||||
// module is already set up--rather than ignoring it.
|
||||
func (app *Lifecycle) RequireUniqueL(logger *slog.Logger, modules ...*Module) error {
|
||||
// Check if any module is already set up
|
||||
for _, mod := range modules {
|
||||
if mod == nil {
|
||||
return fmt.Errorf("module is nil")
|
||||
}
|
||||
|
||||
if _, ok := app.setupTracker[mod.name]; ok {
|
||||
return fmt.Errorf("module '%s' is already set up, cannot require it again", mod.name)
|
||||
}
|
||||
}
|
||||
|
||||
return app.RequireL(logger, modules...)
|
||||
}
|
||||
|
||||
// setupSingle is a helper function to set up a single module. Returns an error
|
||||
// if the module cannot be set up or if dependencies are not satisfied.
|
||||
func (app *Lifecycle) setupSingle(mod *Module, logger *slog.Logger) error {
|
||||
|
||||
@@ -222,6 +222,14 @@ func TestLifecycle_Require(t *testing.T) {
|
||||
assert.Equal(t, lc.logger, mod.logger, "expected module logger to match lifecycle logger")
|
||||
}
|
||||
|
||||
func TestLifecycle_RequireUnique(t *testing.T) {
|
||||
lc := NewLifecycle()
|
||||
mod := NewModule("module1", ModuleOpts{})
|
||||
err := lc.RequireUnique(mod)
|
||||
assert.NoError(t, err, "expected RequireL to succeed")
|
||||
assert.Equal(t, lc.logger, mod.logger, "expected module logger to match lifecycle logger")
|
||||
}
|
||||
|
||||
func TestLifecycle_RequireL(t *testing.T) {
|
||||
cases := []struct {
|
||||
name string
|
||||
@@ -324,7 +332,56 @@ func TestLifecycle_RequireL(t *testing.T) {
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestLifecycle_RequireUniqueL(t *testing.T) {
|
||||
cases := []struct {
|
||||
name string
|
||||
modules []*Module
|
||||
existingModules []string
|
||||
expectedErr string
|
||||
}{
|
||||
{
|
||||
name: "no existing modules",
|
||||
modules: []*Module{
|
||||
NewModule("module1", ModuleOpts{}),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "module already set up",
|
||||
modules: []*Module{
|
||||
NewModule("module1", ModuleOpts{}),
|
||||
NewModule("module2", ModuleOpts{}),
|
||||
},
|
||||
existingModules: []string{"module1"},
|
||||
expectedErr: "module 'module1' is already set up, cannot require it again",
|
||||
},
|
||||
{
|
||||
name: "nil module",
|
||||
modules: []*Module{nil},
|
||||
expectedErr: "module is nil",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
lc := NewLifecycle()
|
||||
|
||||
// Fake existing modules
|
||||
for _, modName := range tc.existingModules {
|
||||
lc.setupTracker[modName] = 0 // Mark as set up
|
||||
}
|
||||
|
||||
err := lc.RequireUniqueL(lc.logger, tc.modules...)
|
||||
if tc.expectedErr == "" {
|
||||
assert.NoError(err, "expected RequireUniqueL to succeed")
|
||||
} else {
|
||||
assert.Error(err, "expected RequireUniqueL to fail")
|
||||
assert.Contains(err.Error(), tc.expectedErr, "expected error message to match")
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestLifecycle_setupSingle(t *testing.T) {
|
||||
|
||||
Reference in New Issue
Block a user