refactor: consolidate Require API and split lifecycle files
Add RequireOpts, RequireWithOpts, and GetModule. Move helpers to lifecycle_internal.go and errors to errors.go. Remove unused GenericModule. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -1,5 +0,0 @@
|
|||||||
// Package app provides the core setup and teardown functions for the
|
|
||||||
// backend application. It handles the initialization of all sub-systems
|
|
||||||
// and the logger. app should never be imported except by a main package.
|
|
||||||
// Examples of suitable main packages are cmd and test.
|
|
||||||
package app
|
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
package app
|
||||||
|
|
||||||
|
import "errors"
|
||||||
|
|
||||||
|
// ErrModuleNotFound is returned when a module is not found in the lifecycle.
|
||||||
|
var ErrModuleNotFound = errors.New("module not found")
|
||||||
@@ -1,25 +1,14 @@
|
|||||||
package app
|
package app
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ErrModuleNotFound is returned when a module is not found in the lifecycle.
|
|
||||||
var ErrModuleNotFound = errors.New("module not found")
|
|
||||||
|
|
||||||
// ModuleFn is a function type for module setup and teardown functions.
|
// ModuleFn is a function type for module setup and teardown functions.
|
||||||
type ModuleFn func(*Module) error
|
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
|
// Module represents a sub-system of the application, with its setup and
|
||||||
// teardown functions and dependencies.
|
// teardown functions and dependencies.
|
||||||
type Module struct {
|
type Module struct {
|
||||||
@@ -60,7 +49,8 @@ func (s *Module) Lifecycle() *Lifecycle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Logger returns the logger for the module. Uses the lifecycle's logger unless
|
// Logger returns the logger for the module. Uses the lifecycle's logger unless
|
||||||
// a specific logger has been set during module load.
|
// a specific logger has been set during module load. Panics if the module is
|
||||||
|
// not associated with a lifecycle and no override logger was set.
|
||||||
func (s *Module) Logger() *slog.Logger {
|
func (s *Module) Logger() *slog.Logger {
|
||||||
if s.logger != nil {
|
if s.logger != nil {
|
||||||
return s.logger
|
return s.logger
|
||||||
|
|||||||
+61
@@ -0,0 +1,61 @@
|
|||||||
|
package app
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"log/slog"
|
||||||
|
)
|
||||||
|
|
||||||
|
// RequireOpts configures [Lifecycle.RequireWithOpts] behavior.
|
||||||
|
type RequireOpts struct {
|
||||||
|
// Logger overrides the lifecycle logger for the required modules. If nil,
|
||||||
|
// the lifecycle logger is used.
|
||||||
|
Logger *slog.Logger
|
||||||
|
|
||||||
|
// Unique, when true, returns an error if any requested module name is
|
||||||
|
// already set up instead of ignoring duplicate instances.
|
||||||
|
Unique bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// Require adds module(s) to the lifecycle and immediately runs setup.
|
||||||
|
// Modules that are already set up (by name) are ignored.
|
||||||
|
func (app *Lifecycle) Require(modules ...*Module) error {
|
||||||
|
return app.require(RequireOpts{}, modules...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RequireWithOpts is like [Lifecycle.Require] with additional options.
|
||||||
|
func (app *Lifecycle) RequireWithOpts(opts RequireOpts, modules ...*Module) error {
|
||||||
|
return app.require(opts, modules...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetModule returns a registered module by name.
|
||||||
|
func (app *Lifecycle) GetModule(name string) (*Module, error) {
|
||||||
|
mod, err := app.getModuleByName(name)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("get module %q: %w", name, err)
|
||||||
|
}
|
||||||
|
return mod, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// RequireL loads modules using a specific logger. Deprecated: use
|
||||||
|
// RequireWithOpts(RequireOpts{Logger: logger}, modules...).
|
||||||
|
func (app *Lifecycle) RequireL(logger *slog.Logger, modules ...*Module) error {
|
||||||
|
if logger == nil {
|
||||||
|
return fmt.Errorf("logger cannot be nil")
|
||||||
|
}
|
||||||
|
return app.require(RequireOpts{Logger: logger}, modules...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RequireUnique loads modules and errors if any name is already set up.
|
||||||
|
// Deprecated: use RequireWithOpts(RequireOpts{Unique: true}, modules...).
|
||||||
|
func (app *Lifecycle) RequireUnique(modules ...*Module) error {
|
||||||
|
return app.require(RequireOpts{Unique: true}, modules...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RequireUniqueL combines RequireL and RequireUnique.
|
||||||
|
// Deprecated: use RequireWithOpts(RequireOpts{Logger: logger, Unique: true}, modules...).
|
||||||
|
func (app *Lifecycle) RequireUniqueL(logger *slog.Logger, modules ...*Module) error {
|
||||||
|
if logger == nil {
|
||||||
|
return fmt.Errorf("logger cannot be nil")
|
||||||
|
}
|
||||||
|
return app.require(RequireOpts{Logger: logger, Unique: true}, modules...)
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user