Documentation
ΒΆ
Overview ΒΆ
Package modular provides a flexible, modular application framework for Go. It supports configuration management, dependency injection, service registration, and multi-tenant functionality.
The modular framework allows you to build applications composed of independent modules that can declare dependencies, provide services, and be configured individually. Each module implements the Module interface and can optionally implement additional interfaces like Configurable, ServiceAware, Startable, etc.
Basic usage:
app := modular.NewStdApplication(configProvider, logger)
app.RegisterModule(&MyModule{})
if err := app.Run(); err != nil {
log.Fatal(err)
}
Package modular provides Observer pattern interfaces for event-driven communication. These interfaces use CloudEvents specification for standardized event format and better interoperability with external systems.
Package modular provides CloudEvents integration for the Observer pattern. This file provides CloudEvents utility functions and validation for standardized event format and better interoperability.
Package modular provides tenant functionality for multi-tenant applications. This file contains tenant-related types and interfaces.
The tenant functionality enables a single application instance to serve multiple isolated tenants, each with their own configuration, data, and potentially customized behavior.
Key concepts:
- TenantID: unique identifier for each tenant
- TenantContext: context that carries tenant information through the call chain
- TenantService: manages tenant registration and configuration
- TenantAwareModule: modules that can adapt their behavior per tenant
Example multi-tenant application setup:
// Create tenant service
tenantSvc := modular.NewStandardTenantService(logger)
// Register tenant service
app.RegisterService("tenantService", tenantSvc)
// Register tenant-aware modules
app.RegisterModule(&MyTenantAwareModule{})
// Register tenants with specific configurations
tenantSvc.RegisterTenant("tenant-1", map[string]ConfigProvider{
"database": modular.NewStdConfigProvider(&DatabaseConfig{Host: "tenant1-db"}),
})
Package modular provides tenant-aware functionality for multi-tenant applications. This file contains the core tenant service implementation.
Index ΒΆ
- Constants
- Variables
- func CompareModuleInstances(original, current Module, moduleName string)
- func DebugAllModuleInterfaces(app Application)
- func DebugModuleInterfaces(app Application, moduleName string)
- func DetectBaseConfigStructure() bool
- func GenerateSampleConfig(cfg interface{}, format string) ([]byte, error)
- func GetBaseConfigFeeder() feeders.Feeder
- func HandleEventEmissionError(err error, logger Logger, moduleName, eventType string) bool
- func IsBaseConfigEnabled() bool
- func IsErrCircularDependency(err error) bool
- func IsSynchronousNotification(ctx context.Context) bool
- func LoadTenantConfigs(app Application, tenantService TenantService, params TenantConfigParams) error
- func NewCloudEvent(eventType, source string, data interface{}, metadata map[string]interface{}) cloudevents.Event
- func NewModuleLifecycleEvent(source, subject, name, version, action string, metadata map[string]interface{}) cloudevents.Event
- func ProcessConfigDefaults(cfg interface{}) error
- func SaveSampleConfig(cfg interface{}, format, filePath string) error
- func SetBaseConfig(configDir, environment string)
- func ValidateCloudEvent(event cloudevents.Event) error
- func ValidateConfig(cfg interface{}) error
- func ValidateConfigRequired(cfg interface{}) error
- func WithSynchronousNotification(ctx context.Context) context.Context
- type AppRegistry
- type Application
- type ApplicationBuilder
- type ApplicationDecorator
- type BaseApplicationDecorator
- func (d *BaseApplicationDecorator) ConfigProvider() ConfigProvider
- func (d *BaseApplicationDecorator) ConfigSections() map[string]ConfigProvider
- func (d *BaseApplicationDecorator) GetConfigSection(section string) (ConfigProvider, error)
- func (d *BaseApplicationDecorator) GetInnerApplication() Application
- func (d *BaseApplicationDecorator) GetObservers() []ObserverInfo
- func (d *BaseApplicationDecorator) GetService(name string, target any) error
- func (d *BaseApplicationDecorator) GetTenantConfig(tenantID TenantID, section string) (ConfigProvider, error)
- func (d *BaseApplicationDecorator) GetTenantService() (TenantService, error)
- func (d *BaseApplicationDecorator) Init() error
- func (d *BaseApplicationDecorator) IsVerboseConfig() bool
- func (d *BaseApplicationDecorator) Logger() Logger
- func (d *BaseApplicationDecorator) NotifyObservers(ctx context.Context, event cloudevents.Event) error
- func (d *BaseApplicationDecorator) RegisterConfigSection(section string, cp ConfigProvider)
- func (d *BaseApplicationDecorator) RegisterModule(module Module)
- func (d *BaseApplicationDecorator) RegisterObserver(observer Observer, eventTypes ...string) error
- func (d *BaseApplicationDecorator) RegisterService(name string, service any) error
- func (d *BaseApplicationDecorator) Run() error
- func (d *BaseApplicationDecorator) ServiceIntrospector() ServiceIntrospector
- func (d *BaseApplicationDecorator) SetLogger(logger Logger)
- func (d *BaseApplicationDecorator) SetVerboseConfig(enabled bool)
- func (d *BaseApplicationDecorator) Start() error
- func (d *BaseApplicationDecorator) Stop() error
- func (d *BaseApplicationDecorator) SvcRegistry() ServiceRegistry
- func (d *BaseApplicationDecorator) UnregisterObserver(observer Observer) error
- func (d *BaseApplicationDecorator) WithTenant(tenantID TenantID) (*TenantContext, error)
- type BaseConfigOptions
- type BaseLoggerDecorator
- type CloudEvent
- type ComplexFeeder
- type Config
- func (c *Config) AddFeeder(feeder Feeder) *Config
- func (c *Config) AddStructKey(key string, target interface{}) *Config
- func (c *Config) Feed() error
- func (c *Config) FeedWithModuleContext(target interface{}, moduleName string) error
- func (c *Config) SetFieldTracker(tracker FieldTracker) *Config
- func (c *Config) SetVerboseDebug(enabled bool, logger Logger) *Config
- type ConfigDecorator
- type ConfigProvider
- type ConfigSetup
- type ConfigValidator
- type Configurable
- type Constructable
- type DefaultFieldTracker
- func (t *DefaultFieldTracker) GetFieldPopulation(fieldPath string) *FieldPopulation
- func (t *DefaultFieldTracker) GetMostRelevantFieldPopulation(fieldPath string) *FieldPopulation
- func (t *DefaultFieldTracker) GetPopulationsByFeeder(feederType string) []FieldPopulation
- func (t *DefaultFieldTracker) GetPopulationsBySource(sourceType string) []FieldPopulation
- func (t *DefaultFieldTracker) RecordFieldPopulation(fp FieldPopulation)
- func (t *DefaultFieldTracker) SetLogger(logger Logger)
- type DependencyAware
- type DependencyEdge
- type DualWriterLoggerDecorator
- type EdgeType
- type EnhancedServiceRegistry
- func (r *EnhancedServiceRegistry) AsServiceRegistry() ServiceRegistry
- func (r *EnhancedServiceRegistry) ClearCurrentModule()
- func (r *EnhancedServiceRegistry) GetService(name string) (any, bool)
- func (r *EnhancedServiceRegistry) GetServiceEntry(name string) (*ServiceRegistryEntry, bool)
- func (r *EnhancedServiceRegistry) GetServicesByInterface(interfaceType reflect.Type) []*ServiceRegistryEntry
- func (r *EnhancedServiceRegistry) GetServicesByModule(moduleName string) []string
- func (r *EnhancedServiceRegistry) RegisterService(name string, service any) (string, error)
- func (r *EnhancedServiceRegistry) SetCurrentModule(module Module)
- type EventValidationObserver
- func (v *EventValidationObserver) GetAllEvents() []cloudevents.Event
- func (v *EventValidationObserver) GetMissingEvents() []string
- func (v *EventValidationObserver) GetUnexpectedEvents() []string
- func (v *EventValidationObserver) ObserverID() string
- func (v *EventValidationObserver) OnEvent(ctx context.Context, event cloudevents.Event) error
- func (v *EventValidationObserver) Reset()
- type Feeder
- type FieldPopulation
- type FieldTracker
- type FieldTrackerBridge
- type FieldTrackingFeeder
- type FileBasedTenantConfigLoader
- type FilterLoggerDecorator
- type FunctionalObserver
- type InstanceAwareConfigProvider
- type InstanceAwareConfigSupport
- type InstanceAwareFeeder
- type InstancePrefixFunc
- type InterfaceMatch
- type LevelModifierLoggerDecorator
- type LoadAppConfigFunc
- type Logger
- type LoggerDecorator
- type Module
- type ModuleAwareFeeder
- type ModuleConstructor
- type ModuleLifecyclePayload
- type ModuleRegistry
- type ModuleWithConstructor
- type ObservableApplication
- func (app *ObservableApplication) GetObservers() []ObserverInfo
- func (app *ObservableApplication) Init() error
- func (app *ObservableApplication) NotifyObservers(ctx context.Context, event cloudevents.Event) error
- func (app *ObservableApplication) RegisterModule(module Module)
- func (app *ObservableApplication) RegisterObserver(observer Observer, eventTypes ...string) error
- func (app *ObservableApplication) RegisterService(name string, service any) error
- func (app *ObservableApplication) Start() error
- func (app *ObservableApplication) Stop() error
- func (app *ObservableApplication) UnregisterObserver(observer Observer) error
- type ObservableDecorator
- type ObservableModule
- type Observer
- type ObserverFunc
- type ObserverInfo
- type Option
- func WithBaseApplication(base Application) Option
- func WithConfigDecorators(decorators ...ConfigDecorator) Option
- func WithConfigProvider(provider ConfigProvider) Option
- func WithLogger(logger Logger) Option
- func WithModules(modules ...Module) Option
- func WithObserver(observers ...ObserverFunc) Option
- func WithTenantAware(loader TenantLoader) Option
- type PrefixLoggerDecorator
- type ServiceAware
- type ServiceDependency
- type ServiceIntrospector
- type ServiceIntrospectorImpl
- type ServiceProvider
- type ServiceRegistry
- type ServiceRegistryEntry
- type StandardTenantService
- func (ts *StandardTenantService) GetTenantConfig(tenantID TenantID, section string) (ConfigProvider, error)
- func (ts *StandardTenantService) GetTenants() []TenantID
- func (ts *StandardTenantService) RegisterTenant(tenantID TenantID, configs map[string]ConfigProvider) error
- func (ts *StandardTenantService) RegisterTenantAwareModule(module TenantAwareModule) error
- func (ts *StandardTenantService) RegisterTenantConfigSection(tenantID TenantID, section string, provider ConfigProvider) error
- func (ts *StandardTenantService) RemoveTenant(tenantID TenantID) error
- type Startable
- type StdApplication
- func (app *StdApplication) ConfigProvider() ConfigProvider
- func (app *StdApplication) ConfigSections() map[string]ConfigProvider
- func (app *StdApplication) GetConfigSection(section string) (ConfigProvider, error)
- func (app *StdApplication) GetService(name string, target any) error
- func (app *StdApplication) GetTenantConfig(tenantID TenantID, section string) (ConfigProvider, error)
- func (app *StdApplication) GetTenantService() (TenantService, error)
- func (app *StdApplication) Init() error
- func (app *StdApplication) InitWithApp(appToPass Application) error
- func (app *StdApplication) IsVerboseConfig() bool
- func (app *StdApplication) Logger() Logger
- func (app *StdApplication) RegisterConfigSection(section string, cp ConfigProvider)
- func (app *StdApplication) RegisterModule(module Module)
- func (app *StdApplication) RegisterService(name string, service any) error
- func (app *StdApplication) Run() error
- func (app *StdApplication) ServiceIntrospector() ServiceIntrospector
- func (app *StdApplication) SetConfigFeeders(feeders []Feeder)
- func (app *StdApplication) SetLogger(logger Logger)
- func (app *StdApplication) SetVerboseConfig(enabled bool)
- func (app *StdApplication) Start() error
- func (app *StdApplication) Stop() error
- func (app *StdApplication) SvcRegistry() ServiceRegistry
- func (app *StdApplication) WithTenant(tenantID TenantID) (*TenantContext, error)
- type StdConfigProvider
- type Stoppable
- type StructStateDiffer
- type Subject
- type Tenant
- type TenantApplication
- type TenantAwareConfig
- type TenantAwareDecorator
- func (d *TenantAwareDecorator) GetTenantConfig(tenantID TenantID, section string) (ConfigProvider, error)
- func (d *TenantAwareDecorator) GetTenantService() (TenantService, error)
- func (d *TenantAwareDecorator) Start() error
- func (d *TenantAwareDecorator) WithTenant(tenantID TenantID) (*TenantContext, error)
- type TenantAwareModule
- type TenantAwareRegistry
- type TenantConfigLoader
- type TenantConfigParams
- type TenantConfigProvider
- func (tcp *TenantConfigProvider) GetConfig() any
- func (tcp *TenantConfigProvider) GetDefaultConfig() ConfigProvider
- func (tcp *TenantConfigProvider) GetTenantConfig(tenantID TenantID, section string) (ConfigProvider, error)
- func (tcp *TenantConfigProvider) HasTenantConfig(tenantID TenantID, section string) bool
- func (tcp *TenantConfigProvider) SetTenantConfig(tenantID TenantID, section string, provider ConfigProvider)
- type TenantContext
- type TenantID
- type TenantLoader
- type TenantService
- type ValueInjectionLoggerDecorator
- type VerboseAwareFeeder
- type VerboseLogger
Constants ΒΆ
const ( // Module lifecycle events EventTypeModuleRegistered = "com.modular.module.registered" EventTypeModuleInitialized = "com.modular.module.initialized" EventTypeModuleStarted = "com.modular.module.started" EventTypeModuleStopped = "com.modular.module.stopped" EventTypeModuleFailed = "com.modular.module.failed" // Service lifecycle events EventTypeServiceRegistered = "com.modular.service.registered" EventTypeServiceUnregistered = "com.modular.service.unregistered" EventTypeServiceRequested = "com.modular.service.requested" // Configuration events EventTypeConfigLoaded = "com.modular.config.loaded" EventTypeConfigValidated = "com.modular.config.validated" EventTypeConfigChanged = "com.modular.config.changed" // Application lifecycle events EventTypeApplicationStarted = "com.modular.application.started" EventTypeApplicationStopped = "com.modular.application.stopped" EventTypeApplicationFailed = "com.modular.application.failed" )
EventType constants for common application events. These provide a standardized vocabulary for CloudEvent types emitted by the core framework. Following CloudEvents specification, these use reverse domain notation.
const ModuleLifecycleSchema = "modular.module.lifecycle.v1"
ModuleLifecycleSchema is the schema identifier for module lifecycle payloads.
Variables ΒΆ
var ( // Configuration errors - issues with loading and managing configuration ErrConfigSectionNotFound = errors.New("config section not found") ErrApplicationNil = errors.New("application is nil") ErrConfigProviderNil = errors.New("failed to load app config: config provider is nil") ErrConfigSectionError = errors.New("failed to load app config: error triggered by section") ErrLoggerNotSet = errors.New("logger not set in application builder") // Config validation errors - problems with configuration structure and values ErrConfigNil = errors.New("config is nil") ErrConfigNotPointer = errors.New("config must be a pointer") ErrConfigNotStruct = errors.New("config must be a struct") ErrConfigRequiredFieldMissing = errors.New("required field is missing") ErrConfigValidationFailed = errors.New("config validation failed") ErrUnsupportedTypeForDefault = errors.New("unsupported type for default value") ErrDefaultValueParseError = errors.New("failed to parse default value") ErrDefaultValueOverflowsInt = errors.New("default value overflows int") ErrDefaultValueOverflowsUint = errors.New("default value overflows uint") ErrDefaultValueOverflowsFloat = errors.New("default value overflows float") ErrInvalidFieldKind = errors.New("invalid field kind") ErrIncompatibleFieldKind = errors.New("incompatible field kind") ErrUnexpectedFieldKind = errors.New("unexpected field kind") ErrUnsupportedFormatType = errors.New("unsupported format type") ErrConfigFeederError = errors.New("config feeder error") ErrConfigSetupError = errors.New("config setup error") ErrConfigNilPointer = errors.New("config is nil pointer") ErrFieldCannotBeSet = errors.New("field cannot be set") // Service registry errors ErrServiceAlreadyRegistered = errors.New("service already registered") ErrServiceNotFound = errors.New("service not found") // Service injection errors ErrTargetNotPointer = errors.New("target must be a non-nil pointer") ErrTargetValueInvalid = errors.New("target value is invalid") ErrServiceIncompatible = errors.New("service cannot be assigned to target") ErrServiceNil = errors.New("service is nil") ErrServiceWrongType = errors.New("service doesn't satisfy required type") ErrServiceWrongInterface = errors.New("service doesn't satisfy required interface") // Dependency resolution errors ErrCircularDependency = errors.New("circular dependency detected") ErrModuleDependencyMissing = errors.New("module depends on non-existent module") ErrRequiredServiceNotFound = errors.New("required service not found for module") // Constructor errors ErrConstructorNotFunction = errors.New("constructor must be a function") ErrConstructorInvalidReturnCount = errors.New("constructor must return exactly two values (Module, error)") ErrConstructorInvalidReturnType = errors.New("constructor must return a Module as first value") ErrConstructorParameterServiceNotFound = errors.New("no service found for constructor parameter") ErrInvalidInterfaceConfiguration = errors.New("invalid interface configuration for required service") ErrInterfaceConfigurationNil = errors.New("SatisfiesInterface is nil") ErrInterfaceConfigurationNotInterface = errors.New("SatisfiesInterface is not an interface type") ErrServiceInterfaceIncompatible = errors.New("service does not implement required interface") // Tenant errors ErrAppContextNotInitialized = errors.New("application context not initialized") ErrTenantNotFound = errors.New("tenant not found") ErrTenantConfigNotFound = errors.New("tenant config section not found") ErrTenantConfigProviderNil = errors.New("tenant config provider is nil") ErrTenantConfigValueNil = errors.New("tenant config value is nil") ErrTenantRegisterNilConfig = errors.New("cannot register nil config for tenant") ErrMockTenantConfigsNotInitialized = errors.New("mock tenant configs not initialized") ErrConfigSectionNotFoundForTenant = errors.New("config section not found for tenant") // Observer/Event emission errors ErrNoSubjectForEventEmission = errors.New("no subject available for event emission") // Test-specific errors ErrSetupFailed = errors.New("setup error") ErrFeedFailed = errors.New("feed error") ErrFeedKeyFailed = errors.New("feedKey error") // Tenant config errors ErrConfigCastFailed = errors.New("failed to cast config to expected type") ErrOriginalOrLoadedNil = errors.New("original or loaded config is nil") ErrDestinationNotPointer = errors.New("destination must be a pointer") ErrCannotCopyMapToStruct = errors.New("cannot copy from map to non-struct") ErrUnsupportedSourceType = errors.New("unsupported source type") // Additional tenant config errors ErrTenantSectionConfigNil = errors.New("tenant section config is nil after feeding") ErrCreatedNilProvider = errors.New("created nil provider for tenant section") ErrIncompatibleFieldTypes = errors.New("incompatible types for field assignment") ErrIncompatibleInterfaceValue = errors.New("incompatible interface value for field") )
Application errors
var ConfigFeeders = []Feeder{ feeders.NewEnvFeeder(), }
ConfigFeeders provides a default set of configuration feeders for common use cases
var (
ErrUnsupportedExtension = errors.New("unsupported file extension")
)
Static errors for better error handling
Functions ΒΆ
func CompareModuleInstances ΒΆ added in v1.2.9
CompareModuleInstances compares two module instances to see if they're the same
func DebugAllModuleInterfaces ΒΆ added in v1.2.9
func DebugAllModuleInterfaces(app Application)
DebugAllModuleInterfaces debugs all registered modules
func DebugModuleInterfaces ΒΆ added in v1.2.9
func DebugModuleInterfaces(app Application, moduleName string)
DebugModuleInterfaces helps debug interface implementation issues during module lifecycle
func DetectBaseConfigStructure ΒΆ added in v1.4.1
func DetectBaseConfigStructure() bool
DetectBaseConfigStructure automatically detects if base configuration structure exists and enables it if found. This is called automatically during application initialization.
func GenerateSampleConfig ΒΆ added in v1.2.2
GenerateSampleConfig generates a sample configuration for a config struct The format parameter can be "yaml", "json", or "toml"
func GetBaseConfigFeeder ΒΆ added in v1.4.1
GetBaseConfigFeeder returns a BaseConfigFeeder if base config is enabled
func HandleEventEmissionError ΒΆ added in v1.4.1
HandleEventEmissionError provides consistent error handling for event emission failures. This helper function standardizes how modules should handle the "no subject available" error and other emission failures to reduce noisy output during tests and in non-observable applications.
It returns true if the error was handled (i.e., it was ErrNoSubjectForEventEmission or similar), false if the error should be handled by the caller.
Example usage:
if err := module.EmitEvent(ctx, event); err != nil {
if !modular.HandleEventEmissionError(err, logger, "my-module", eventType) {
// Handle other types of errors here
}
}
func IsBaseConfigEnabled ΒΆ added in v1.4.1
func IsBaseConfigEnabled() bool
IsBaseConfigEnabled returns true if base configuration support is enabled
func IsErrCircularDependency ΒΆ added in v1.4.2
IsErrCircularDependency checks if an error is a circular dependency error
func IsSynchronousNotification ΒΆ added in v1.4.1
IsSynchronousNotification returns true if the context requests synchronous delivery.
func LoadTenantConfigs ΒΆ added in v1.1.0
func LoadTenantConfigs(app Application, tenantService TenantService, params TenantConfigParams) error
LoadTenantConfigs scans the given directory for config files. Each file should be named with the tenant ID (e.g. "tenant123.json"). For each file, it unmarshals the configuration and registers it with the provided TenantService for the given section. The configNameRegex is a regex pattern for the config file names (e.g. "^tenant[0-9]+\\.json$").
func NewCloudEvent ΒΆ added in v1.4.0
func NewCloudEvent(eventType, source string, data interface{}, metadata map[string]interface{}) cloudevents.Event
NewCloudEvent creates a new CloudEvent with the specified parameters. This is a convenience function for creating properly formatted CloudEvents.
func NewModuleLifecycleEvent ΒΆ added in v1.4.2
func NewModuleLifecycleEvent(source, subject, name, version, action string, metadata map[string]interface{}) cloudevents.Event
NewModuleLifecycleEvent builds a CloudEvent for a module/application lifecycle using the structured payload. It sets payload_schema and module_action extensions for lightweight routing without full payload decode.
func ProcessConfigDefaults ΒΆ added in v1.2.2
func ProcessConfigDefaults(cfg interface{}) error
ProcessConfigDefaults applies default values to a config struct based on struct tags. It looks for `default:"value"` tags on struct fields and sets the field value if currently zero/empty.
Supported field types:
- Basic types: string, int, float, bool
- Slices: []string, []int, etc.
- Pointers to basic types
Example struct tags:
type Config struct {
Host string `default:"localhost"`
Port int `default:"8080"`
Debug bool `default:"false"`
Features []string `default:"feature1,feature2"`
}
This function is automatically called by the configuration loading system before validation, but can also be called manually if needed.
func SaveSampleConfig ΒΆ added in v1.2.2
SaveSampleConfig generates and saves a sample configuration file
func SetBaseConfig ΒΆ added in v1.4.1
func SetBaseConfig(configDir, environment string)
SetBaseConfig configures the framework to use base configuration with environment overrides This should be called before building the application if you want to use base config support
func ValidateCloudEvent ΒΆ added in v1.4.0
func ValidateCloudEvent(event cloudevents.Event) error
ValidateCloudEvent validates that a CloudEvent conforms to the specification. This provides validation beyond the basic CloudEvent SDK validation.
func ValidateConfig ΒΆ added in v1.2.2
func ValidateConfig(cfg interface{}) error
ValidateConfig validates a configuration using the following steps: 1. Processes default values 2. Validates required fields 3. If the config implements ConfigValidator, calls its Validate method
func ValidateConfigRequired ΒΆ added in v1.2.2
func ValidateConfigRequired(cfg interface{}) error
ValidateConfigRequired checks all struct fields with `required:"true"` tag and verifies they are not zero/empty values
Types ΒΆ
type AppRegistry ΒΆ
type AppRegistry interface {
// SvcRegistry retrieves the service registry.
// The service registry contains all services registered by modules
// and the application, providing a central location for service lookup.
SvcRegistry() ServiceRegistry
}
AppRegistry provides registry functionality for applications. This interface provides access to the application's service registry, allowing modules and components to access registered services.
type Application ΒΆ
type Application interface {
// ConfigProvider retrieves the application's main configuration provider.
// This provides access to application-level configuration that isn't
// specific to any particular module.
ConfigProvider() ConfigProvider
// SvcRegistry retrieves the service registry.
// Modules use this to register services they provide and lookup
// services they need from other modules.
SvcRegistry() ServiceRegistry
// RegisterModule adds a module to the application.
// Modules must be registered before calling Init(). The framework
// will handle initialization order based on declared dependencies.
//
// Example:
// app.RegisterModule(&DatabaseModule{})
// app.RegisterModule(&WebServerModule{})
RegisterModule(module Module)
// RegisterConfigSection registers a configuration section with the application.
// This allows modules to register their configuration requirements,
// making them available for loading from configuration sources.
//
// Example:
// cfg := &MyModuleConfig{}
// provider := modular.NewStdConfigProvider(cfg)
// app.RegisterConfigSection("mymodule", provider)
RegisterConfigSection(section string, cp ConfigProvider)
// ConfigSections retrieves all registered configuration sections.
// Returns a map of section names to their configuration providers.
// Useful for debugging and introspection.
ConfigSections() map[string]ConfigProvider
// GetConfigSection retrieves a specific configuration section.
// Returns an error if the section doesn't exist.
//
// Example:
// provider, err := app.GetConfigSection("database")
// if err != nil {
// return err
// }
// cfg := provider.GetConfig().(*DatabaseConfig)
GetConfigSection(section string) (ConfigProvider, error)
// RegisterService adds a service to the service registry with type checking.
// Services registered here become available to all modules that declare
// them as dependencies.
//
// Returns an error if a service with the same name is already registered.
//
// Example:
// db := &DatabaseConnection{}
// err := app.RegisterService("database", db)
RegisterService(name string, service any) error
// GetService retrieves a service from the registry with type assertion.
// The target parameter must be a pointer to the expected type.
// The framework will perform type checking and assignment.
//
// Example:
// var db *DatabaseConnection
// err := app.GetService("database", &db)
GetService(name string, target any) error
// Init initializes the application and all registered modules.
// This method:
// - Calls RegisterConfig on all configurable modules
// - Loads configuration from all registered sources
// - Resolves module dependencies
// - Initializes modules in dependency order
// - Registers services provided by modules
//
// Must be called before Start() or Run().
Init() error
// Start starts the application and all startable modules.
// Modules implementing the Startable interface will have their
// Start method called in dependency order.
//
// This is typically used when you want to start the application
// but handle the shutdown logic yourself (rather than using Run()).
Start() error
// Stop stops the application and all stoppable modules.
// Modules implementing the Stoppable interface will have their
// Stop method called in reverse dependency order.
//
// Provides a timeout context for graceful shutdown.
Stop() error
// Run starts the application and blocks until termination.
// This is equivalent to calling Init(), Start(), and then waiting
// for a termination signal (SIGINT, SIGTERM) before calling Stop().
//
// This is the most common way to run a modular application:
// if err := app.Run(); err != nil {
// log.Fatal(err)
// }
Run() error
// Logger retrieves the application's logger.
// This logger is used by the framework and can be used by modules
// for consistent logging throughout the application.
Logger() Logger
// SetLogger sets the application's logger.
// Should be called before module registration to ensure
// all framework operations use the new logger.
SetLogger(logger Logger)
// SetVerboseConfig enables or disables verbose configuration debugging.
// When enabled, DEBUG level logging will be performed during configuration
// processing to show which config is being processed, which key is being
// evaluated, and which attribute or key is being searched for.
SetVerboseConfig(enabled bool)
// IsVerboseConfig returns whether verbose configuration debugging is enabled.
IsVerboseConfig() bool
// ServiceIntrospector groups advanced service registry introspection helpers.
// Use this instead of adding new methods directly to Application.
ServiceIntrospector() ServiceIntrospector
}
func NewApplication ΒΆ
func NewApplication(opts ...Option) (Application, error)
NewApplication creates a new application with the provided options. This is the main entry point for the new builder API.
func NewStdApplication ΒΆ added in v1.1.0
func NewStdApplication(cp ConfigProvider, logger Logger) Application
NewStdApplication creates a new application instance with the provided configuration and logger. This is the standard way to create a modular application.
Parameters:
- cp: ConfigProvider for application-level configuration
- logger: Logger implementation for framework and module logging
The created application will have empty registries that can be populated by registering modules and services. The application must be initialized with Init() before it can be started.
Example:
// Create configuration
appConfig := &MyAppConfig{}
configProvider := modular.NewStdConfigProvider(appConfig)
// Create logger (implement modular.Logger interface)
logger := &MyLogger{}
// Create application
app := modular.NewStdApplication(configProvider, logger)
// Register modules
app.RegisterModule(&DatabaseModule{})
app.RegisterModule(&WebServerModule{})
// Run application
if err := app.Run(); err != nil {
log.Fatal(err)
}
type ApplicationBuilder ΒΆ added in v1.4.0
type ApplicationBuilder struct {
// contains filtered or unexported fields
}
ApplicationBuilder helps construct applications with various decorators and options
func (*ApplicationBuilder) Build ΒΆ added in v1.4.0
func (b *ApplicationBuilder) Build() (Application, error)
Build constructs the final application with all decorators applied
type ApplicationDecorator ΒΆ added in v1.4.0
type ApplicationDecorator interface {
Application
// GetInnerApplication returns the wrapped application
GetInnerApplication() Application
}
ApplicationDecorator defines the interface for decorating applications. Decorators wrap applications to add additional functionality without modifying the core application implementation.
type BaseApplicationDecorator ΒΆ added in v1.4.0
type BaseApplicationDecorator struct {
// contains filtered or unexported fields
}
BaseApplicationDecorator provides a foundation for application decorators. It implements ApplicationDecorator by forwarding all calls to the wrapped application.
func NewBaseApplicationDecorator ΒΆ added in v1.4.0
func NewBaseApplicationDecorator(inner Application) *BaseApplicationDecorator
NewBaseApplicationDecorator creates a new base decorator wrapping the given application.
func (*BaseApplicationDecorator) ConfigProvider ΒΆ added in v1.4.0
func (d *BaseApplicationDecorator) ConfigProvider() ConfigProvider
func (*BaseApplicationDecorator) ConfigSections ΒΆ added in v1.4.0
func (d *BaseApplicationDecorator) ConfigSections() map[string]ConfigProvider
func (*BaseApplicationDecorator) GetConfigSection ΒΆ added in v1.4.0
func (d *BaseApplicationDecorator) GetConfigSection(section string) (ConfigProvider, error)
func (*BaseApplicationDecorator) GetInnerApplication ΒΆ added in v1.4.0
func (d *BaseApplicationDecorator) GetInnerApplication() Application
GetInnerApplication returns the wrapped application
func (*BaseApplicationDecorator) GetObservers ΒΆ added in v1.4.0
func (d *BaseApplicationDecorator) GetObservers() []ObserverInfo
func (*BaseApplicationDecorator) GetService ΒΆ added in v1.4.0
func (d *BaseApplicationDecorator) GetService(name string, target any) error
func (*BaseApplicationDecorator) GetTenantConfig ΒΆ added in v1.4.0
func (d *BaseApplicationDecorator) GetTenantConfig(tenantID TenantID, section string) (ConfigProvider, error)
func (*BaseApplicationDecorator) GetTenantService ΒΆ added in v1.4.0
func (d *BaseApplicationDecorator) GetTenantService() (TenantService, error)
TenantAware methods - if inner supports TenantApplication interface
func (*BaseApplicationDecorator) Init ΒΆ added in v1.4.0
func (d *BaseApplicationDecorator) Init() error
func (*BaseApplicationDecorator) IsVerboseConfig ΒΆ added in v1.4.0
func (d *BaseApplicationDecorator) IsVerboseConfig() bool
func (*BaseApplicationDecorator) Logger ΒΆ added in v1.4.0
func (d *BaseApplicationDecorator) Logger() Logger
func (*BaseApplicationDecorator) NotifyObservers ΒΆ added in v1.4.0
func (d *BaseApplicationDecorator) NotifyObservers(ctx context.Context, event cloudevents.Event) error
func (*BaseApplicationDecorator) RegisterConfigSection ΒΆ added in v1.4.0
func (d *BaseApplicationDecorator) RegisterConfigSection(section string, cp ConfigProvider)
func (*BaseApplicationDecorator) RegisterModule ΒΆ added in v1.4.0
func (d *BaseApplicationDecorator) RegisterModule(module Module)
func (*BaseApplicationDecorator) RegisterObserver ΒΆ added in v1.4.0
func (d *BaseApplicationDecorator) RegisterObserver(observer Observer, eventTypes ...string) error
Observer methods - if inner supports Subject interface
func (*BaseApplicationDecorator) RegisterService ΒΆ added in v1.4.0
func (d *BaseApplicationDecorator) RegisterService(name string, service any) error
func (*BaseApplicationDecorator) Run ΒΆ added in v1.4.0
func (d *BaseApplicationDecorator) Run() error
func (*BaseApplicationDecorator) ServiceIntrospector ΒΆ added in v1.4.2
func (d *BaseApplicationDecorator) ServiceIntrospector() ServiceIntrospector
ServiceIntrospector forwards to the inner application's ServiceIntrospector implementation.
func (*BaseApplicationDecorator) SetLogger ΒΆ added in v1.4.0
func (d *BaseApplicationDecorator) SetLogger(logger Logger)
func (*BaseApplicationDecorator) SetVerboseConfig ΒΆ added in v1.4.0
func (d *BaseApplicationDecorator) SetVerboseConfig(enabled bool)
func (*BaseApplicationDecorator) Start ΒΆ added in v1.4.0
func (d *BaseApplicationDecorator) Start() error
func (*BaseApplicationDecorator) Stop ΒΆ added in v1.4.0
func (d *BaseApplicationDecorator) Stop() error
func (*BaseApplicationDecorator) SvcRegistry ΒΆ added in v1.4.0
func (d *BaseApplicationDecorator) SvcRegistry() ServiceRegistry
func (*BaseApplicationDecorator) UnregisterObserver ΒΆ added in v1.4.0
func (d *BaseApplicationDecorator) UnregisterObserver(observer Observer) error
func (*BaseApplicationDecorator) WithTenant ΒΆ added in v1.4.0
func (d *BaseApplicationDecorator) WithTenant(tenantID TenantID) (*TenantContext, error)
type BaseConfigOptions ΒΆ added in v1.4.1
type BaseConfigOptions struct {
// ConfigDir is the root directory containing base/ and environments/ subdirectories
ConfigDir string
// Environment specifies which environment overrides to apply (e.g., "prod", "staging", "dev")
Environment string
// Enabled determines whether base config support is active
Enabled bool
}
BaseConfigOptions holds configuration for base config support
var BaseConfigSettings BaseConfigOptions
BaseConfigSettings holds the global base config settings
type BaseLoggerDecorator ΒΆ added in v1.4.1
type BaseLoggerDecorator struct {
// contains filtered or unexported fields
}
BaseLoggerDecorator provides a foundation for logger decorators. It implements LoggerDecorator by forwarding all calls to the wrapped logger.
func NewBaseLoggerDecorator ΒΆ added in v1.4.1
func NewBaseLoggerDecorator(inner Logger) *BaseLoggerDecorator
NewBaseLoggerDecorator creates a new base decorator wrapping the given logger.
func (*BaseLoggerDecorator) Debug ΒΆ added in v1.4.1
func (d *BaseLoggerDecorator) Debug(msg string, args ...any)
func (*BaseLoggerDecorator) Error ΒΆ added in v1.4.1
func (d *BaseLoggerDecorator) Error(msg string, args ...any)
func (*BaseLoggerDecorator) GetInnerLogger ΒΆ added in v1.4.1
func (d *BaseLoggerDecorator) GetInnerLogger() Logger
GetInnerLogger returns the wrapped logger
func (*BaseLoggerDecorator) Info ΒΆ added in v1.4.1
func (d *BaseLoggerDecorator) Info(msg string, args ...any)
func (*BaseLoggerDecorator) Warn ΒΆ added in v1.4.1
func (d *BaseLoggerDecorator) Warn(msg string, args ...any)
type CloudEvent ΒΆ added in v1.4.0
type CloudEvent = cloudevents.Event
CloudEvent is an alias for the CloudEvents Event type for convenience
type ComplexFeeder ΒΆ
ComplexFeeder extends the basic Feeder interface with additional functionality for complex configuration scenarios
func GetBaseConfigComplexFeeder ΒΆ added in v1.4.1
func GetBaseConfigComplexFeeder() ComplexFeeder
GetBaseConfigComplexFeeder returns a BaseConfigFeeder as ComplexFeeder if base config is enabled
type Config ΒΆ
type Config struct {
// Feeders contains all the registered configuration feeders
Feeders []Feeder
// StructKeys maps struct identifiers to their configuration objects.
// Used internally to track which configuration structures have been processed.
StructKeys map[string]interface{}
// VerboseDebug enables detailed logging during configuration processing
VerboseDebug bool
// Logger is used for verbose debug logging
Logger Logger
// FieldTracker tracks which fields are populated by which feeders
FieldTracker FieldTracker
}
Config represents a configuration builder that can combine multiple feeders and structures. It provides functionality for the modular framework to coordinate configuration loading.
The Config builder allows you to:
- Add multiple configuration sources (files, environment, etc.)
- Combine configuration from different feeders
- Apply configuration to multiple struct targets
- Track which structs have been configured
- Enable verbose debugging for configuration processing
- Track field-level population details
func NewConfig ΒΆ
func NewConfig() *Config
NewConfig creates a new configuration builder. The returned Config can be used to set up complex configuration scenarios involving multiple sources and target structures.
Example:
cfg := modular.NewConfig() cfg.AddFeeder(modular.ConfigFeeders[0]) // Add file feeder cfg.AddStruct(&myConfig) // Add target struct err := cfg.Feed() // Load configuration
func (*Config) AddFeeder ΒΆ added in v1.3.3
AddFeeder adds a configuration feeder to support verbose debugging and field tracking
func (*Config) AddStructKey ΒΆ
AddStructKey adds a structure with a key to the configuration
func (*Config) FeedWithModuleContext ΒΆ added in v1.4.0
FeedWithModuleContext feeds a single configuration structure with module context information This allows module-aware feeders to customize their behavior based on the module name
func (*Config) SetFieldTracker ΒΆ added in v1.3.4
func (c *Config) SetFieldTracker(tracker FieldTracker) *Config
SetFieldTracker sets the field tracker for capturing field population details
type ConfigDecorator ΒΆ added in v1.4.0
type ConfigDecorator interface {
// DecorateConfig takes a base config provider and returns a decorated one
DecorateConfig(base ConfigProvider) ConfigProvider
// Name returns the decorator name for debugging
Name() string
}
ConfigDecorator defines the interface for decorating configuration providers. Config decorators can modify, enhance, or validate configuration during loading.
func InstanceAwareConfig ΒΆ added in v1.4.0
func InstanceAwareConfig() ConfigDecorator
InstanceAwareConfig creates an instance-aware configuration decorator
func TenantAwareConfigDecorator ΒΆ added in v1.4.0
func TenantAwareConfigDecorator(loader TenantLoader) ConfigDecorator
TenantAwareConfigDecorator creates a tenant-aware configuration decorator
type ConfigProvider ΒΆ
type ConfigProvider interface {
// GetConfig returns the configuration object.
// The returned value should be a pointer to a struct that represents
// the configuration schema. Modules typically type-assert this to
// their expected configuration type.
//
// Example:
// cfg := provider.GetConfig().(*MyModuleConfig)
GetConfig() any
}
ConfigProvider defines the interface for providing configuration objects. Configuration providers encapsulate configuration data and make it available to modules and the application framework.
The framework supports multiple configuration sources (files, environment variables, command-line flags) and formats (JSON, YAML, TOML) through different providers.
type ConfigSetup ΒΆ added in v1.0.0
type ConfigSetup interface {
Setup() error
}
ConfigSetup is an interface that configs can implement to perform additional setup after being populated by feeders
type ConfigValidator ΒΆ added in v1.2.2
type ConfigValidator interface {
// Validate validates the configuration and returns an error if invalid.
// This method is called automatically by the framework after configuration
// loading and default value processing. It should return a descriptive
// error if the configuration is invalid.
Validate() error
}
ConfigValidator is an interface for configuration validation. Configuration structs can implement this interface to provide custom validation logic beyond the standard required field checking.
The framework automatically calls Validate() on configuration objects that implement this interface during module initialization.
Example implementation:
type MyConfig struct {
Host string `json:"host" required:"true"`
Port int `json:"port" default:"8080" validate:"range:1024-65535"`
}
func (c *MyConfig) Validate() error {
if c.Port < 1024 || c.Port > 65535 {
return fmt.Errorf("port must be between 1024 and 65535")
}
return nil
}
type Configurable ΒΆ added in v1.2.0
type Configurable interface {
// RegisterConfig registers configuration requirements with the application.
// This method is called during application initialization before Init().
//
// Implementation should:
// - Define the configuration structure
// - Register the configuration section with app.RegisterConfigSection()
// - Set up any configuration validation rules
//
// Example:
// func (m *MyModule) RegisterConfig(app Application) error {
// cfg := &MyModuleConfig{}
// provider := modular.NewStdConfigProvider(cfg)
// app.RegisterConfigSection(m.Name(), provider)
// return nil
// }
RegisterConfig(app Application) error
}
Configurable is an interface for modules that can have configuration. Modules implementing this interface can register configuration sections with the application, allowing them to receive typed configuration data.
The configuration system supports multiple formats (JSON, YAML, TOML) and multiple sources (files, environment variables, etc.).
type Constructable ΒΆ added in v1.2.0
type Constructable interface {
// Constructor returns a function to construct this module with dependency injection.
// The returned function should have the signature:
// func(app Application, services map[string]any) (Module, error)
//
// The services map contains all services that this module declared as requirements.
// The constructor can also accept individual service types as parameters, and
// the framework will automatically provide them based on type matching.
//
// Example:
// func (m *WebModule) Constructor() ModuleConstructor {
// return func(app Application, services map[string]any) (Module, error) {
// db := services["database"].(Database)
// return NewWebModule(db), nil
// }
// }
Constructor() ModuleConstructor
}
Constructable is an interface for modules that support constructor-based dependency injection. This is an advanced feature that allows modules to be reconstructed with their dependencies automatically injected as constructor parameters.
This is useful when a module needs its dependencies available during construction rather than after initialization, or when using dependency injection frameworks.
type DefaultFieldTracker ΒΆ added in v1.3.4
type DefaultFieldTracker struct {
FieldPopulations []FieldPopulation
// contains filtered or unexported fields
}
DefaultFieldTracker is a basic implementation of FieldTracker
func NewDefaultFieldTracker ΒΆ added in v1.3.4
func NewDefaultFieldTracker() *DefaultFieldTracker
NewDefaultFieldTracker creates a new default field tracker
func (*DefaultFieldTracker) GetFieldPopulation ΒΆ added in v1.3.4
func (t *DefaultFieldTracker) GetFieldPopulation(fieldPath string) *FieldPopulation
GetFieldPopulation returns the population info for a specific field path It returns the first population found for the given field path
func (*DefaultFieldTracker) GetMostRelevantFieldPopulation ΒΆ added in v1.4.2
func (t *DefaultFieldTracker) GetMostRelevantFieldPopulation(fieldPath string) *FieldPopulation
GetMostRelevantFieldPopulation returns the population info for a specific field path It returns the last population that actually set a non-nil value
func (*DefaultFieldTracker) GetPopulationsByFeeder ΒΆ added in v1.3.4
func (t *DefaultFieldTracker) GetPopulationsByFeeder(feederType string) []FieldPopulation
GetPopulationsByFeeder returns all field populations by a specific feeder type
func (*DefaultFieldTracker) GetPopulationsBySource ΒΆ added in v1.3.4
func (t *DefaultFieldTracker) GetPopulationsBySource(sourceType string) []FieldPopulation
GetPopulationsBySource returns all field populations by a specific source type
func (*DefaultFieldTracker) RecordFieldPopulation ΒΆ added in v1.3.4
func (t *DefaultFieldTracker) RecordFieldPopulation(fp FieldPopulation)
RecordFieldPopulation records a field population event
func (*DefaultFieldTracker) SetLogger ΒΆ added in v1.3.4
func (t *DefaultFieldTracker) SetLogger(logger Logger)
SetLogger sets the logger for the tracker
type DependencyAware ΒΆ added in v1.2.0
type DependencyAware interface {
// Dependencies returns names of other modules this module depends on.
// The returned slice should contain the exact names returned by
// the Name() method of the dependency modules.
//
// Dependencies are initialized before this module during application startup.
// If any dependency is missing, application initialization will fail.
//
// Example:
// func (m *WebModule) Dependencies() []string {
// return []string{"database", "auth", "cache"}
// }
Dependencies() []string
}
DependencyAware is an interface for modules that depend on other modules. The framework uses this information to determine initialization order, ensuring dependencies are initialized before dependent modules.
Dependencies are resolved by module name and must be exact matches. Circular dependencies will cause initialization to fail.
type DependencyEdge ΒΆ added in v1.4.2
type DependencyEdge struct {
From string
To string
Type EdgeType
// For interface-based dependencies, show which interface is involved
InterfaceType reflect.Type
ServiceName string
}
DependencyEdge represents a dependency edge with its source type
type DualWriterLoggerDecorator ΒΆ added in v1.4.1
type DualWriterLoggerDecorator struct {
*BaseLoggerDecorator
// contains filtered or unexported fields
}
DualWriterLoggerDecorator logs to two destinations simultaneously. This decorator forwards all log calls to both the primary logger and a secondary logger.
func NewDualWriterLoggerDecorator ΒΆ added in v1.4.1
func NewDualWriterLoggerDecorator(primary, secondary Logger) *DualWriterLoggerDecorator
NewDualWriterLoggerDecorator creates a decorator that logs to both primary and secondary loggers.
func (*DualWriterLoggerDecorator) Debug ΒΆ added in v1.4.1
func (d *DualWriterLoggerDecorator) Debug(msg string, args ...any)
func (*DualWriterLoggerDecorator) Error ΒΆ added in v1.4.1
func (d *DualWriterLoggerDecorator) Error(msg string, args ...any)
func (*DualWriterLoggerDecorator) Info ΒΆ added in v1.4.1
func (d *DualWriterLoggerDecorator) Info(msg string, args ...any)
func (*DualWriterLoggerDecorator) Warn ΒΆ added in v1.4.1
func (d *DualWriterLoggerDecorator) Warn(msg string, args ...any)
type EnhancedServiceRegistry ΒΆ added in v1.4.2
type EnhancedServiceRegistry struct {
// contains filtered or unexported fields
}
EnhancedServiceRegistry provides enhanced service registry functionality that tracks module associations and handles automatic conflict resolution.
func NewEnhancedServiceRegistry ΒΆ added in v1.4.2
func NewEnhancedServiceRegistry() *EnhancedServiceRegistry
NewEnhancedServiceRegistry creates a new enhanced service registry.
func (*EnhancedServiceRegistry) AsServiceRegistry ΒΆ added in v1.4.2
func (r *EnhancedServiceRegistry) AsServiceRegistry() ServiceRegistry
AsServiceRegistry returns a backwards-compatible ServiceRegistry view.
func (*EnhancedServiceRegistry) ClearCurrentModule ΒΆ added in v1.4.2
func (r *EnhancedServiceRegistry) ClearCurrentModule()
ClearCurrentModule clears the current module context.
func (*EnhancedServiceRegistry) GetService ΒΆ added in v1.4.2
func (r *EnhancedServiceRegistry) GetService(name string) (any, bool)
GetService retrieves a service by name.
func (*EnhancedServiceRegistry) GetServiceEntry ΒΆ added in v1.4.2
func (r *EnhancedServiceRegistry) GetServiceEntry(name string) (*ServiceRegistryEntry, bool)
GetServiceEntry retrieves the full service registry entry.
func (*EnhancedServiceRegistry) GetServicesByInterface ΒΆ added in v1.4.2
func (r *EnhancedServiceRegistry) GetServicesByInterface(interfaceType reflect.Type) []*ServiceRegistryEntry
GetServicesByInterface returns all services that implement the given interface.
func (*EnhancedServiceRegistry) GetServicesByModule ΒΆ added in v1.4.2
func (r *EnhancedServiceRegistry) GetServicesByModule(moduleName string) []string
GetServicesByModule returns all services provided by a specific module.
func (*EnhancedServiceRegistry) RegisterService ΒΆ added in v1.4.2
func (r *EnhancedServiceRegistry) RegisterService(name string, service any) (string, error)
RegisterService registers a service with automatic conflict resolution. If a service name conflicts, it will automatically append module information.
func (*EnhancedServiceRegistry) SetCurrentModule ΒΆ added in v1.4.2
func (r *EnhancedServiceRegistry) SetCurrentModule(module Module)
SetCurrentModule sets the module that is currently being initialized. This is used to track which module is registering services.
type EventValidationObserver ΒΆ added in v1.4.1
type EventValidationObserver struct {
// contains filtered or unexported fields
}
EventValidationObserver is a special observer that tracks which events have been emitted and can validate against a whitelist of expected events. This is primarily used in testing to ensure all module events are emitted.
func NewEventValidationObserver ΒΆ added in v1.4.1
func NewEventValidationObserver(id string, expectedEvents []string) *EventValidationObserver
NewEventValidationObserver creates a new observer that validates events against an expected list. This is useful for testing event completeness.
func (*EventValidationObserver) GetAllEvents ΒΆ added in v1.4.1
func (v *EventValidationObserver) GetAllEvents() []cloudevents.Event
GetAllEvents returns all events that were captured by this observer.
func (*EventValidationObserver) GetMissingEvents ΒΆ added in v1.4.1
func (v *EventValidationObserver) GetMissingEvents() []string
GetMissingEvents returns a list of expected events that were not emitted.
func (*EventValidationObserver) GetUnexpectedEvents ΒΆ added in v1.4.1
func (v *EventValidationObserver) GetUnexpectedEvents() []string
GetUnexpectedEvents returns a list of emitted events that were not expected.
func (*EventValidationObserver) ObserverID ΒΆ added in v1.4.1
func (v *EventValidationObserver) ObserverID() string
ObserverID implements the Observer interface.
func (*EventValidationObserver) OnEvent ΒΆ added in v1.4.1
func (v *EventValidationObserver) OnEvent(ctx context.Context, event cloudevents.Event) error
OnEvent implements the Observer interface and tracks emitted events.
func (*EventValidationObserver) Reset ΒΆ added in v1.4.1
func (v *EventValidationObserver) Reset()
Reset clears all captured events for reuse in new test scenarios.
type Feeder ΒΆ
type Feeder interface {
// Feed gets a struct and feeds it using configuration data.
Feed(structure interface{}) error
}
Feeder defines the interface for configuration feeders that provide configuration data.
type FieldPopulation ΒΆ added in v1.3.4
type FieldPopulation struct {
FieldPath string // Full path to the field (e.g., "Connections.primary.DSN")
FieldName string // Name of the field
FieldType string // Type of the field
FeederType string // Type of feeder that populated it
SourceType string // Type of source (env, yaml, etc.)
SourceKey string // Source key that was used (e.g., "DB_PRIMARY_DSN")
Value interface{} // Value that was set
InstanceKey string // Instance key for instance-aware fields
SearchKeys []string // All keys that were searched for this field
FoundKey string // The key that was actually found
}
FieldPopulation represents a single field population event
type FieldTracker ΒΆ added in v1.3.4
type FieldTracker interface {
// RecordFieldPopulation records that a field was populated by a feeder
RecordFieldPopulation(fp FieldPopulation)
// SetLogger sets the logger for the tracker
SetLogger(logger Logger)
}
FieldTracker interface allows feeders to report which fields they populate
type FieldTrackerBridge ΒΆ added in v1.3.4
type FieldTrackerBridge struct {
// contains filtered or unexported fields
}
FieldTrackerBridge adapts between the main package's FieldTracker interface and the feeders package's FieldTracker interface
func NewFieldTrackerBridge ΒΆ added in v1.3.4
func NewFieldTrackerBridge(mainTracker FieldTracker) *FieldTrackerBridge
NewFieldTrackerBridge creates a new bridge adapter
func (*FieldTrackerBridge) RecordFieldPopulation ΒΆ added in v1.3.4
func (b *FieldTrackerBridge) RecordFieldPopulation(fp feeders.FieldPopulation)
RecordFieldPopulation implements the feeders.FieldTracker interface by converting feeders.FieldPopulation to the main package's FieldPopulation
type FieldTrackingFeeder ΒΆ added in v1.3.4
type FieldTrackingFeeder interface {
// SetFieldTracker sets the field tracker for this feeder
SetFieldTracker(tracker FieldTracker)
}
FieldTrackingFeeder interface allows feeders to support field tracking
type FileBasedTenantConfigLoader ΒΆ added in v1.1.0
type FileBasedTenantConfigLoader struct {
// contains filtered or unexported fields
}
FileBasedTenantConfigLoader implements TenantConfigLoader for file-based tenant configurations
func DefaultTenantConfigLoader ΒΆ added in v1.1.0
func DefaultTenantConfigLoader(configDir string) *FileBasedTenantConfigLoader
DefaultTenantConfigLoader creates a loader with default configuration
func NewFileBasedTenantConfigLoader ΒΆ added in v1.1.0
func NewFileBasedTenantConfigLoader(params TenantConfigParams) *FileBasedTenantConfigLoader
NewFileBasedTenantConfigLoader creates a new file-based tenant config loader
func (*FileBasedTenantConfigLoader) LoadTenantConfigurations ΒΆ added in v1.1.0
func (l *FileBasedTenantConfigLoader) LoadTenantConfigurations(app Application, tenantService TenantService) error
LoadTenantConfigurations loads tenant configurations from files
type FilterLoggerDecorator ΒΆ added in v1.4.1
type FilterLoggerDecorator struct {
*BaseLoggerDecorator
// contains filtered or unexported fields
}
FilterLoggerDecorator filters log events based on configurable criteria. This decorator can filter by log level, message content, or key-value pairs.
func NewFilterLoggerDecorator ΒΆ added in v1.4.1
func NewFilterLoggerDecorator(inner Logger, messageFilters []string, keyFilters map[string]string, levelFilters map[string]bool) *FilterLoggerDecorator
NewFilterLoggerDecorator creates a decorator that filters log events. If levelFilters is nil, all levels (info, error, warn, debug) are allowed by default.
func (*FilterLoggerDecorator) Debug ΒΆ added in v1.4.1
func (d *FilterLoggerDecorator) Debug(msg string, args ...any)
func (*FilterLoggerDecorator) Error ΒΆ added in v1.4.1
func (d *FilterLoggerDecorator) Error(msg string, args ...any)
func (*FilterLoggerDecorator) Info ΒΆ added in v1.4.1
func (d *FilterLoggerDecorator) Info(msg string, args ...any)
func (*FilterLoggerDecorator) Warn ΒΆ added in v1.4.1
func (d *FilterLoggerDecorator) Warn(msg string, args ...any)
type FunctionalObserver ΒΆ added in v1.4.0
type FunctionalObserver struct {
// contains filtered or unexported fields
}
FunctionalObserver provides a simple way to create observers using functions. This is useful for quick observer creation without defining full structs.
func (*FunctionalObserver) ObserverID ΒΆ added in v1.4.0
func (f *FunctionalObserver) ObserverID() string
ObserverID implements the Observer interface by returning the observer ID.
func (*FunctionalObserver) OnEvent ΒΆ added in v1.4.0
func (f *FunctionalObserver) OnEvent(ctx context.Context, event cloudevents.Event) error
OnEvent implements the Observer interface by calling the handler function.
type InstanceAwareConfigProvider ΒΆ added in v1.3.1
type InstanceAwareConfigProvider struct {
// contains filtered or unexported fields
}
InstanceAwareConfigProvider handles configuration for multiple instances of the same type
func NewInstanceAwareConfigProvider ΒΆ added in v1.3.1
func NewInstanceAwareConfigProvider(cfg any, prefixFunc InstancePrefixFunc) *InstanceAwareConfigProvider
NewInstanceAwareConfigProvider creates a new instance-aware configuration provider
func (*InstanceAwareConfigProvider) GetConfig ΒΆ added in v1.3.1
func (p *InstanceAwareConfigProvider) GetConfig() any
GetConfig returns the configuration object
func (*InstanceAwareConfigProvider) GetInstancePrefixFunc ΒΆ added in v1.3.1
func (p *InstanceAwareConfigProvider) GetInstancePrefixFunc() InstancePrefixFunc
GetInstancePrefixFunc returns the instance prefix function
type InstanceAwareConfigSupport ΒΆ added in v1.3.1
type InstanceAwareConfigSupport interface {
// GetInstanceConfigs returns a map of instance configurations that should be fed with instance-aware feeders
GetInstanceConfigs() map[string]interface{}
}
InstanceAwareConfigSupport indicates that a configuration supports instance-aware feeding
type InstanceAwareFeeder ΒΆ added in v1.3.1
type InstanceAwareFeeder interface {
ComplexFeeder
// FeedInstances feeds multiple instances from a map[string]ConfigType
FeedInstances(instances interface{}) error
}
InstanceAwareFeeder provides functionality for feeding multiple instances of the same configuration type
func NewInstanceAwareEnvFeeder ΒΆ added in v1.3.1
func NewInstanceAwareEnvFeeder(prefixFunc InstancePrefixFunc) InstanceAwareFeeder
NewInstanceAwareEnvFeeder creates a new instance-aware environment variable feeder
type InstancePrefixFunc ΒΆ added in v1.3.1
type InstancePrefixFunc = feeders.InstancePrefixFunc
InstancePrefixFunc is a function that generates a prefix for an instance key
type InterfaceMatch ΒΆ added in v1.4.2
type InterfaceMatch struct {
Consumer string
Provider string
InterfaceType reflect.Type
ServiceName string
Required bool
}
InterfaceMatch represents a consumer-provider match for an interface-based dependency
type LevelModifierLoggerDecorator ΒΆ added in v1.4.1
type LevelModifierLoggerDecorator struct {
*BaseLoggerDecorator
// contains filtered or unexported fields
}
LevelModifierLoggerDecorator modifies the log level of events. This decorator can promote or demote log levels based on configured rules.
func NewLevelModifierLoggerDecorator ΒΆ added in v1.4.1
func NewLevelModifierLoggerDecorator(inner Logger, levelMappings map[string]string) *LevelModifierLoggerDecorator
NewLevelModifierLoggerDecorator creates a decorator that modifies log levels.
func (*LevelModifierLoggerDecorator) Debug ΒΆ added in v1.4.1
func (d *LevelModifierLoggerDecorator) Debug(msg string, args ...any)
func (*LevelModifierLoggerDecorator) Error ΒΆ added in v1.4.1
func (d *LevelModifierLoggerDecorator) Error(msg string, args ...any)
func (*LevelModifierLoggerDecorator) Info ΒΆ added in v1.4.1
func (d *LevelModifierLoggerDecorator) Info(msg string, args ...any)
func (*LevelModifierLoggerDecorator) Warn ΒΆ added in v1.4.1
func (d *LevelModifierLoggerDecorator) Warn(msg string, args ...any)
type LoadAppConfigFunc ΒΆ added in v1.0.0
type LoadAppConfigFunc func(*StdApplication) error
LoadAppConfigFunc is the function type for loading application configuration. This function is responsible for loading configuration data into the application using the registered config feeders and config sections.
The default implementation can be replaced for testing or custom configuration scenarios.
var AppConfigLoader LoadAppConfigFunc = loadAppConfig
AppConfigLoader is the default implementation that can be replaced in tests. This variable allows the configuration loading strategy to be customized, which is particularly useful for testing scenarios where you want to control how configuration is loaded.
Example of replacing for tests:
oldLoader := modular.AppConfigLoader
defer func() { modular.AppConfigLoader = oldLoader }()
modular.AppConfigLoader = func(app *StdApplication) error {
// Custom test configuration loading
return nil
}
type Logger ΒΆ
type Logger interface {
// Info logs an informational message with optional key-value pairs.
// Used for normal application events like module startup, service registration, etc.
//
// Example:
// logger.Info("Module initialized", "module", "database", "version", "1.2.3")
Info(msg string, args ...any)
// Error logs an error message with optional key-value pairs.
// Used for errors that don't prevent application startup but should be noted.
//
// Example:
// logger.Error("Failed to connect to service", "service", "cache", "error", err)
Error(msg string, args ...any)
// Warn logs a warning message with optional key-value pairs.
// Used for conditions that are unusual but don't prevent normal operation.
//
// Example:
// logger.Warn("Service unavailable, using fallback", "service", "external-api")
Warn(msg string, args ...any)
// Debug logs a debug message with optional key-value pairs.
// Used for detailed diagnostic information, typically disabled in production.
//
// Example:
// logger.Debug("Dependency resolved", "from", "module1", "to", "module2")
Debug(msg string, args ...any)
}
Logger defines the interface for application logging. The modular framework uses structured logging with key-value pairs to provide consistent, parseable log output across all modules.
All framework operations (module initialization, service registration, dependency resolution, etc.) are logged using this interface, so implementing applications can control how framework logs appear.
The Logger interface uses variadic arguments in key-value pairs:
logger.Info("message", "key1", "value1", "key2", "value2")
This approach is compatible with popular structured logging libraries like slog, logrus, zap, and others.
Example implementation using Go's standard log/slog:
type SlogLogger struct {
logger *slog.Logger
}
func (l *SlogLogger) Info(msg string, args ...any) {
l.logger.Info(msg, args...)
}
func (l *SlogLogger) Error(msg string, args ...any) {
l.logger.Error(msg, args...)
}
func (l *SlogLogger) Warn(msg string, args ...any) {
l.logger.Warn(msg, args...)
}
func (l *SlogLogger) Debug(msg string, args ...any) {
l.logger.Debug(msg, args...)
}
type LoggerDecorator ΒΆ added in v1.4.1
type LoggerDecorator interface {
Logger
// GetInnerLogger returns the wrapped logger
GetInnerLogger() Logger
}
LoggerDecorator defines the interface for decorating loggers. Decorators wrap loggers to add additional functionality without modifying the core logger implementation.
type Module ΒΆ
type Module interface {
// Name returns the unique identifier for this module.
// The name is used for dependency resolution and service registration.
// It must be unique within the application and should be descriptive
// of the module's purpose.
//
// Example: "database", "auth", "httpserver", "cache"
Name() string
// Init initializes the module with the application context.
// This method is called during application initialization after
// all modules have been registered and their configurations loaded.
//
// The Init method should:
// - Validate any required configuration
// - Initialize internal state
// - Register any services this module provides
// - Prepare for Start() to be called
//
// Init is called in dependency order - modules that depend on others
// are initialized after their dependencies.
Init(app Application) error
}
Module represents a registrable component in the application. All modules must implement this interface to be managed by the application.
A module is the basic building block of a modular application. It encapsulates a specific piece of functionality and can interact with other modules through the application's service registry and configuration system.
type ModuleAwareFeeder ΒΆ added in v1.4.0
type ModuleAwareFeeder interface {
Feeder
// FeedWithModuleContext feeds configuration with module context information.
// The moduleName parameter provides the name of the module whose configuration
// is being processed, allowing the feeder to customize its behavior accordingly.
FeedWithModuleContext(structure interface{}, moduleName string) error
}
ModuleAwareFeeder provides functionality for feeders that can receive module context during configuration feeding. This allows feeders to customize behavior based on which module's configuration is being processed.
type ModuleConstructor ΒΆ
type ModuleConstructor func(app Application, services map[string]any) (Module, error)
ModuleConstructor is a function type that creates module instances with dependency injection. Constructor functions receive the application instance and a map of resolved services that the module declared as requirements.
The constructor should:
- Extract required services from the services map
- Perform any type assertions needed
- Create and return a new module instance
- Return an error if construction fails
Constructor functions enable advanced dependency injection patterns and can also accept typed parameters that the framework will resolve automatically.
type ModuleLifecyclePayload ΒΆ added in v1.4.2
type ModuleLifecyclePayload struct {
// Subject indicates whether this is a module or application lifecycle event (e.g., "module", "application").
Subject string `json:"subject"`
// Name is the module/application name.
Name string `json:"name"`
// Action is the lifecycle action (e.g., start|stop|init|register|fail|initialize|initialized).
Action string `json:"action"`
// Version optionally records the module version if available.
Version string `json:"version,omitempty"`
// Timestamp is when the lifecycle action occurred (RFC3339 in JSON output).
Timestamp time.Time `json:"timestamp"`
// Additional arbitrary metadata (kept minimal; prefer evolving the struct if fields become first-class).
Metadata map[string]interface{} `json:"metadata,omitempty"`
}
ModuleLifecyclePayload represents a structured lifecycle event for a module or the application. This provides a strongly-typed alternative to scattering lifecycle details across CloudEvent extensions. Additional routing-friendly metadata (like action) is still duplicated into a small extension for fast filtering.
type ModuleRegistry ΒΆ
ModuleRegistry represents a registry of modules keyed by their names. This is used internally by the application to manage registered modules and resolve dependencies between them.
The registry ensures each module name is unique and provides efficient lookup during dependency resolution and lifecycle management.
type ModuleWithConstructor ΒΆ
type ModuleWithConstructor interface {
Module
Constructable
}
ModuleWithConstructor defines modules that support constructor-based dependency injection. This is a convenience interface that combines Module and Constructable.
Modules implementing this interface will be reconstructed using their constructor after dependencies are resolved, allowing for cleaner dependency injection patterns.
type ObservableApplication ΒΆ added in v1.4.0
type ObservableApplication struct {
*StdApplication
// contains filtered or unexported fields
}
ObservableApplication extends StdApplication with observer pattern capabilities. This struct embeds StdApplication and adds observer management functionality. It uses CloudEvents specification for standardized event handling and interoperability.
func NewObservableApplication ΒΆ added in v1.4.0
func NewObservableApplication(cp ConfigProvider, logger Logger) *ObservableApplication
NewObservableApplication creates a new application instance with observer pattern support. This wraps the standard application with observer capabilities while maintaining all existing functionality.
func (*ObservableApplication) GetObservers ΒΆ added in v1.4.0
func (app *ObservableApplication) GetObservers() []ObserverInfo
GetObservers returns information about currently registered observers. This is useful for debugging and monitoring.
func (*ObservableApplication) Init ΒΆ added in v1.4.0
func (app *ObservableApplication) Init() error
Init initializes the application and emits lifecycle events
func (*ObservableApplication) NotifyObservers ΒΆ added in v1.4.0
func (app *ObservableApplication) NotifyObservers(ctx context.Context, event cloudevents.Event) error
NotifyObservers sends a CloudEvent to all registered observers. The notification process is non-blocking for the caller and handles observer errors gracefully.
func (*ObservableApplication) RegisterModule ΒΆ added in v1.4.0
func (app *ObservableApplication) RegisterModule(module Module)
RegisterModule registers a module and emits CloudEvent
func (*ObservableApplication) RegisterObserver ΒΆ added in v1.4.0
func (app *ObservableApplication) RegisterObserver(observer Observer, eventTypes ...string) error
RegisterObserver adds an observer to receive notifications from the application. Observers can optionally filter events by type using the eventTypes parameter. If eventTypes is empty, the observer receives all events.
func (*ObservableApplication) RegisterService ΒΆ added in v1.4.0
func (app *ObservableApplication) RegisterService(name string, service any) error
RegisterService registers a service and emits CloudEvent
func (*ObservableApplication) Start ΒΆ added in v1.4.0
func (app *ObservableApplication) Start() error
Start starts the application and emits lifecycle events
func (*ObservableApplication) Stop ΒΆ added in v1.4.0
func (app *ObservableApplication) Stop() error
Stop stops the application and emits lifecycle events
func (*ObservableApplication) UnregisterObserver ΒΆ added in v1.4.0
func (app *ObservableApplication) UnregisterObserver(observer Observer) error
UnregisterObserver removes an observer from receiving notifications. This method is idempotent and won't error if the observer wasn't registered.
type ObservableDecorator ΒΆ added in v1.4.0
type ObservableDecorator struct {
*BaseApplicationDecorator
// contains filtered or unexported fields
}
ObservableDecorator wraps an application to add observer pattern capabilities. It emits CloudEvents for application lifecycle events and manages observers.
func NewObservableDecorator ΒΆ added in v1.4.0
func NewObservableDecorator(inner Application, observers ...ObserverFunc) *ObservableDecorator
NewObservableDecorator creates a new observable decorator with the provided observers
func (*ObservableDecorator) AddObserver ΒΆ added in v1.4.0
func (d *ObservableDecorator) AddObserver(observer ObserverFunc)
AddObserver adds a new observer function
func (*ObservableDecorator) Init ΒΆ added in v1.4.0
func (d *ObservableDecorator) Init() error
Init overrides the base Init method to emit lifecycle events
func (*ObservableDecorator) RemoveObserver ΒΆ added in v1.4.0
func (d *ObservableDecorator) RemoveObserver(observer ObserverFunc)
RemoveObserver removes an observer function (not commonly used with functional observers)
func (*ObservableDecorator) Start ΒΆ added in v1.4.0
func (d *ObservableDecorator) Start() error
Start overrides the base Start method to emit lifecycle events
func (*ObservableDecorator) Stop ΒΆ added in v1.4.0
func (d *ObservableDecorator) Stop() error
Stop overrides the base Stop method to emit lifecycle events
type ObservableModule ΒΆ added in v1.4.0
type ObservableModule interface {
Module
// RegisterObservers is called during module initialization to allow
// the module to register as an observer for events it's interested in.
// The subject parameter is typically the application itself.
RegisterObservers(subject Subject) error
// EmitEvent allows modules to emit their own CloudEvents.
// This should typically delegate to the application's NotifyObservers method.
EmitEvent(ctx context.Context, event cloudevents.Event) error
// GetRegisteredEventTypes returns a list of all event types this module
// can emit. This is used for validation in testing to ensure all events
// are properly tested and emitted during execution.
GetRegisteredEventTypes() []string
}
ObservableModule is an optional interface that modules can implement to participate in the observer pattern. Modules implementing this interface can emit their own events and register observers for events they're interested in. All events use the CloudEvents specification for standardization.
type Observer ΒΆ added in v1.4.0
type Observer interface {
// OnEvent is called when an event occurs that the observer is interested in.
// The context can be used for cancellation and timeouts.
// Observers should handle events quickly to avoid blocking other observers.
OnEvent(ctx context.Context, event cloudevents.Event) error
// ObserverID returns a unique identifier for this observer.
// This ID is used for registration tracking and debugging.
ObserverID() string
}
Observer defines the interface for objects that want to be notified of events. Observers register with Subjects to receive notifications when events occur. This follows the traditional Observer pattern where observers are notified of state changes or events in subjects they're watching. Events use the CloudEvents specification for standardization.
func NewFunctionalObserver ΒΆ added in v1.4.0
func NewFunctionalObserver(id string, handler func(ctx context.Context, event cloudevents.Event) error) Observer
NewFunctionalObserver creates a new observer that uses the provided function to handle events. This is a convenience constructor for simple use cases.
type ObserverFunc ΒΆ added in v1.4.0
type ObserverFunc func(ctx context.Context, event cloudevents.Event) error
ObserverFunc is a functional observer that can be registered with the application
type ObserverInfo ΒΆ added in v1.4.0
type ObserverInfo struct {
// ID is the unique identifier of the observer
ID string `json:"id"`
// EventTypes are the event types this observer is subscribed to.
// Empty slice means all events.
EventTypes []string `json:"eventTypes"`
// RegisteredAt indicates when the observer was registered
RegisteredAt time.Time `json:"registeredAt"`
}
ObserverInfo provides information about a registered observer. This is used for debugging, monitoring, and administrative interfaces.
type Option ΒΆ added in v1.4.0
type Option func(*ApplicationBuilder) error
Option represents a functional option for configuring applications
func WithBaseApplication ΒΆ added in v1.4.0
func WithBaseApplication(base Application) Option
WithBaseApplication sets the base application to decorate
func WithConfigDecorators ΒΆ added in v1.4.0
func WithConfigDecorators(decorators ...ConfigDecorator) Option
WithConfigDecorators adds configuration decorators
func WithConfigProvider ΒΆ added in v1.4.0
func WithConfigProvider(provider ConfigProvider) Option
WithConfigProvider sets the configuration provider
func WithLogger ΒΆ added in v1.4.0
WithLogger sets the logger for the application
func WithModules ΒΆ added in v1.4.0
WithModules adds modules to the application
func WithObserver ΒΆ added in v1.4.0
func WithObserver(observers ...ObserverFunc) Option
WithObserver enables observer pattern and adds observer functions
func WithTenantAware ΒΆ added in v1.4.0
func WithTenantAware(loader TenantLoader) Option
WithTenantAware enables tenant-aware functionality with the provided loader
type PrefixLoggerDecorator ΒΆ added in v1.4.1
type PrefixLoggerDecorator struct {
*BaseLoggerDecorator
// contains filtered or unexported fields
}
PrefixLoggerDecorator adds a prefix to all log messages. This decorator automatically prepends a configured prefix to every log message.
func NewPrefixLoggerDecorator ΒΆ added in v1.4.1
func NewPrefixLoggerDecorator(inner Logger, prefix string) *PrefixLoggerDecorator
NewPrefixLoggerDecorator creates a decorator that adds a prefix to log messages.
func (*PrefixLoggerDecorator) Debug ΒΆ added in v1.4.1
func (d *PrefixLoggerDecorator) Debug(msg string, args ...any)
func (*PrefixLoggerDecorator) Error ΒΆ added in v1.4.1
func (d *PrefixLoggerDecorator) Error(msg string, args ...any)
func (*PrefixLoggerDecorator) Info ΒΆ added in v1.4.1
func (d *PrefixLoggerDecorator) Info(msg string, args ...any)
func (*PrefixLoggerDecorator) Warn ΒΆ added in v1.4.1
func (d *PrefixLoggerDecorator) Warn(msg string, args ...any)
type ServiceAware ΒΆ added in v1.2.0
type ServiceAware interface {
// ProvidesServices returns a list of services provided by this module.
// These services will be registered in the application's service registry
// after the module is initialized, making them available to other modules.
//
// Each ServiceProvider should specify:
// - Name: unique identifier for the service
// - Instance: the actual service implementation
//
// Example:
// func (m *DatabaseModule) ProvidesServices() []ServiceProvider {
// return []ServiceProvider{
// {Name: "database", Instance: m.db},
// {Name: "migrator", Instance: m.migrator},
// }
// }
ProvidesServices() []ServiceProvider
// RequiresServices returns a list of services required by this module.
// These services must be provided by other modules or the application
// for this module to function correctly.
//
// Services can be matched by name or by interface. When using interface
// matching, the framework will find any service that implements the
// specified interface.
//
// Example:
// func (m *WebModule) RequiresServices() []ServiceDependency {
// return []ServiceDependency{
// {Name: "database", Required: true},
// {Name: "logger", SatisfiesInterface: reflect.TypeOf((*Logger)(nil)).Elem(), MatchByInterface: true},
// }
// }
RequiresServices() []ServiceDependency
}
ServiceAware is an interface for modules that can provide or consume services. Services enable loose coupling between modules by providing a registry for sharing functionality without direct dependencies.
Modules can both provide services for other modules to use and require services that other modules provide. The framework handles service injection automatically based on these declarations.
type ServiceDependency ΒΆ
type ServiceDependency struct {
// Name is the service identifier to lookup.
// For interface-based matching, this is used as the key in the
// injected services map but may not correspond to a registered service name.
Name string
// Required indicates whether the application should fail to start
// if this service is not available. Optional services (Required: false)
// will be silently ignored if not found.
Required bool
// Type specifies the concrete type expected for this service.
// Used for additional type checking during dependency resolution.
// Optional - if nil, no concrete type checking is performed.
Type reflect.Type
// SatisfiesInterface specifies an interface that the service must implement.
// Used with MatchByInterface to find services by interface rather than name.
// Obtain with: reflect.TypeOf((*InterfaceName)(nil)).Elem()
SatisfiesInterface reflect.Type
// MatchByInterface enables interface-based service lookup.
// When true, the framework will search for any service that implements
// SatisfiesInterface rather than looking up by exact name.
// Useful for loose coupling where modules depend on interfaces rather than specific implementations.
MatchByInterface bool
}
ServiceDependency defines a requirement for a service from another module. Dependencies can be matched either by exact name or by interface type. The framework handles dependency resolution and injection automatically.
There are two main patterns for service dependencies:
Name-based lookup: ServiceDependency{Name: "database", Required: true}
Interface-based lookup: ServiceDependency{ Name: "logger", MatchByInterface: true, SatisfiesInterface: reflect.TypeOf((*Logger)(nil)).Elem(), Required: true, }
type ServiceIntrospector ΒΆ added in v1.4.2
type ServiceIntrospector interface {
GetServicesByModule(moduleName string) []string
GetServiceEntry(serviceName string) (*ServiceRegistryEntry, bool)
GetServicesByInterface(interfaceType reflect.Type) []*ServiceRegistryEntry
}
ServiceIntrospector provides advanced service registry introspection helpers. This extension interface allows future additions without expanding Application.
type ServiceIntrospectorImpl ΒΆ added in v1.4.2
type ServiceIntrospectorImpl struct {
// contains filtered or unexported fields
}
ServiceIntrospectorImpl implements ServiceIntrospector backed by StdApplication's enhanced registry.
func (*ServiceIntrospectorImpl) GetServiceEntry ΒΆ added in v1.4.2
func (s *ServiceIntrospectorImpl) GetServiceEntry(serviceName string) (*ServiceRegistryEntry, bool)
func (*ServiceIntrospectorImpl) GetServicesByInterface ΒΆ added in v1.4.2
func (s *ServiceIntrospectorImpl) GetServicesByInterface(interfaceType reflect.Type) []*ServiceRegistryEntry
func (*ServiceIntrospectorImpl) GetServicesByModule ΒΆ added in v1.4.2
func (s *ServiceIntrospectorImpl) GetServicesByModule(moduleName string) []string
type ServiceProvider ΒΆ added in v1.0.0
type ServiceProvider struct {
// Name is the unique identifier for this service.
// Other modules reference this service by this exact name.
// Should be descriptive and follow naming conventions like "database", "logger", "cache".
Name string
// Description provides human-readable documentation for this service.
// Used for debugging and documentation purposes.
// Example: "PostgreSQL database connection pool"
Description string
// Instance is the actual service implementation.
// Can be any type - struct, interface implementation, function, etc.
// Consuming modules are responsible for type assertion.
Instance any
}
ServiceProvider defines a service offered by a module. Services are registered in the application's service registry and can be consumed by other modules that declare them as dependencies.
A service provider encapsulates:
- Name: unique identifier for service lookup
- Description: human-readable description for documentation
- Instance: the actual service implementation (interface{})
type ServiceRegistry ΒΆ
ServiceRegistry allows registration and retrieval of services by name. Services are stored as interface{} values and must be type-asserted when retrieved. The registry supports both concrete types and interfaces.
Services enable loose coupling between modules by providing a shared registry where modules can publish functionality for others to consume.
type ServiceRegistryEntry ΒΆ added in v1.4.2
type ServiceRegistryEntry struct {
// Service is the actual service instance
Service any
// ModuleName is the name of the module that provided this service
ModuleName string
// ModuleType is the reflect.Type of the module that provided this service
ModuleType reflect.Type
// OriginalName is the original name requested when registering the service
OriginalName string
// ActualName is the final name used in the registry (may be modified for uniqueness)
ActualName string
}
ServiceRegistryEntry represents an enhanced service registry entry that tracks both the service instance and its providing module.
type StandardTenantService ΒΆ added in v1.1.0
type StandardTenantService struct {
// contains filtered or unexported fields
}
StandardTenantService provides a basic implementation of the TenantService interface
func NewStandardTenantService ΒΆ added in v1.1.0
func NewStandardTenantService(logger Logger) *StandardTenantService
NewStandardTenantService creates a new tenant service
func (*StandardTenantService) GetTenantConfig ΒΆ added in v1.1.0
func (ts *StandardTenantService) GetTenantConfig(tenantID TenantID, section string) (ConfigProvider, error)
GetTenantConfig retrieves tenant-specific configuration
func (*StandardTenantService) GetTenants ΒΆ added in v1.1.0
func (ts *StandardTenantService) GetTenants() []TenantID
GetTenants returns all registered tenant IDs
func (*StandardTenantService) RegisterTenant ΒΆ added in v1.1.0
func (ts *StandardTenantService) RegisterTenant(tenantID TenantID, configs map[string]ConfigProvider) error
RegisterTenant registers a new tenant with optional initial configs
func (*StandardTenantService) RegisterTenantAwareModule ΒΆ added in v1.1.0
func (ts *StandardTenantService) RegisterTenantAwareModule(module TenantAwareModule) error
RegisterTenantAwareModule registers a module to receive tenant events
func (*StandardTenantService) RegisterTenantConfigSection ΒΆ added in v1.1.0
func (ts *StandardTenantService) RegisterTenantConfigSection( tenantID TenantID, section string, provider ConfigProvider, ) error
RegisterTenantConfigSection registers a configuration section for a specific tenant
func (*StandardTenantService) RemoveTenant ΒΆ added in v1.1.0
func (ts *StandardTenantService) RemoveTenant(tenantID TenantID) error
RemoveTenant removes a tenant and its configurations
type Startable ΒΆ added in v1.2.0
type Startable interface {
// Start begins the module's runtime operations.
// This method is called after Init() and after all modules have been initialized.
// Start is called in dependency order - dependencies start before dependents.
//
// The provided context is the application's lifecycle context. When this
// context is cancelled, the module should stop its operations gracefully.
//
// Start should be non-blocking for short-running initialization, but may
// spawn goroutines for long-running operations. Use the provided context
// to handle graceful shutdown.
//
// Example:
// func (m *HTTPServerModule) Start(ctx context.Context) error {
// go func() {
// <-ctx.Done()
// m.server.Shutdown(context.Background())
// }()
// return m.server.ListenAndServe()
// }
Start(ctx context.Context) error
}
Startable is an interface for modules that need to perform startup operations. Modules implementing this interface will have their Start method called after all modules have been initialized successfully.
Start operations typically involve:
- Starting background goroutines
- Opening network listeners
- Connecting to external services
- Beginning periodic tasks
type StdApplication ΒΆ added in v1.1.0
type StdApplication struct {
// contains filtered or unexported fields
}
StdApplication represents the core StdApplication container
func (*StdApplication) ConfigProvider ΒΆ added in v1.1.0
func (app *StdApplication) ConfigProvider() ConfigProvider
ConfigProvider retrieves the application config provider
func (*StdApplication) ConfigSections ΒΆ added in v1.1.0
func (app *StdApplication) ConfigSections() map[string]ConfigProvider
ConfigSections retrieves all registered configuration sections
func (*StdApplication) GetConfigSection ΒΆ added in v1.1.0
func (app *StdApplication) GetConfigSection(section string) (ConfigProvider, error)
GetConfigSection retrieves a configuration section
func (*StdApplication) GetService ΒΆ added in v1.1.0
func (app *StdApplication) GetService(name string, target any) error
GetService retrieves a service with type assertion
func (*StdApplication) GetTenantConfig ΒΆ added in v1.1.0
func (app *StdApplication) GetTenantConfig(tenantID TenantID, section string) (ConfigProvider, error)
GetTenantConfig retrieves configuration for a specific tenant and section
func (*StdApplication) GetTenantService ΒΆ added in v1.1.0
func (app *StdApplication) GetTenantService() (TenantService, error)
GetTenantService returns the application's tenant service if available
func (*StdApplication) Init ΒΆ added in v1.1.0
func (app *StdApplication) Init() error
Init initializes the application with the provided modules
func (*StdApplication) InitWithApp ΒΆ added in v1.4.1
func (app *StdApplication) InitWithApp(appToPass Application) error
InitWithApp initializes the application with the provided modules, using appToPass as the application instance passed to modules
func (*StdApplication) IsVerboseConfig ΒΆ added in v1.3.3
func (app *StdApplication) IsVerboseConfig() bool
IsVerboseConfig returns whether verbose configuration debugging is enabled
func (*StdApplication) Logger ΒΆ added in v1.1.0
func (app *StdApplication) Logger() Logger
Logger represents a logger
func (*StdApplication) RegisterConfigSection ΒΆ added in v1.1.0
func (app *StdApplication) RegisterConfigSection(section string, cp ConfigProvider)
RegisterConfigSection registers a configuration section with the application
func (*StdApplication) RegisterModule ΒΆ added in v1.1.0
func (app *StdApplication) RegisterModule(module Module)
RegisterModule adds a module to the application
func (*StdApplication) RegisterService ΒΆ added in v1.1.0
func (app *StdApplication) RegisterService(name string, service any) error
RegisterService adds a service with type checking
func (*StdApplication) Run ΒΆ added in v1.1.0
func (app *StdApplication) Run() error
Run starts the application and blocks until termination
func (*StdApplication) ServiceIntrospector ΒΆ added in v1.4.2
func (app *StdApplication) ServiceIntrospector() ServiceIntrospector
ServiceIntrospector returns an implementation of ServiceIntrospector.
func (*StdApplication) SetConfigFeeders ΒΆ added in v1.4.2
func (app *StdApplication) SetConfigFeeders(feeders []Feeder)
SetConfigFeeders sets per-application configuration feeders overriding the package-level ConfigFeeders for this app's Init lifecycle. Passing nil resets to use the global ConfigFeeders again.
func (*StdApplication) SetLogger ΒΆ added in v1.3.0
func (app *StdApplication) SetLogger(logger Logger)
SetLogger sets the application's logger
func (*StdApplication) SetVerboseConfig ΒΆ added in v1.3.3
func (app *StdApplication) SetVerboseConfig(enabled bool)
SetVerboseConfig enables or disables verbose configuration debugging
func (*StdApplication) Start ΒΆ added in v1.1.0
func (app *StdApplication) Start() error
Start starts the application
func (*StdApplication) Stop ΒΆ added in v1.1.0
func (app *StdApplication) Stop() error
Stop stops the application
func (*StdApplication) SvcRegistry ΒΆ added in v1.1.0
func (app *StdApplication) SvcRegistry() ServiceRegistry
SvcRegistry retrieves the service svcRegistry
func (*StdApplication) WithTenant ΒΆ added in v1.1.0
func (app *StdApplication) WithTenant(tenantID TenantID) (*TenantContext, error)
WithTenant creates a tenant context from the application context
type StdConfigProvider ΒΆ
type StdConfigProvider struct {
// contains filtered or unexported fields
}
StdConfigProvider provides a standard implementation of ConfigProvider. It wraps a configuration struct and makes it available through the ConfigProvider interface.
This is the most common way to create configuration providers for modules. Simply create your configuration struct and wrap it with NewStdConfigProvider.
func NewStdConfigProvider ΒΆ
func NewStdConfigProvider(cfg any) *StdConfigProvider
NewStdConfigProvider creates a new standard configuration provider. The cfg parameter should be a pointer to a struct that defines the configuration schema for your module.
Example:
type MyConfig struct {
Host string `json:"host" default:"localhost"`
Port int `json:"port" default:"8080"`
}
cfg := &MyConfig{}
provider := modular.NewStdConfigProvider(cfg)
func (*StdConfigProvider) GetConfig ΒΆ
func (s *StdConfigProvider) GetConfig() any
GetConfig returns the configuration object. The returned value is the exact object that was passed to NewStdConfigProvider.
type Stoppable ΒΆ added in v1.2.0
type Stoppable interface {
// Stop performs graceful shutdown of the module.
// This method is called during application shutdown, in reverse dependency
// order (dependents stop before their dependencies).
//
// The provided context includes a timeout for the shutdown process.
// Modules should respect this timeout and return promptly when it expires.
//
// Stop should:
// - Stop accepting new work
// - Complete or cancel existing work
// - Close resources and connections
// - Return any critical errors that occurred during shutdown
//
// Example:
// func (m *DatabaseModule) Stop(ctx context.Context) error {
// return m.db.Close()
// }
Stop(ctx context.Context) error
}
Stoppable is an interface for modules that need to perform cleanup operations. Modules implementing this interface will have their Stop method called during application shutdown, in reverse dependency order.
Stop operations typically involve:
- Gracefully shutting down background goroutines
- Closing network connections
- Flushing buffers and saving state
- Releasing external resources
type StructStateDiffer ΒΆ added in v1.3.4
type StructStateDiffer struct {
// contains filtered or unexported fields
}
StructStateDiffer captures before/after states to determine field changes
func NewStructStateDiffer ΒΆ added in v1.3.4
func NewStructStateDiffer(tracker FieldTracker, logger Logger) *StructStateDiffer
NewStructStateDiffer creates a new struct state differ
func (*StructStateDiffer) CaptureAfterStateAndDiff ΒΆ added in v1.3.4
func (d *StructStateDiffer) CaptureAfterStateAndDiff(structure interface{}, prefix string, feederType, sourceType string)
CaptureAfterStateAndDiff captures the state after feeder processing and computes diffs
func (*StructStateDiffer) CaptureBeforeState ΒΆ added in v1.3.4
func (d *StructStateDiffer) CaptureBeforeState(structure interface{}, prefix string)
CaptureBeforeState captures the state before feeder processing
func (*StructStateDiffer) Reset ΒΆ added in v1.3.4
func (d *StructStateDiffer) Reset()
Reset clears the captured states for reuse
type Subject ΒΆ added in v1.4.0
type Subject interface {
// RegisterObserver adds an observer to receive notifications.
// Observers can optionally filter events by type using the eventTypes parameter.
// If eventTypes is empty, the observer receives all events.
RegisterObserver(observer Observer, eventTypes ...string) error
// UnregisterObserver removes an observer from receiving notifications.
// This method should be idempotent and not error if the observer
// wasn't registered.
UnregisterObserver(observer Observer) error
// NotifyObservers sends an event to all registered observers.
// The notification process should be non-blocking for the caller
// and handle observer errors gracefully.
NotifyObservers(ctx context.Context, event cloudevents.Event) error
// GetObservers returns information about currently registered observers.
// This is useful for debugging and monitoring.
GetObservers() []ObserverInfo
}
Subject defines the interface for objects that can be observed. Subjects maintain a list of observers and notify them when events occur. This is the core interface that event emitters implement. Events use the CloudEvents specification for standardization.
type TenantApplication ΒΆ added in v1.1.0
type TenantApplication interface {
Application
// GetTenantService returns the application's tenant service if available.
// The tenant service manages tenant registration, lookup, and lifecycle.
// Returns an error if no tenant service has been registered.
//
// Example:
// tenantSvc, err := app.GetTenantService()
// if err != nil {
// return fmt.Errorf("multi-tenancy not configured: %w", err)
// }
GetTenantService() (TenantService, error)
// WithTenant creates a tenant context from the application context.
// Tenant contexts provide scoped access to tenant-specific configurations
// and services, enabling isolation between different tenants.
//
// The returned context can be used for tenant-specific operations
// and will carry tenant identification through the call chain.
//
// Example:
// tenantCtx, err := app.WithTenant("customer-456")
// if err != nil {
// return err
// }
// // Use tenantCtx for tenant-specific operations
WithTenant(tenantID TenantID) (*TenantContext, error)
// GetTenantConfig retrieves configuration for a specific tenant and section.
// This allows modules to access tenant-specific configuration that may
// override or extend the default application configuration.
//
// The section parameter specifies which configuration section to retrieve
// (e.g., "database", "cache", etc.), and the framework will return the
// tenant-specific version if available, falling back to defaults otherwise.
//
// Example:
// cfg, err := app.GetTenantConfig("tenant-789", "database")
// if err != nil {
// return err
// }
// dbConfig := cfg.GetConfig().(*DatabaseConfig)
GetTenantConfig(tenantID TenantID, section string) (ConfigProvider, error)
}
TenantApplication extends Application with multi-tenant functionality. This interface adds tenant-aware capabilities to the standard Application, allowing the same application instance to serve multiple tenants with isolated configurations and contexts.
Multi-tenant applications can:
- Maintain separate configurations per tenant
- Provide tenant-specific service instances
- Isolate tenant data and operations
- Support dynamic tenant registration and management
Example usage:
app := modular.NewStdApplication(configProvider, logger)
// Register tenant service and tenant-aware modules
tenantCtx, err := app.WithTenant("tenant-123")
if err != nil {
return err
}
// Use tenant context for tenant-specific operations
type TenantAwareConfig ΒΆ added in v1.1.0
type TenantAwareConfig struct {
// contains filtered or unexported fields
}
TenantAwareConfig provides configuration that's aware of tenant context
func NewTenantAwareConfig ΒΆ added in v1.1.0
func NewTenantAwareConfig( defaultConfig ConfigProvider, tenantService TenantService, configSection string, ) *TenantAwareConfig
NewTenantAwareConfig creates a new tenant-aware configuration provider
func (*TenantAwareConfig) GetConfig ΒΆ added in v1.1.0
func (tac *TenantAwareConfig) GetConfig() any
GetConfig retrieves the default configuration when no tenant is specified
func (*TenantAwareConfig) GetConfigWithContext ΒΆ added in v1.1.0
func (tac *TenantAwareConfig) GetConfigWithContext(ctx context.Context) any
GetConfigWithContext retrieves tenant-specific configuration based on context
type TenantAwareDecorator ΒΆ added in v1.4.0
type TenantAwareDecorator struct {
*BaseApplicationDecorator
// contains filtered or unexported fields
}
TenantAwareDecorator wraps an application to add tenant resolution capabilities. It injects tenant resolution before Start() and provides tenant-aware functionality.
func NewTenantAwareDecorator ΒΆ added in v1.4.0
func NewTenantAwareDecorator(inner Application, loader TenantLoader) *TenantAwareDecorator
NewTenantAwareDecorator creates a new tenant-aware decorator
func (*TenantAwareDecorator) GetTenantConfig ΒΆ added in v1.4.0
func (d *TenantAwareDecorator) GetTenantConfig(tenantID TenantID, section string) (ConfigProvider, error)
GetTenantConfig implements TenantApplication interface
func (*TenantAwareDecorator) GetTenantService ΒΆ added in v1.4.0
func (d *TenantAwareDecorator) GetTenantService() (TenantService, error)
GetTenantService implements TenantApplication interface
func (*TenantAwareDecorator) Start ΒΆ added in v1.4.0
func (d *TenantAwareDecorator) Start() error
Start overrides the base Start method to inject tenant resolution
func (*TenantAwareDecorator) WithTenant ΒΆ added in v1.4.0
func (d *TenantAwareDecorator) WithTenant(tenantID TenantID) (*TenantContext, error)
WithTenant implements TenantApplication interface
type TenantAwareModule ΒΆ added in v1.1.0
type TenantAwareModule interface {
Module
// OnTenantRegistered is called when a new tenant is registered.
// This method should be used to initialize any tenant-specific resources,
// such as database connections, caches, or configuration.
//
// The method should be non-blocking and handle errors gracefully.
// If initialization fails, the module should log the error but not
// prevent the tenant registration from completing.
OnTenantRegistered(tenantID TenantID)
// OnTenantRemoved is called when a tenant is removed.
// This method should be used to clean up any tenant-specific resources
// to prevent memory leaks or resource exhaustion.
//
// The method should be non-blocking and handle cleanup failures gracefully.
// Even if cleanup fails, the tenant removal should proceed.
OnTenantRemoved(tenantID TenantID)
}
type TenantAwareRegistry ΒΆ added in v1.1.0
type TenantAwareRegistry interface {
// GetServiceForTenant returns a service instance for a specific tenant
GetServiceForTenant(name string, tenantID TenantID, target any) error
}
TenantAwareRegistry provides common service discovery methods that are tenant-aware
type TenantConfigLoader ΒΆ added in v1.1.0
type TenantConfigLoader interface {
// LoadTenantConfigurations loads configurations for all tenants
LoadTenantConfigurations(app Application, tenantService TenantService) error
}
TenantConfigLoader is an interface for loading tenant configurations
type TenantConfigParams ΒΆ added in v1.1.0
type TenantConfigParams struct {
// ConfigNameRegex is a regex pattern for the config file names (e.g. "^tenant[0-9]+\\.json$").
ConfigNameRegex *regexp.Regexp
// ConfigDir is the directory where tenant config files are located.
ConfigDir string
// ConfigFeeders are the feeders to use for loading tenant configs.
ConfigFeeders []Feeder
}
TenantConfigParams defines parameters for loading tenant configurations
type TenantConfigProvider ΒΆ added in v1.1.0
type TenantConfigProvider struct {
// contains filtered or unexported fields
}
TenantConfigProvider manages configurations for multiple tenants
func NewTenantConfigProvider ΒΆ added in v1.1.0
func NewTenantConfigProvider(defaultConfig ConfigProvider) *TenantConfigProvider
NewTenantConfigProvider creates a new tenant configuration provider
func (*TenantConfigProvider) GetConfig ΒΆ added in v1.1.0
func (tcp *TenantConfigProvider) GetConfig() any
GetConfig returns the default configuration to satisfy ConfigProvider interface
func (*TenantConfigProvider) GetDefaultConfig ΒΆ added in v1.1.0
func (tcp *TenantConfigProvider) GetDefaultConfig() ConfigProvider
GetDefaultConfig returns the default configuration (non-tenant specific)
func (*TenantConfigProvider) GetTenantConfig ΒΆ added in v1.1.0
func (tcp *TenantConfigProvider) GetTenantConfig(tenantID TenantID, section string) (ConfigProvider, error)
GetTenantConfig retrieves a configuration for a specific tenant and section
func (*TenantConfigProvider) HasTenantConfig ΒΆ added in v1.1.0
func (tcp *TenantConfigProvider) HasTenantConfig(tenantID TenantID, section string) bool
HasTenantConfig checks if a configuration exists for a specific tenant and section
func (*TenantConfigProvider) SetTenantConfig ΒΆ added in v1.1.0
func (tcp *TenantConfigProvider) SetTenantConfig(tenantID TenantID, section string, provider ConfigProvider)
SetTenantConfig sets a configuration for a specific tenant and section
type TenantContext ΒΆ added in v1.1.0
TenantContext is a context for tenant-aware operations. It extends the standard Go context.Context interface to carry tenant identification through the call chain, enabling tenant-specific behavior in modules and services.
TenantContext should be used whenever performing operations that need to be tenant-specific, such as database queries, configuration lookups, or service calls.
func NewTenantContext ΒΆ added in v1.1.0
func NewTenantContext(ctx context.Context, tenantID TenantID) *TenantContext
NewTenantContext creates a new context with tenant information. The returned context carries the tenant ID and can be used throughout the application to identify which tenant an operation belongs to.
Example:
tenantCtx := modular.NewTenantContext(ctx, "customer-123") result, err := tenantAwareService.DoSomething(tenantCtx, data)
func (*TenantContext) GetTenantID ΒΆ added in v1.1.0
func (tc *TenantContext) GetTenantID() TenantID
GetTenantID returns the tenant ID from the context. This allows modules and services to determine which tenant the current operation is for.
type TenantID ΒΆ added in v1.1.0
type TenantID string
TenantID represents a unique tenant identifier. Tenant IDs should be stable, unique strings that identify tenants throughout the application lifecycle. Common patterns include:
- Customer IDs: "customer-12345"
- Domain names: "example.com"
- UUIDs: "550e8400-e29b-41d4-a716-446655440000"
func GetTenantIDFromContext ΒΆ added in v1.1.0
GetTenantIDFromContext attempts to extract tenant ID from a context. Returns the tenant ID and true if the context is a TenantContext, or empty string and false if it's not a tenant-aware context.
This is useful for functions that may or may not receive a tenant context:
if tenantID, ok := modular.GetTenantIDFromContext(ctx); ok {
// Handle tenant-specific logic
} else {
// Handle default/non-tenant logic
}
type TenantLoader ΒΆ added in v1.4.0
type TenantLoader interface {
// LoadTenants loads and returns all available tenants
LoadTenants() ([]Tenant, error)
}
TenantLoader is an interface for loading tenant information. Implementations can load tenants from various sources like databases, configuration files, APIs, etc.
type TenantService ΒΆ added in v1.1.0
type TenantService interface {
// GetTenantConfig returns tenant-specific configuration for the given tenant and section.
// This method looks up configuration that has been specifically registered for
// the tenant, falling back to default configuration if tenant-specific config
// is not available.
//
// The section parameter identifies which configuration section to retrieve
// (e.g., "database", "cache", "api").
//
// Example:
// cfg, err := tenantSvc.GetTenantConfig("tenant-123", "database")
// if err != nil {
// return err
// }
// dbConfig := cfg.GetConfig().(*DatabaseConfig)
GetTenantConfig(tenantID TenantID, section string) (ConfigProvider, error)
// GetTenants returns all registered tenant IDs.
// This is useful for operations that need to iterate over all tenants,
// such as maintenance tasks, reporting, or health checks.
//
// Example:
// for _, tenantID := range tenantSvc.GetTenants() {
// // Perform operation for each tenant
// err := performMaintenanceForTenant(tenantID)
// }
GetTenants() []TenantID
// RegisterTenant registers a new tenant with optional initial configurations.
// The configs map provides tenant-specific configuration for different sections.
// If a section is not provided in the configs map, the tenant will use the
// default application configuration for that section.
//
// Example:
// tenantConfigs := map[string]ConfigProvider{
// "database": modular.NewStdConfigProvider(&DatabaseConfig{
// Host: "tenant-specific-db.example.com",
// }),
// "cache": modular.NewStdConfigProvider(&CacheConfig{
// Prefix: "tenant-123:",
// }),
// }
// err := tenantSvc.RegisterTenant("tenant-123", tenantConfigs)
RegisterTenant(tenantID TenantID, configs map[string]ConfigProvider) error
// RegisterTenantAwareModule registers a module that wants to be notified about tenant lifecycle events.
// Modules implementing the TenantAwareModule interface can register to receive
// notifications when tenants are added or removed, allowing them to perform
// tenant-specific initialization or cleanup.
//
// This is typically called automatically by the application framework during
// module initialization, but can also be called directly if needed.
//
// Example:
// module := &MyTenantAwareModule{}
// err := tenantSvc.RegisterTenantAwareModule(module)
RegisterTenantAwareModule(module TenantAwareModule) error
}
TenantService provides tenant management functionality. The tenant service is responsible for:
- Managing tenant registration and lifecycle
- Providing tenant-specific configuration
- Notifying modules about tenant events
- Coordinating tenant-aware operations
Applications that need multi-tenant functionality should register a TenantService implementation as a service named "tenantService".
type ValueInjectionLoggerDecorator ΒΆ added in v1.4.1
type ValueInjectionLoggerDecorator struct {
*BaseLoggerDecorator
// contains filtered or unexported fields
}
ValueInjectionLoggerDecorator automatically injects key-value pairs into all log events. This decorator adds configured key-value pairs to every log call.
func NewValueInjectionLoggerDecorator ΒΆ added in v1.4.1
func NewValueInjectionLoggerDecorator(inner Logger, injectedArgs ...any) *ValueInjectionLoggerDecorator
NewValueInjectionLoggerDecorator creates a decorator that automatically injects values into log events.
func (*ValueInjectionLoggerDecorator) Debug ΒΆ added in v1.4.1
func (d *ValueInjectionLoggerDecorator) Debug(msg string, args ...any)
func (*ValueInjectionLoggerDecorator) Error ΒΆ added in v1.4.1
func (d *ValueInjectionLoggerDecorator) Error(msg string, args ...any)
func (*ValueInjectionLoggerDecorator) Info ΒΆ added in v1.4.1
func (d *ValueInjectionLoggerDecorator) Info(msg string, args ...any)
func (*ValueInjectionLoggerDecorator) Warn ΒΆ added in v1.4.1
func (d *ValueInjectionLoggerDecorator) Warn(msg string, args ...any)
type VerboseAwareFeeder ΒΆ added in v1.3.3
type VerboseAwareFeeder interface {
// SetVerboseDebug enables or disables verbose debug logging
SetVerboseDebug(enabled bool, logger interface{ Debug(msg string, args ...any) })
}
VerboseAwareFeeder provides functionality for verbose debug logging during configuration feeding
type VerboseLogger ΒΆ added in v1.3.3
VerboseLogger provides a minimal logging interface to avoid circular dependencies
Source Files
ΒΆ
- application.go
- application_observer.go
- base_config_support.go
- builder.go
- config_feeders.go
- config_field_tracking.go
- config_provider.go
- config_validation.go
- debug_module_interfaces.go
- decorator.go
- decorator_config.go
- decorator_observable.go
- decorator_tenant.go
- errors.go
- field_tracker_bridge.go
- instance_aware_config.go
- logger.go
- logger_decorator.go
- module.go
- observer.go
- observer_cloudevents.go
- observer_context.go
- service.go
- tenant.go
- tenant_aware_config.go
- tenant_config_file_loader.go
- tenant_config_loader.go
- tenant_config_provider.go
- tenant_service.go
Directories
ΒΆ
| Path | Synopsis |
|---|---|
|
cmd
|
|
|
modcli
module
|
|
|
Package feeders provides configuration feeders for reading data from various sources including environment variables, JSON, YAML, TOML files, and .env files.
|
Package feeders provides configuration feeders for reading data from various sources including environment variables, JSON, YAML, TOML files, and .env files. |
|
internal
|
|
|
modules
|
|
|
auth
module
|
|
|
cache
module
|
|
|
chimux
module
|
|
|
database
module
|
|
|
eventbus
module
|
|
|
eventlogger
module
|
|
|
httpclient
module
|
|
|
httpserver
module
|
|
|
jsonschema
module
|
|
|
letsencrypt
module
|
|
|
logmasker
module
|
|
|
reverseproxy
module
|
|
|
scheduler
module
|