context helpers, rework logging to support ongoing inheritance

Leaves module logger property as purely an override, pulling logger
information directly from the lifecycle instead.
This commit is contained in:
Elijah Duffy
2025-06-04 13:36:40 -07:00
parent 6f9e3731ac
commit c3c8a2cafc
5 changed files with 188 additions and 115 deletions

View File

@@ -13,15 +13,23 @@ var ErrModuleNotFound = errors.New("module not found")
// moduleFn is a function type for module setup and teardown functions.
type moduleFn func(*Module) error
// GenericModule is an interface that allows modules to be extended with custom
// functionality, as the module can return a pointer to the underlying Module.
type GenericModule interface {
// Module returns the underlying Module instance.
Module() *Module
}
// Module represents a sub-system of the application, with its setup and
// teardown functions and dependencies.
type Module struct {
logger *slog.Logger
name string
setup moduleFn
teardown moduleFn
depends []string
loaded bool // loaded indicates if the module has been set up
lifecycle *Lifecycle // lifecycle is the parent lifecycle this module belongs to
logger *slog.Logger
name string
setup moduleFn
teardown moduleFn
depends []string
loaded bool // loaded indicates if the module has been set up
}
// ModuleOpts contains user-exposed options when defining a module.
@@ -45,12 +53,13 @@ func NewModule(name string, opts ModuleOpts) *Module {
}
}
// Logger returns the logger for the module.
// Logger returns the logger for the module. Uses the lifecycle's logger unless
// a specific logger has been set during module load.
func (s *Module) Logger() *slog.Logger {
if s.logger == nil {
panic(fmt.Sprintf("module %s used before logger was initialized", s.name))
if s.logger != nil {
return s.logger
}
return s.logger
return s.lifecycle.Logger()
}
// Name returns the name of the module.
@@ -58,6 +67,11 @@ func (s *Module) Name() string {
return s.name
}
// String returns the name of the module in square brackets, e.g. "[module-name]".
func (s *Module) String() string {
return fmt.Sprintf("[%s]", s.name)
}
// Loaded returns whether the module has been set up.
func (s *Module) Loaded() bool {
return s.loaded