Documentation
¶
Overview ¶
Package app provides the core application structure and lifecycle management.
Index ¶
- Variables
- type App
- type Builder
- func (b *Builder) Build() (*App, logger.Logger, error)
- func (b *Builder) ConfigureRuntimeHelpers() *Builder
- func (b *Builder) CreateApp() *Builder
- func (b *Builder) CreateBootstrap() *Builder
- func (b *Builder) CreateHealthProbes() *Builder
- func (b *Builder) CreateLogger() *Builder
- func (b *Builder) GetError() error
- func (b *Builder) InitializeRegistry() *Builder
- func (b *Builder) RegisterClosers() *Builder
- func (b *Builder) RegisterReadyHandler() *Builder
- func (b *Builder) ResolveDependencies() *Builder
- func (b *Builder) WithConfig(cfg *config.Config, opts *Options) *Builder
- type ConnectionPreWarmer
- func (w *ConnectionPreWarmer) IsAvailable() bool
- func (w *ConnectionPreWarmer) LogAvailability()
- func (w *ConnectionPreWarmer) PreWarmDatabase(ctx context.Context, key string) error
- func (w *ConnectionPreWarmer) PreWarmMessaging(ctx context.Context, key string, declarations *messaging.Declarations) error
- func (w *ConnectionPreWarmer) PreWarmSingleTenant(ctx context.Context, declarations *messaging.Declarations) error
- type Describer
- type FactoryResolver
- type HealthProbe
- type HealthStatus
- type ManagerConfigBuilder
- type MessagingInitializer
- func (m *MessagingInitializer) CollectDeclarations(registry *ModuleRegistry) (*messaging.Declarations, error)
- func (m *MessagingInitializer) IsAvailable() bool
- func (m *MessagingInitializer) LogDeploymentMode()
- func (m *MessagingInitializer) PrepareRuntimeConsumers(ctx context.Context, declarations *messaging.Declarations) error
- func (m *MessagingInitializer) SetupLazyConsumerInit(provider ResourceProvider, declarations *messaging.Declarations) error
- type MetadataRegistry
- type Module
- type ModuleDeps
- type ModuleDescriptor
- type ModuleInfo
- type ModuleRegistry
- type MultiTenantResourceProvider
- type OSSignalHandler
- type Options
- type ResourceManagerFactory
- type ResourceProvider
- type ServerRunner
- type SignalHandler
- type SingleTenantResourceProvider
- type StandardTimeoutProvider
- type TenantStore
- type TimeoutProvider
Constants ¶
This section is empty.
Variables ¶
var DefaultModuleRegistry = &MetadataRegistry{ modules: make(map[string]ModuleInfo), }
DefaultModuleRegistry is the global module metadata registry
var ErrNoTenantInContext = errors.New("no tenant in context")
Functions ¶
This section is empty.
Types ¶
type App ¶
type App struct {
// contains filtered or unexported fields
}
App represents the main application instance. It manages the lifecycle and coordination of all application components.
func New ¶
New creates a new application instance with dependencies determined by configuration. It initializes only the services that are configured, failing fast if configured services cannot connect. Returns the app instance, a logger (always available even on failure), and any error.
func NewWithConfig ¶ added in v0.4.0
NewWithConfig creates a new application instance with the provided config and optional overrides. This factory method allows for dependency injection while maintaining fail-fast behavior. Returns the app instance, a logger (always available even on failure), and any error.
func NewWithOptions ¶ added in v0.5.0
NewWithOptions creates a new application instance allowing overrides for config loading and dependencies. Returns the app instance, a logger (always available even on failure), and any error.
func (*App) GetMessagingDeclarations ¶ added in v0.9.0
func (a *App) GetMessagingDeclarations() *messaging.Declarations
GetMessagingDeclarations returns the captured messaging declarations. This is used by tenant managers to replay infrastructure for each tenant.
func (*App) RegisterModule ¶
RegisterModule registers a new module with the application. It adds the module to the registry for initialization and route registration.
type Builder ¶ added in v0.9.0
type Builder struct {
// contains filtered or unexported fields
}
Builder orchestrates the step-by-step construction of an App instance using a fluent interface pattern. Each step is responsible for a single aspect of initialization, making the process clear and testable.
func NewAppBuilder ¶ added in v0.9.0
func NewAppBuilder() *Builder
NewAppBuilder creates a new app builder instance.
func (*Builder) Build ¶ added in v0.9.0
Build returns the completed App instance, logger, or any error encountered during building. The logger is always returned, even on error, to enable proper error logging.
func (*Builder) ConfigureRuntimeHelpers ¶ added in v0.9.0
ConfigureRuntimeHelpers prepares helper components used during runtime.
func (*Builder) CreateApp ¶ added in v0.9.0
CreateApp creates the core App instance with basic configuration.
func (*Builder) CreateBootstrap ¶ added in v0.9.0
CreateBootstrap creates the bootstrap helper for dependency resolution.
func (*Builder) CreateHealthProbes ¶ added in v0.9.0
CreateHealthProbes creates health check probes for all managers.
func (*Builder) CreateLogger ¶ added in v0.9.0
CreateLogger creates and configures the application logger.
func (*Builder) GetError ¶ added in v0.9.0
GetError returns any error encountered during the building process.
func (*Builder) InitializeRegistry ¶ added in v0.9.0
InitializeRegistry creates and configures the module registry.
func (*Builder) RegisterClosers ¶ added in v0.9.0
RegisterClosers registers all components that need cleanup on shutdown.
func (*Builder) RegisterReadyHandler ¶ added in v0.9.0
RegisterReadyHandler registers the health check handler with the server.
func (*Builder) ResolveDependencies ¶ added in v0.9.0
ResolveDependencies creates and configures all application dependencies.
type ConnectionPreWarmer ¶ added in v0.9.0
type ConnectionPreWarmer struct {
// contains filtered or unexported fields
}
ConnectionPreWarmer handles pre-warming of database and messaging connections for improved startup performance and health checking.
func NewConnectionPreWarmer ¶ added in v0.9.0
func NewConnectionPreWarmer( log logger.Logger, dbManager *database.DbManager, messagingManager *messaging.Manager, ) *ConnectionPreWarmer
NewConnectionPreWarmer creates a new connection pre-warmer.
func (*ConnectionPreWarmer) IsAvailable ¶ added in v0.9.0
func (w *ConnectionPreWarmer) IsAvailable() bool
IsAvailable returns true if both database and messaging managers are available.
func (*ConnectionPreWarmer) LogAvailability ¶ added in v0.9.0
func (w *ConnectionPreWarmer) LogAvailability()
LogAvailability logs which components are available for pre-warming.
func (*ConnectionPreWarmer) PreWarmDatabase ¶ added in v0.9.0
func (w *ConnectionPreWarmer) PreWarmDatabase(ctx context.Context, key string) error
PreWarmDatabase attempts to establish a database connection for the given key. Returns error but caller determines if it's fatal.
func (*ConnectionPreWarmer) PreWarmMessaging ¶ added in v0.9.0
func (w *ConnectionPreWarmer) PreWarmMessaging( ctx context.Context, key string, declarations *messaging.Declarations, ) error
PreWarmMessaging attempts to establish messaging components for the given key. This includes ensuring consumers are set up and getting a publisher. Returns error but caller determines if it's fatal.
func (*ConnectionPreWarmer) PreWarmSingleTenant ¶ added in v0.9.0
func (w *ConnectionPreWarmer) PreWarmSingleTenant( ctx context.Context, declarations *messaging.Declarations, ) error
PreWarmSingleTenant pre-warms connections for single-tenant deployments. It establishes database connections and messaging consumers/publishers upfront. Errors are logged as warnings and don't cause startup failure.
type Describer ¶ added in v0.5.0
type Describer interface {
DescribeRoutes() []server.RouteDescriptor
DescribeModule() ModuleDescriptor
}
Describer is an optional interface that modules can implement to provide additional metadata for documentation generation and introspection.
func IsDescriber ¶ added in v0.5.0
IsDescriber checks if a module implements the Describer interface
type FactoryResolver ¶ added in v0.9.0
type FactoryResolver struct {
// contains filtered or unexported fields
}
FactoryResolver encapsulates the logic for resolving factory functions from Options, providing default implementations when not specified.
func NewFactoryResolver ¶ added in v0.9.0
func NewFactoryResolver(opts *Options) *FactoryResolver
NewFactoryResolver creates a new factory resolver with the given options.
func (*FactoryResolver) DatabaseConnector ¶ added in v0.9.0
func (f *FactoryResolver) DatabaseConnector() database.Connector
DatabaseConnector returns the appropriate database connector function. If no custom connector is provided in options, returns the default implementation.
func (*FactoryResolver) HasCustomFactories ¶ added in v0.9.0
func (f *FactoryResolver) HasCustomFactories() bool
HasCustomFactories returns true if any custom factories are provided in options. This can be useful for logging or debugging purposes.
func (*FactoryResolver) MessagingClientFactory ¶ added in v0.9.0
func (f *FactoryResolver) MessagingClientFactory() messaging.ClientFactory
MessagingClientFactory returns the appropriate messaging client factory function. If no custom factory is provided in options, returns a factory that creates AMQPClient instances.
func (*FactoryResolver) ResourceSource ¶ added in v0.9.0
func (f *FactoryResolver) ResourceSource(cfg *config.Config) TenantStore
ResourceSource returns the appropriate tenant resource source. If no custom resource source is provided in options, creates one from config.
type HealthProbe ¶ added in v0.9.0
type HealthProbe interface {
Run(ctx context.Context) HealthStatus
}
HealthProbe exposes a uniform interface for readiness probes.
type HealthStatus ¶ added in v0.9.0
type HealthStatus struct {
Name string
Status string
Details map[string]any
Err error
Critical bool
}
HealthStatus captures the outcome of a readiness probe.
type ManagerConfigBuilder ¶ added in v0.9.0
type ManagerConfigBuilder struct {
// contains filtered or unexported fields
}
ManagerConfigBuilder creates configuration options for database and messaging managers based on deployment mode (single-tenant vs multi-tenant).
func NewManagerConfigBuilder ¶ added in v0.9.0
func NewManagerConfigBuilder(multiTenantEnabled bool, tenantLimit int) *ManagerConfigBuilder
NewManagerConfigBuilder creates a new manager configuration builder.
func (*ManagerConfigBuilder) BuildDatabaseOptions ¶ added in v0.9.0
func (b *ManagerConfigBuilder) BuildDatabaseOptions() database.DbManagerOptions
BuildDatabaseOptions creates database manager options based on deployment mode. Multi-tenant mode uses tenant limits and shorter TTL for dynamic scaling. Single-tenant mode uses smaller fixed limits and longer TTL for stability.
func (*ManagerConfigBuilder) BuildMessagingOptions ¶ added in v0.9.0
func (b *ManagerConfigBuilder) BuildMessagingOptions() messaging.ManagerOptions
BuildMessagingOptions creates messaging manager options based on deployment mode. Multi-tenant mode uses tenant limits and shorter TTL for dynamic scaling. Single-tenant mode uses smaller fixed limits and moderate TTL.
func (*ManagerConfigBuilder) IsMultiTenant ¶ added in v0.9.0
func (b *ManagerConfigBuilder) IsMultiTenant() bool
IsMultiTenant returns true if the builder is configured for multi-tenant mode.
func (*ManagerConfigBuilder) TenantLimit ¶ added in v0.9.0
func (b *ManagerConfigBuilder) TenantLimit() int
TenantLimit returns the configured tenant limit for multi-tenant mode.
type MessagingInitializer ¶ added in v0.9.0
type MessagingInitializer struct {
// contains filtered or unexported fields
}
MessagingInitializer handles messaging system initialization including declaration collection and consumer setup for different deployment modes.
func NewMessagingInitializer ¶ added in v0.9.0
func NewMessagingInitializer( log logger.Logger, manager *messaging.Manager, multiTenant bool, ) *MessagingInitializer
NewMessagingInitializer creates a new messaging initializer.
func (*MessagingInitializer) CollectDeclarations ¶ added in v0.9.0
func (m *MessagingInitializer) CollectDeclarations(registry *ModuleRegistry) (*messaging.Declarations, error)
CollectDeclarations collects messaging declarations from all registered modules. This builds the unified declaration store used for all tenant registries.
func (*MessagingInitializer) IsAvailable ¶ added in v0.9.0
func (m *MessagingInitializer) IsAvailable() bool
IsAvailable returns true if the messaging manager is available.
func (*MessagingInitializer) LogDeploymentMode ¶ added in v0.9.0
func (m *MessagingInitializer) LogDeploymentMode()
LogDeploymentMode logs the current deployment mode for messaging.
func (*MessagingInitializer) PrepareRuntimeConsumers ¶ added in v0.9.0
func (m *MessagingInitializer) PrepareRuntimeConsumers( ctx context.Context, declarations *messaging.Declarations, ) error
PrepareRuntimeConsumers prepares consumers based on deployment mode. For single-tenant: starts consumers immediately. For multi-tenant: logs that consumers will start on-demand.
func (*MessagingInitializer) SetupLazyConsumerInit ¶ added in v0.9.0
func (m *MessagingInitializer) SetupLazyConsumerInit( provider ResourceProvider, declarations *messaging.Declarations, ) error
SetupLazyConsumerInit modifies the resource provider's GetMessaging function to include lazy consumer initialization. This ensures consumers are started on-demand when messaging is first accessed.
type MetadataRegistry ¶ added in v0.5.0
type MetadataRegistry struct {
// contains filtered or unexported fields
}
MetadataRegistry tracks discovered modules for introspection
func (*MetadataRegistry) Clear ¶ added in v0.5.0
func (r *MetadataRegistry) Clear()
Clear removes all registered modules (useful for testing)
func (*MetadataRegistry) Count ¶ added in v0.5.0
func (r *MetadataRegistry) Count() int
Count returns the number of registered modules
func (*MetadataRegistry) GetModule ¶ added in v0.5.0
func (r *MetadataRegistry) GetModule(name string) (ModuleInfo, bool)
GetModule returns information for a specific module
func (*MetadataRegistry) GetModules ¶ added in v0.5.0
func (r *MetadataRegistry) GetModules() map[string]ModuleInfo
GetModules returns a copy of all registered module information
func (*MetadataRegistry) RegisterModule ¶ added in v0.5.0
func (r *MetadataRegistry) RegisterModule(name string, module Module, pkg string)
RegisterModule adds a module to the metadata registry
type Module ¶
type Module interface {
Name() string
Init(deps *ModuleDeps) error
RegisterRoutes(hr *server.HandlerRegistry, r server.RouteRegistrar)
DeclareMessaging(decls *messaging.Declarations)
Shutdown() error
}
Module defines the interface that all application modules must implement. It provides hooks for initialization, route registration, messaging setup, and cleanup.
type ModuleDeps ¶
type ModuleDeps struct {
Logger logger.Logger
Config *config.Config
// GetDB returns a database interface for the current context.
// In single-tenant mode, returns the global database instance.
// In multi-tenant mode, resolves tenant from context and returns tenant-specific database.
GetDB func(_ context.Context) (database.Interface, error)
// GetMessaging returns a messaging client for the current context.
// In single-tenant mode, returns the global messaging client.
// In multi-tenant mode, resolves tenant from context and returns tenant-specific client.
GetMessaging func(_ context.Context) (messaging.AMQPClient, error)
}
ModuleDeps contains the dependencies that are injected into each module. It provides access to core services like database, logging, and messaging. All modules must use GetDB() and GetMessaging() functions for resource access.
type ModuleDescriptor ¶ added in v0.5.0
type ModuleDescriptor struct {
Name string // Module name
Version string // Module version
Description string // Module description
Tags []string // Module tags for grouping
BasePath string // Base path for all module routes
}
ModuleDescriptor captures module-level metadata
type ModuleInfo ¶ added in v0.5.0
type ModuleInfo struct {
Module Module // The actual module instance
Descriptor ModuleDescriptor // Module metadata
Package string // Go package path
}
ModuleInfo contains both the module instance and its metadata
type ModuleRegistry ¶
type ModuleRegistry struct {
// contains filtered or unexported fields
}
ModuleRegistry manages the registration and lifecycle of application modules. It handles module initialization, route registration, messaging setup, and shutdown.
func NewModuleRegistry ¶
func NewModuleRegistry(deps *ModuleDeps) *ModuleRegistry
NewModuleRegistry creates a new module registry with the given dependencies. It initializes an empty registry ready to accept module registrations.
func (*ModuleRegistry) DeclareMessaging ¶ added in v0.9.0
func (r *ModuleRegistry) DeclareMessaging(decls *messaging.Declarations) error
DeclareMessaging calls DeclareMessaging on all registered modules to populate a shared declarations store. This method builds the declaration store that will be used for all tenant registries.
func (*ModuleRegistry) Register ¶
func (r *ModuleRegistry) Register(module Module) error
Register adds a module to the registry and initializes it. It calls the module's Init method with the injected dependencies.
func (*ModuleRegistry) RegisterRoutes ¶
func (r *ModuleRegistry) RegisterRoutes(registrar server.RouteRegistrar)
RegisterRoutes calls RegisterRoutes on all registered modules. It should be called after all modules have been registered.
func (*ModuleRegistry) Shutdown ¶
func (r *ModuleRegistry) Shutdown() error
Shutdown gracefully shuts down all registered modules. It calls each module's Shutdown method and logs any errors. Messaging shutdown is handled by the messaging manager.
type MultiTenantResourceProvider ¶ added in v0.9.0
type MultiTenantResourceProvider struct {
// contains filtered or unexported fields
}
MultiTenantResourceProvider provides database and messaging resources for multi-tenant deployments using tenant ID from context.
func NewMultiTenantResourceProvider ¶ added in v0.9.0
func NewMultiTenantResourceProvider( dbManager *database.DbManager, messagingManager *messaging.Manager, declarations *messaging.Declarations, ) *MultiTenantResourceProvider
NewMultiTenantResourceProvider creates a resource provider for multi-tenant mode.
func (*MultiTenantResourceProvider) GetDB ¶ added in v0.9.0
GetDB returns the database interface for the tenant specified in context.
func (*MultiTenantResourceProvider) GetMessaging ¶ added in v0.9.0
func (p *MultiTenantResourceProvider) GetMessaging(ctx context.Context) (messaging.AMQPClient, error)
GetMessaging returns the messaging client for the tenant specified in context. It ensures tenant-specific consumers are initialized before returning the publisher.
func (*MultiTenantResourceProvider) SetDeclarations ¶ added in v0.9.0
func (p *MultiTenantResourceProvider) SetDeclarations(declarations *messaging.Declarations)
SetDeclarations updates the declaration store used for ensuring consumers.
type OSSignalHandler ¶ added in v0.4.0
type OSSignalHandler struct{}
OSSignalHandler implements SignalHandler using the real OS signal package
func (*OSSignalHandler) Notify ¶ added in v0.4.0
func (osh *OSSignalHandler) Notify(c chan<- os.Signal, sig ...os.Signal)
func (*OSSignalHandler) WaitForSignal ¶ added in v0.4.0
func (osh *OSSignalHandler) WaitForSignal(c <-chan os.Signal)
type Options ¶ added in v0.4.0
type Options struct {
Database database.Interface
MessagingClient messaging.Client
SignalHandler SignalHandler
TimeoutProvider TimeoutProvider
Server ServerRunner
ConfigLoader func() (*config.Config, error)
DatabaseConnector func(*config.DatabaseConfig, logger.Logger) (database.Interface, error)
MessagingClientFactory func(string, logger.Logger) messaging.AMQPClient
ResourceSource TenantStore
}
Options contains optional dependencies for creating an App instance
type ResourceManagerFactory ¶ added in v0.9.0
type ResourceManagerFactory struct {
// contains filtered or unexported fields
}
ResourceManagerFactory creates database and messaging managers using resolved factories and configuration options.
func NewResourceManagerFactory ¶ added in v0.9.0
func NewResourceManagerFactory( factoryResolver *FactoryResolver, configBuilder *ManagerConfigBuilder, log logger.Logger, ) *ResourceManagerFactory
NewResourceManagerFactory creates a new resource manager factory.
func (*ResourceManagerFactory) CreateDatabaseManager ¶ added in v0.9.0
func (f *ResourceManagerFactory) CreateDatabaseManager( resourceSource TenantStore, ) *database.DbManager
CreateDatabaseManager creates a database manager using the resolved factory and appropriate configuration options for the deployment mode.
func (*ResourceManagerFactory) CreateMessagingManager ¶ added in v0.9.0
func (f *ResourceManagerFactory) CreateMessagingManager( resourceSource TenantStore, ) *messaging.Manager
CreateMessagingManager creates a messaging manager using the resolved factory and appropriate configuration options for the deployment mode.
func (*ResourceManagerFactory) LogFactoryInfo ¶ added in v0.9.0
func (f *ResourceManagerFactory) LogFactoryInfo()
LogFactoryInfo logs information about which factories are being used. This is useful for debugging and operational visibility.
type ResourceProvider ¶ added in v0.9.0
type ResourceProvider interface {
GetDB(ctx context.Context) (database.Interface, error)
GetMessaging(ctx context.Context) (messaging.AMQPClient, error)
}
ResourceProvider abstracts database and messaging access with support for both single-tenant and multi-tenant deployment modes.
type ServerRunner ¶ added in v0.5.0
type ServerRunner interface {
Start() error
Shutdown(ctx context.Context) error
Echo() *echo.Echo
ModuleGroup() server.RouteRegistrar
RegisterReadyHandler(handler echo.HandlerFunc)
}
ServerRunner abstracts the HTTP server to allow injecting test-friendly implementations
type SignalHandler ¶ added in v0.4.0
type SignalHandler interface {
Notify(c chan<- os.Signal, sig ...os.Signal)
WaitForSignal(c <-chan os.Signal)
}
SignalHandler interface allows for injectable signal handling for testing
type SingleTenantResourceProvider ¶ added in v0.9.0
type SingleTenantResourceProvider struct {
// contains filtered or unexported fields
}
SingleTenantResourceProvider provides database and messaging resources for single-tenant deployments using a fixed empty key.
func NewSingleTenantResourceProvider ¶ added in v0.9.0
func NewSingleTenantResourceProvider( dbManager *database.DbManager, messagingManager *messaging.Manager, declarations *messaging.Declarations, ) *SingleTenantResourceProvider
NewSingleTenantResourceProvider creates a resource provider for single-tenant mode.
func (*SingleTenantResourceProvider) GetDB ¶ added in v0.9.0
GetDB returns the database interface for single-tenant mode.
func (*SingleTenantResourceProvider) GetMessaging ¶ added in v0.9.0
func (p *SingleTenantResourceProvider) GetMessaging(ctx context.Context) (messaging.AMQPClient, error)
GetMessaging returns the messaging client for single-tenant mode. It ensures consumers are initialized before returning the publisher.
func (*SingleTenantResourceProvider) SetDeclarations ¶ added in v0.9.0
func (p *SingleTenantResourceProvider) SetDeclarations(declarations *messaging.Declarations)
SetDeclarations updates the declaration store used for ensuring consumers.
type StandardTimeoutProvider ¶ added in v0.4.0
type StandardTimeoutProvider struct{}
StandardTimeoutProvider implements TimeoutProvider using context.WithTimeout
func (*StandardTimeoutProvider) WithTimeout ¶ added in v0.4.0
func (stp *StandardTimeoutProvider) WithTimeout(parent context.Context, timeout time.Duration) (context.Context, context.CancelFunc)
type TenantStore ¶ added in v0.9.0
type TenantStore interface {
database.TenantStore
messaging.TenantMessagingResourceSource
}
TenantStore combines the interfaces required by the database and messaging managers.
type TimeoutProvider ¶ added in v0.4.0
type TimeoutProvider interface {
WithTimeout(parent context.Context, timeout time.Duration) (context.Context, context.CancelFunc)
}
TimeoutProvider interface allows for injectable timeout creation for testing