Documentation
¶
Overview ¶
Package core provides the dependency injection container and lifecycle management for the Helix framework.
Index ¶
Constants ¶
const DefaultShutdownTimeout = 30 * time.Second
DefaultShutdownTimeout is the lifecycle shutdown budget used when no custom timeout is configured by the application bootstrap.
Variables ¶
var ( ErrNotFound = errors.New("helix: not found") ErrCyclicDep = errors.New("helix: cyclic dependency") ErrUnresolvable = errors.New("helix: cannot resolve component") ErrShutdownTimeout = errors.New("helix: shutdown timeout exceeded") )
Sentinel errors returned by the Helix DI container.
Functions ¶
func ResolveAll ¶
ResolveAll resolves every registered component assignable to T.
Resolver implementations may opt into this capability without expanding the base Resolver interface used by both reflection and generated modes.
Types ¶
type ComponentRegistration ¶
type ComponentRegistration struct {
// Component is the registered value (pointer to struct).
Component any
// Scope controls how instances are created. Defaults to ScopeSingleton.
Scope Scope
// Lazy defers instantiation until the first Resolve call.
Lazy bool
}
ComponentRegistration holds the metadata for a registered component. It is used internally by Resolver implementations.
func NewComponentRegistration ¶
func NewComponentRegistration(component any) ComponentRegistration
NewComponentRegistration creates a ComponentRegistration with safe defaults (ScopeSingleton, Lazy = false). Use this instead of a struct literal to avoid the zero-value trap where Scope would be "" instead of ScopeSingleton.
type Container ¶
type Container struct {
// contains filtered or unexported fields
}
Container is the Helix dependency injection container. It delegates all registration and resolution to a pluggable Resolver. Use NewContainer with WithResolver to configure a concrete resolver.
func NewContainer ¶
NewContainer creates a new Container and applies the provided options. Without WithResolver, Register and Resolve will return ErrUnresolvable.
func (*Container) Register ¶
Register adds a component to the container's resolver registry. Returns ErrUnresolvable if no Resolver has been configured or component is nil.
func (*Container) Resolve ¶
Resolve populates target with the registered component matching its type. Returns ErrUnresolvable if no Resolver has been configured or target is nil.
type CyclicDepError ¶
type CyclicDepError struct {
Path []string
}
CyclicDepError is returned when a cyclic dependency is detected. It wraps ErrCyclicDep and includes the full dependency path.
func (*CyclicDepError) Error ¶
func (e *CyclicDepError) Error() string
func (*CyclicDepError) Unwrap ¶
func (e *CyclicDepError) Unwrap() error
Unwrap allows errors.Is(err, ErrCyclicDep) to return true.
type DependencyGraph ¶
DependencyGraph represents the resolved component dependency graph. Nodes holds the type names of all registered components. Edges maps each component type name to its list of dependencies.
type Lifecycle ¶
Lifecycle is implemented by components that need to hook into the application start/stop sequence.
OnStart is called after all dependencies are resolved, before the HTTP server begins accepting connections.
OnStop is called on SIGTERM/SIGINT, in reverse dependency order, allowing components to flush buffers and release resources.
type LifecycleCandidate ¶
LifecycleCandidate holds a resolved non-lazy singleton component that implements the Lifecycle interface.
type LifecycleResolver ¶
type LifecycleResolver interface {
// LifecycleCandidates returns all non-lazy singleton components implementing
// Lifecycle, in registration order. Dependency ordering is applied by the caller.
LifecycleCandidates() ([]LifecycleCandidate, error)
}
LifecycleResolver is an optional capability that a Resolver may implement to enable Container.Start() and Container.Shutdown(). Resolvers that do not implement this interface cause Start() to return a clear error. ReflectResolver satisfies this interface by default.
type Option ¶
type Option func(*Container)
Option is a functional option for configuring a Container.
func WithLogger ¶
WithLogger overrides the logger used for lifecycle shutdown errors.
func WithResolver ¶
WithResolver sets the Resolver implementation used by the Container. Without this option, Register and Resolve return ErrUnresolvable. Panics if r is nil.
func WithShutdownTimeout ¶
WithShutdownTimeout overrides the lifecycle shutdown budget.
type ReflectResolver ¶
type ReflectResolver struct {
// contains filtered or unexported fields
}
ReflectResolver resolves dependencies using Go reflection at runtime. It is the default Helix resolver mode and stores singleton instances by type.
func NewReflectResolver ¶
func NewReflectResolver() *ReflectResolver
NewReflectResolver creates a reflection-based resolver with initialized maps.
func (*ReflectResolver) Graph ¶
func (r *ReflectResolver) Graph() DependencyGraph
Graph returns a defensive copy of the current dependency graph.
func (*ReflectResolver) LifecycleCandidates ¶
func (r *ReflectResolver) LifecycleCandidates() ([]LifecycleCandidate, error)
LifecycleCandidates returns all non-lazy singleton components implementing Lifecycle, in registration order. Uses reflect.Type as the seen-set key to prevent collisions between types that share a short string representation.
func (*ReflectResolver) Register ¶
func (r *ReflectResolver) Register(component any) error
Register stores a component registration keyed by its concrete pointer type.
func (*ReflectResolver) Resolve ¶
func (r *ReflectResolver) Resolve(target any) error
Resolve finds the registered component matching target's element type.
type Resolver ¶
type Resolver interface {
Register(component any) error
Resolve(target any) error
Graph() DependencyGraph
}
Resolver is the abstraction layer for dependency resolution strategies. Two implementations are provided:
- ReflectResolver: runtime reflection, zero configuration required (default)
- WireResolver: compile-time code generation, zero reflection in production (opt-in)
type WireResolver ¶
type WireResolver struct {
// contains filtered or unexported fields
}
WireResolver stores pre-wired singleton instances generated at compile time.
func NewWireResolver ¶
func NewWireResolver() *WireResolver
NewWireResolver creates a resolver for compile-time generated DI wiring.
func (*WireResolver) Graph ¶
func (r *WireResolver) Graph() DependencyGraph
Graph returns a flat dependency graph for generated wiring.
func (*WireResolver) LifecycleCandidates ¶
func (r *WireResolver) LifecycleCandidates() ([]LifecycleCandidate, error)
LifecycleCandidates returns registered components implementing Lifecycle.
func (*WireResolver) Register ¶
func (r *WireResolver) Register(component any) error
Register stores a pre-wired component instance by its concrete pointer type.
func (*WireResolver) Resolve ¶
func (r *WireResolver) Resolve(target any) error
Resolve assigns a registered pre-wired instance to target.