app

package
v0.9.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 26, 2025 License: MIT Imports: 18 Imported by: 0

Documentation

Overview

Package app provides the core application structure and lifecycle management.

Index

Constants

This section is empty.

Variables

View Source
var DefaultModuleRegistry = &MetadataRegistry{
	modules: make(map[string]ModuleInfo),
}

DefaultModuleRegistry is the global module metadata registry

View Source
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

func New() (*App, error)

func NewWithConfig added in v0.4.0

func NewWithConfig(cfg *config.Config, opts *Options) (*App, error)

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.

func NewWithOptions added in v0.5.0

func NewWithOptions(opts *Options) (*App, error)

NewWithOptions creates a new application instance allowing overrides for config loading and dependencies.

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

func (a *App) RegisterModule(module Module) error

RegisterModule registers a new module with the application. It adds the module to the registry for initialization and route registration.

func (*App) Run

func (a *App) Run() error

Run starts the application and blocks until a shutdown signal is received. It handles graceful shutdown with a timeout.

func (*App) Shutdown

func (a *App) Shutdown(ctx context.Context) error

Shutdown gracefully shuts down the application with the given context. It closes database connections, messaging client, and stops the HTTP server. Returns an aggregated error if any components fail to shut down.

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

func (b *Builder) Build() (*App, error)

Build returns the completed App instance or any error encountered during building.

func (*Builder) ConfigureRuntimeHelpers added in v0.9.0

func (b *Builder) ConfigureRuntimeHelpers() *Builder

ConfigureRuntimeHelpers prepares helper components used during runtime.

func (*Builder) CreateApp added in v0.9.0

func (b *Builder) CreateApp() *Builder

CreateApp creates the core App instance with basic configuration.

func (*Builder) CreateBootstrap added in v0.9.0

func (b *Builder) CreateBootstrap() *Builder

CreateBootstrap creates the bootstrap helper for dependency resolution.

func (*Builder) CreateHealthProbes added in v0.9.0

func (b *Builder) CreateHealthProbes() *Builder

CreateHealthProbes creates health check probes for all managers.

func (*Builder) CreateLogger added in v0.9.0

func (b *Builder) CreateLogger() *Builder

CreateLogger creates and configures the application logger.

func (*Builder) GetError added in v0.9.0

func (b *Builder) GetError() error

GetError returns any error encountered during the building process.

func (*Builder) InitializeRegistry added in v0.9.0

func (b *Builder) InitializeRegistry() *Builder

InitializeRegistry creates and configures the module registry.

func (*Builder) RegisterClosers added in v0.9.0

func (b *Builder) RegisterClosers() *Builder

RegisterClosers registers all components that need cleanup on shutdown.

func (*Builder) RegisterReadyHandler added in v0.9.0

func (b *Builder) RegisterReadyHandler() *Builder

RegisterReadyHandler registers the health check handler with the server.

func (*Builder) ResolveDependencies added in v0.9.0

func (b *Builder) ResolveDependencies() *Builder

ResolveDependencies creates and configures all application dependencies.

func (*Builder) WithConfig added in v0.9.0

func (b *Builder) WithConfig(cfg *config.Config, opts *Options) *Builder

WithConfig sets the configuration and options for the app.

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

func IsDescriber(m Module) (Describer, bool)

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

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

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

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

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL