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