diff --git a/lifecycle.go b/lifecycle.go index 72535d4..ec3db23 100644 --- a/lifecycle.go +++ b/lifecycle.go @@ -46,11 +46,11 @@ func NewLifecycleL(defaultLogger *slog.Logger, modules ...*Module) *Lifecycle { // Ensure modules are unique unique := make(map[string]bool) - for _, sub := range modules { - if _, exists := unique[sub.name]; exists { - panic(fmt.Sprintf("duplicate module name: %s", sub.name)) + for _, mod := range modules { + if _, exists := unique[mod.name]; exists { + panic(fmt.Sprintf("duplicate module name: %s", mod.name)) } - unique[sub.name] = true + unique[mod.name] = true } return &Lifecycle{ @@ -81,8 +81,8 @@ func (app *Lifecycle) Logger() *slog.Logger { // of the application lifecycle to ensure all resources are cleaned up properly. func (app *Lifecycle) Setup() error { setupCount := 0 - for _, sub := range app.modules { - if ok, err := app.setupSingle(sub, app.logger); err != nil { + for _, mod := range app.modules { + if ok, err := app.setupSingle(mod, app.logger); err != nil { return err } else if ok { setupCount++ @@ -127,23 +127,23 @@ func (app *Lifecycle) Require(modules ...*Module) error { // This variation is useful when you need to set up modules with a non- // default logger. func (app *Lifecycle) RequireL(logger *slog.Logger, modules ...*Module) error { - for _, sub := range modules { - if sub == nil { + for _, mod := range modules { + if mod == nil { return fmt.Errorf("module is nil") } // Check if the module is already set up - if _, ok := app.setupTracker[sub.name]; ok { - app.logger.Warn("module already set up, ignoring", "module", sub.name) + if _, ok := app.setupTracker[mod.name]; ok { + app.logger.Warn("module already set up, ignoring", "module", mod.name) continue } // Add the module to the lifecycle - app.modules = append(app.modules, sub) + app.modules = append(app.modules, mod) // Run the setup function for the module - if _, err := app.setupSingle(sub, logger); err != nil { - return fmt.Errorf("error setting up required module '%s': %w", sub.name, err) + if _, err := app.setupSingle(mod, logger); err != nil { + return fmt.Errorf("error setting up required module '%s': %w", mod.name, err) } } @@ -153,19 +153,19 @@ func (app *Lifecycle) RequireL(logger *slog.Logger, modules ...*Module) error { } // setupSingle is a helper function to set up a single module. -func (app *Lifecycle) setupSingle(sub *Module, logger *slog.Logger) (bool, error) { - if sub == nil { +func (app *Lifecycle) setupSingle(mod *Module, logger *slog.Logger) (bool, error) { + if mod == nil { return false, fmt.Errorf("module is nil") } // Set the logger for the module - sub.logger = logger + mod.logger = logger // Check if all dependencies are satisfied - for _, dep := range sub.depends { + for _, dep := range mod.depends { if _, ok := app.setupTracker[dep]; !ok { if app.opts.DisableAutoload { - return false, fmt.Errorf("dependency '%s' not satisfied for '%s'", dep, sub.name) + return false, fmt.Errorf("dependency '%s' not satisfied for '%s'", dep, mod.name) } else { // Attempt to set up the dependency mod, err := app.getModuleByName(dep) @@ -174,21 +174,22 @@ func (app *Lifecycle) setupSingle(sub *Module, logger *slog.Logger) (bool, error } if _, err := app.setupSingle(mod, logger); err != nil { - return false, fmt.Errorf("error setting up dependency '%s' for '%s': %w", dep, sub.name, err) + return false, fmt.Errorf("error setting up dependency '%s' for '%s': %w", dep, mod.name, err) } } } } - if sub.setup != nil { + if mod.setup != nil { // Run the setup function for the module - if err := sub.setup(); err != nil { - return false, fmt.Errorf("error initializing '%s': %w", sub.name, err) + if err := mod.setup(); err != nil { + return false, fmt.Errorf("error initializing '%s': %w", mod.name, err) } // Mark this module as setup - app.setupTracker[sub.name] = true + app.setupTracker[mod.name] = true + mod.loaded = true return true, nil } @@ -196,22 +197,23 @@ func (app *Lifecycle) setupSingle(sub *Module, logger *slog.Logger) (bool, error } // singleTeardown is a helper function to tear down a single module. -func (app *Lifecycle) singleTeardown(sub *Module) (bool, error) { - if sub == nil { +func (app *Lifecycle) singleTeardown(mod *Module) (bool, error) { + if mod == nil { return false, fmt.Errorf("module is nil") } // Check if the module was set up - if _, ok := app.setupTracker[sub.name]; !ok { + if _, ok := app.setupTracker[mod.name]; !ok { return false, nil } // Run the teardown function for the module - if sub.teardown != nil { - sub.teardown() + if mod.teardown != nil { + mod.teardown() // Mark this module as torn down - app.teardownTracker[sub.name] = true + app.teardownTracker[mod.name] = true + mod.loaded = false return true, nil } @@ -220,9 +222,9 @@ func (app *Lifecycle) singleTeardown(sub *Module) (bool, error) { // getModuleByName retrieves a module by its name from the lifecycle. func (app *Lifecycle) getModuleByName(name string) (*Module, error) { - for _, sub := range app.modules { - if sub.name == name { - return sub, nil + for _, mod := range app.modules { + if mod.name == name { + return mod, nil } } return nil, fmt.Errorf("module '%s' not found", name) diff --git a/module.go b/module.go index f966e47..c76003e 100644 --- a/module.go +++ b/module.go @@ -13,6 +13,7 @@ type Module struct { setup setupFn teardown teardownFn depends []string + loaded bool // loaded indicates if the module has been set up } // ModuleOpts contains user-exposed options when defining a module. @@ -48,3 +49,8 @@ func (s *Module) Logger() *slog.Logger { func (s *Module) Name() string { return s.name } + +// Loaded returns whether the module has been set up. +func (s *Module) Loaded() bool { + return s.loaded +}