Documentation
¶
Index ¶
- Constants
- func FindFieldForInterface[I any](reflectType reflect.Type) *reflect.StructField
- func FindFieldWithAnnotation[A any](reflectType reflect.Type) *reflect.StructField
- func FindTypesImplementingInterface(iface reflect.Type, ifaces ...reflect.Type) []reflect.Type
- func GetFieldFirstTag(field *reflect.StructField, tags []string) string
- func NewBeamBuilder(ptr any) (*BeamBuilder, Error)
- func UnprotectValue(value reflect.Value) reflect.Value
- type Application
- type Beam
- type BeamAttribute
- type BeamAttributeEvaluator
- type BeamBuilder
- func (this *BeamBuilder) Build() Beam
- func (this *BeamBuilder) WithAnnotatedType(aType reflect.Type) *BeamBuilder
- func (this *BeamBuilder) WithFoundry(foundry func(context.Context) (any, Error)) *BeamBuilder
- func (this *BeamBuilder) WithQualifier(qualifier string) *BeamBuilder
- func (this *BeamBuilder) WithScope(scope BeamScope) *BeamBuilder
- type BeamConditionEvaluator
- type BeamConditional
- type BeamPostConstruct
- type BeamPostConstructWithContext
- type BeamProvider
- type BeamRunner
- type BeamScope
- type BeamScopeAnnotation
- type BeamScopes
- type Component
- type ConditionalOnCGO
- type ConditionalOnMissingBeam
- type ConditionalOnNoCGO
- type ConditionalOnProfile
- type ConditionalOnProperty
- type Configuration
- type ConfigurationParser
- type ConfigurationProperties
- type ContainerConfiguration
- type Controller
- type DefaultBeam
- type Environment
- type EventFilter
- type Foundry
- type IgnoreScanning
- type InitializingContext
- type InnerBeamPostConstruct
- type Logging
- type PostEventFilter
- type PreEventFilter
- type Primary
- type Prototype
- type PrototypeContextKeyType
- type Qualifier
- type Repository
- type Server
- type Service
- type Singleton
- type Stereotype
- type TxManager
Constants ¶
const ( LevelTrace = slog.Level(-8) LevelDebug = slog.LevelDebug LevelInfo = slog.LevelInfo LevelWarn = slog.LevelWarn LevelError = slog.LevelError )
Variables ¶
This section is empty.
Functions ¶
func FindFieldForInterface ¶
func FindFieldForInterface[I any](reflectType reflect.Type) *reflect.StructField
FindFieldForInterface() will return the first field of a struct that is an anonymous interface, implementing interface A.
It will return nil if no field can be found.
func FindFieldWithAnnotation ¶
func FindFieldWithAnnotation[A any](reflectType reflect.Type) *reflect.StructField
FindFieldWithAnnotation() will return the first field of a struct that is an anonymous interface and of type A.
Contrary to FindFieldForInterface, this search for a specific interface field, not one implementing that interface.
It will return nil if no field can be found.
func FindTypesImplementingInterface ¶
FindTypesImplementingInterface() will return a slice of reflect.Type of types (pointers of structs) that implements one or more interfaces.
Only exported types are considered.
func GetFieldFirstTag ¶
func GetFieldFirstTag(field *reflect.StructField, tags []string) string
GetFieldFirstTag() will return the first tag value from a list of possible tags found on a struct field.
func NewBeamBuilder ¶
func NewBeamBuilder(ptr any) (*BeamBuilder, Error)
NewBeamBuilder() will return a new BeamBuilder.
Its argument may be :
A pointer or nil-pointer to a struct.
An interface.
A reflect.Type of one of those.
If this is a non-nil pointer to a struct and this beam happen to be a Singleton Beam, this pointer will be returned, which can be useful when used in testing.
func UnprotectValue ¶
UnprotectValue() let you get a new settable pointer to a reflect.Value.
It's main use if to let you write to a struct private field, like this framework do to inject Beam on private fields.
Types ¶
type Application ¶
type Application interface {
Stereotype
// contains filtered or unexported methods
}
Application Stereotype marker interface
type Beam ¶
type Beam interface {
// Attributes() returns a map of string/string containing this beam attributes.
//
// Attributes are a way to mark Beam with values like "Qualifier" or "Primary".
Attributes() map[string]string
// Type() returns the struct type (as a pointer)
Type() reflect.Type
// AnnotatedType() may returns a different type, to look for annotations.
//
// This is mainly used by [Configuration] structs where each function may have as first argument an anonymous
// struct defining other annotations than the parent [Configuration] struct.
AnnotatedType() reflect.Type
// Scope() represent the [BeamScope] (Singleton or Prototype)
Scope() BeamScope
// Foundry() represent the function used to create another instance of this [Beam].
//
// Implementation for a Singleton Beam should always return the same pointer to the struct, regardless of [context.Context].
//
// Implementations for a Prototype Beam will get from [context.Context] the following key/values :
//
// - [PrototypeContextParentType] : [reflect.Type] of the parent object it is inject to.
//
// - [PrototypeContextParentInstance] : (any) current instance of the parent object.
//
// NOTE: Default Foundry created by [BeamBuilder] do not care about those.
// Only [Configuration] method [Beam] will receive them, if it has a [context.Context] argument.
// Typical stereotyped Beam should use [BeamPostConstructWithContext.WithContext].
Foundry() func(context.Context) (any, Error)
}
Beam represent a beam definition, which is what the "container" instantiates and injects.
There is a default Beam struct implementation DefaultBeam, which can be built using the BeamBuilder type and the NewBeamBuilder function.
There is no need to have your own implementation, but it's open.
type BeamAttribute ¶
type BeamAttribute interface {
// contains filtered or unexported methods
}
BeamAttribute represents a base marker interface for a Beam attribute. Like for example Qualifier.
Those attributes may be used with an @:"Inject" tag to limit injection on a specific Beam.
type BeamAttributeEvaluator ¶
type BeamAttributeEvaluator interface {
// EvaluateBeamAttribute() must return a value for that specific attribute, mostly taken from a struct tag.
//
// The returned string must not be empty, as it will indicate that Beam does not have that attribute.
EvaluateBeamAttribute(beam Beam) string
}
BeamAttributeEvaluator represents the interface a struct must implements to define an evaluator of a particular BeamAttribute.
That struct must contain that BeamAttribute marker interface. For example the Primary BeamAttribute and its BeamAttributeEvaluator:
type Primary interface {
BeamAttribute // Implements BeamAttribute
_Primary() // Marker interface method
}
type PrimaryEvaluator struct {
Primary
}
func (this *PrimaryEvaluator) EvaluateBeamAttribute(_ Beam) string {
return "primary"
}
type BeamBuilder ¶
type BeamBuilder struct {
// contains filtered or unexported fields
}
BeamBuilder represents a struct used to create a new Beam.
func (*BeamBuilder) Build ¶
func (this *BeamBuilder) Build() Beam
Build() will finally return a Beam.
func (*BeamBuilder) WithAnnotatedType ¶
func (this *BeamBuilder) WithAnnotatedType(aType reflect.Type) *BeamBuilder
WithAnnotatedType() let you specify another type to look for annotations.
func (*BeamBuilder) WithFoundry ¶
func (this *BeamBuilder) WithFoundry(foundry func(context.Context) (any, Error)) *BeamBuilder
WithFoundry() let you specify a function to be used to instantiate a new instance of this Beam.
func (*BeamBuilder) WithQualifier ¶
func (this *BeamBuilder) WithQualifier(qualifier string) *BeamBuilder
WithQualifier() let you give a name to this Beam, which can be used when injecting.
func (*BeamBuilder) WithScope ¶
func (this *BeamBuilder) WithScope(scope BeamScope) *BeamBuilder
WithScope() let you specify a scope for this Beam
type BeamConditionEvaluator ¶
type BeamConditionEvaluator interface {
// EvaluateBeamCondition() must return true if a [Beam] satisfy that condition.
EvaluateBeamCondition(beam Beam, container InitializingContext) bool
}
BeamConditionEvaluator represents the interface a struct must implements to define an evaluator of a particular BeamConditional.
That struct must contain that BeamConditional marker interface.
type BeamConditional ¶
type BeamConditional interface {
// contains filtered or unexported methods
}
BeamConditional represents a base marker interface for a Beam conditional creation, like for example ConditionalOnProfile
type BeamPostConstruct ¶
type BeamPostConstruct interface {
// PostConstruct() is the function a Stereotyped Singleton struct must implement and the
// container will call it once the Beam has been injected successfully.
//
// If an Error is returned, the container initialization will fail.
PostConstruct() Error
}
BeamPostConstruct represent an interface with a PostConstruct function for a Singleton Beam.
type BeamPostConstructWithContext ¶
type BeamPostConstructWithContext interface {
// WithContext() is the function a Stereotyped Prototype struct must implement and the
// container will call it once the [Beam] has been injected successfully.
//
// If an Error is returned, the container initialization will fail.
//
// The [context.Context] will contain at least the following key/values :
//
// - [PrototypeContextParentType] : [reflect.Type] of the parent object it is inject to.
//
// - [PrototypeContextParentInstance] : (any) current instance of the parent object.
//
// Users can also populate the context with predefined key/values when used with a [Foundry].
WithContext(context.Context) Error
}
BeamPostConstructWithContext represent an interface with a PostConstruct function for a Prototype Beam.
This function will be called after BeamPostConstruct.PostConstruct.
type BeamProvider ¶
type BeamProvider interface {
ProvideBeam(reflect.Type, InitializingContext) (Beam, []Beam)
}
BeamProvider is an interface representing a compile-in type which can provide Beams using a predefined stereotype.
There is four main Stereotype : Service, Component, Repository and Controller.
There is two predefined Stereotype derived from Component : Configuration and ConfigurationProperties.
Those two marker interfaces are used by a struct implements BeamProvider and those stereotypes to have specialized Beam.
type BeamRunner ¶
type BeamRunner interface {
// The container will first need to be [ContainerConfiguration.Initialize] without errors and when
// [ContainerConfiguration.Run] is called, this function will be called.
Run(wg *sync.WaitGroup)
}
BeamRunner define an interface Beams may implement to have it called by the container function Run() after Initialize().
type BeamScopeAnnotation ¶
type BeamScopeAnnotation interface {
// contains filtered or unexported methods
}
type BeamScopes ¶
type BeamScopes struct {
SINGLETON,
PROTOTYPE Enum[BeamScopes]
}
BeamScopes is an github.com/BeamFoundry/rays/pkg/lang.Enum struct
type Component ¶
type Component interface {
Stereotype
// contains filtered or unexported methods
}
Component Stereotype marker interface.
type ConditionalOnCGO ¶
type ConditionalOnCGO interface {
BeamConditional
// contains filtered or unexported methods
}
ConditionalOnCGO BeamConditional marker interface.
This marker interface indicates if a Beam should eligible for registration based on the value of environment variable CGO_ENABLED. If this variable is set to "1", this condition will apply.
type ConditionalOnMissingBeam ¶
type ConditionalOnMissingBeam interface {
BeamConditional
PostEventFilter
// contains filtered or unexported methods
}
ConditionalOnMissingBeam BeamConditional marker interface.
This marker interface indicates a Beam should be eligible for registration if no other Beam of the same type is actually registered.
This works by delaying this condition to when all others conditional Beam have been evaluated and acts as a failback Beam registration.
As this condition is evaluated on the Beam type (same struct type or same interface), it can be best used inside a Configuration Beam.
// DatabaseConfiguration will configure an `DBDriver` interface.
type DatabaseConfiguration struct {
Configuration
}
// InMemoryDatabaseDriver will register a `*InMemoryDatabaseDriver` as a `DBDriver` interface,
// if the `Profile` "development" has been actived.
func (this *DatabaseConfiguration) InMemoryDatabaseDriver(
_ struct {
ConditionalOnProfile `Name:"developpement`
},
) DBDriver {
return &InMemorySQLDriver{}
}
// Fallback `&SQLDriver{}` as a `DBDriver` interface, if no other `DBDriver` has been registered.
func (this *DatabaseConfiguration) DatabaseDriver(
_ struct {
ConditionalOnMissingBeam
},
) DBDriver {
return &SQLDriver{}
}
type ConditionalOnNoCGO ¶
type ConditionalOnNoCGO interface {
BeamConditional
// contains filtered or unexported methods
}
ConditionalOnNoCGO BeamConditional marker interface.
This marker interface indicates if a Beam should eligible for registration based on the value of environment variable CGO_ENABLED. If this variable is not set to "1", this condition will apply.
type ConditionalOnProfile ¶
type ConditionalOnProfile interface {
BeamConditional
// contains filtered or unexported methods
}
ConditionalOnProfile BeamConditional marker interface.
This marker interface indicates if a Beam should be eligible for registration based on InitializingContext ActiveProfiles().
Profile(s) should be specified as a comma-separated StructTag using either the tag "Name", "Profile" or "Profile".
// ConditionService will be instantiated if either "profile1" or "profile2" profiles are activated
type ConditionService struct {
Component
ConditionalOnProfile `Name:"profile1,profile2"`
}
type ConditionalOnProperty ¶
type ConditionalOnProperty interface {
BeamConditional
// contains filtered or unexported methods
}
ConditionaOnProperty BeamConditional marker interface.
This marker interface indicates if a Beam should be eligible for registration based on a configuration property.
This interface must have a StructTag "Name" indicating this property. By default it must be defined and not evaluate to "false" (using strconv.ParseBool rules).
Instead of evaluating it as a "bool", a StructTag 'HavingValue" can be specified to indicate the value it should have.
Furthermore if the property is not defined, and a StructTag 'MatchIfMissing' is provided with a boolean string expression (see [strconv.ParseBool), it will be checked to know if this condition matches.
Given the following configuration :
app:
audit:
enabled: true
And this code :
// Tracer interface
type Tracer interface {
Trace(message string)
}
// AppTracerConfig will be registered only if "app.audit.enabled" evaluates to "true".
// The Beam it defines will not be evaluated and registered if not so.
type AppTracerConfig struct {
Configuration
ConditionalOnProperty `Name:"app.audit.enabled" MatchIfMissing:"false"`
}
// LogTracer will only be called if "app.audit.mode" exists
// and has the value "logging" or if does not exists at all.
func (a *AppTracerConfig) LogTracer(
_ struct {
ConditionalOnProperty `Name:"app.audit.mode" HavingValue="logging" MatchIfMissing:"true"`
},
) Tracer {
return &LogTracer{}
}
// KafkaTracer will only be called if "app.audit.mode" exists and equals to "kafka.
func (a *AppTracerConfig) KafkaTracer(
_ struct {
ConditionalOnProperty `Name:"app.audit.mode" HavingValue="kafka"`
},
) Tracer {
return &KafkaTracer{}
}
var _, _ = any(&AppTracerConfig{{}).(Stereotype)
// AppAuditor will be registered only if "app.audit.enabled" evaluates to "true".
// It will need a "Tracer" which will be provided by "AppTracerConfig"
type AppAuditor struct {
Component
ConditionalOnProperty `Name:"app.audit.enabled"`
tracer Tracer `@:"Inject"`
}
func (a *AppTracer) Audit(message string) {
a.tracer.Trace(message)
}
var _, _ = any(&AppAuditor{}).(Stereotype)
// A Service with an Optional AppAuditor
type AppService struct {
Service
auditor Optional[*AppAuditor] `@:"Inject"`
}
func (a *AppService) PostConstruct() Error {
if auditor, ok := a.auditor.Get(); ok {
auditor.Audit("AppService PostConstruct")
}
}
var _, _ = any(&AppService{]).(Stereotype)
How this works :
AppTracerConfig will be registered, having its ConditionalOnProperty "app.audit.enabled" evaluating to true.
- It will register a "Tracer" Beam using LogTracer() because the property "app.audit.mode" is not defined.
- It will have done the same if "app.audit.mode" was defined with the value "logging".
- It will not define a "Tracer" Beam using KafkaTracer() as "app.audit.mode" is not defined and with a value of "kafka".
AppAuditor will be registered, as its ConditionalOnProperty "app.audit.enabled" is "true", and can be injected.
AppService will br injected with a "*AppAuditor".
type Configuration ¶
type Configuration interface {
Component
// contains filtered or unexported methods
}
Configuration is a Component derived Stereotype marker interface.
The container will scan components and define a Beam defining this struct, and any struct pointer or interface returned from public methods attached to this struct.
It is mainly used to define Beam from struct not implementing a Stereotype.
import (
"database/sql"
. "github.com/BeamFoundry/rays/pkg/core"
)
type DatabaseConfig struct {
Configuration
}
// Forces the compiler to retain DatabaseConfig in the binary
// and verifies it implements the Stereotype interface.
var _, _ = any(&DatabaseConfig{}).(Stereotype)
// The container calls this method and registers the returned pointer as a Beam.
func (c *DatabaseConfig) ProvidePostgres() *sql.DB {
db, err := sql.Open("postgres", "...")
if err != nil {
return nil
}
return db
}
As with all Stereotype Beam it will be subject to BeamConditional loading.
Each public method that will be considered must return a struct pointer or interface, and optionally an error or an github.com/BeamFoundry/rays/pkg/lang.Error.
If it only returns one element (struct pointer or interface), it will be checked for nil and not register a Beam in that case.
If it returns two elements (struct pointer or interface, followed by an error or Error), the presence of the second element will be checked first invalidating the Beam registration and resulting in a container initialization error.
[Conditional] and BeamAttribute (like Qualifier) may be defined in an anonymous struct defined as first argument to the method.
For example, changing the Qualifier, adding a [Condition] and returning optionally an error :
func (c *DatabaseConfig) ProvidePostgres(
_ struct {
Qualifier `Name:"DbDrive"` // change the Beam qualifier (it would have been "providePostgres")
ConditionalOnMissingBeam
},
) (*sql.DB, error) {
return sql.Open("postgres", "...")
}
If no such anonymous struct defining a Qualifier, the Beam's Qualifier will be derived from the method's name (lowering the first letter).
Note on BeamConditional inheritance on Beam:
If there is no anonymous struct, BeamConditional, if any, will be inherited from the struct definition.
- A Configuration Beam with ConditionalOnMissingBeam will always be unique and it will not apply in this case. But a method not having an anonymous struct as first argument will inherit this [Condition] and registration may depends.
- A Configuration Beam with ConditionalOnProfile will be evaluated on this Configuration Beam and likewise will be the same for all the Beam it tries to register.
type ConfigurationParser ¶
type ConfigurationParser interface {
ParseConfigurationFilesystem(fsys fs.FS, loader func(m map[string]any, profile string))
}
ConfigurationParser represent the interface an object parsing a filesystems for configuration files need to implement.
type ConfigurationProperties ¶
type ConfigurationProperties interface {
Component
// contains filtered or unexported methods
}
ConfigurationProperties is a Component derived Stereotype marker interface. It is used to load configuration into a struct.
During its initialization, the container will load its configuration, as defined from calls to the github.com/BeamFoundry/rays.ApplicationContext, into struct defining this Stereotype interface.
ConfigurationProperties members are to be defined as private (lowercase) as the container does not implements tag matching.
The configuration key path to apply to this struct must be indicated, in a dot-separated format, in a "Name" struct tag to this marker interface.
After that struct has to be injected into another Stereotype component like Component or Service, in the same package.
Valid member types ¶
- All primitive types like string, int32, float64 (including time.Duration), bool ... and string pointer (to check for nil)
- Struct or struct pointer with private (lowercase) members
- Struct implementing [TextUnmarshaler] (converting a string value to a struct)
- Slice of all primitive types and struct (see above)
- Map of string or map of TextUnmarshaler to all the above types and of those map type.
Validation ¶
Although ConfigurationProperties supports only private fields and the github.com/go-playground/validator/v10.Validation library only supports public fields, validation is supported.
Using reflection a shadow struct will be constructed using public fields and be validated. If you use Cross-Field validation, remember to use fields with a uppercase first letter instead but errors will have the fields path/name with the "correct", private fields name.
Example ¶
Considering this YAML configuration loaded into the container:
app:
kafka:
brokers: ["localhost:9092"]
timeout: "5000ms"
retry: true
A corresponding ConfigurationProperties beam and a Service beam loading the "app.kafka" configuration key path whould look like this:
// myrepo/myapp/services/kafka.go
package services
import (
"fmt"
"time"
. "github.com/BeamFoundry/rays/pkg/core"
)
// 1. Define the Configuration
type KafkaConfig struct {
ConfigurationProperties `Name:"app.kafka"`
// Exact same-case matching is required.
//
// Ensure it's not empty and has valid hostname/port string values.
brokers []string `validate:"gt=0,dive,hostname_port"`
// Parsing "5000ms" and validating it a minimum value
timeout time.Duration `validate:"min:100ms"`
retry bool
}
// 2. Inject it into a Service
type KafkaServer struct {
Service
config *KafkaConfig `@:"Inject"`
}
// 3. Initialize the service using the injected configuration
func (s *KafkaServer) PostConstruct() Error {
fmt.Printf("Connecting to %d brokers with a timeout of %v\n", len(s.config.brokers), s.config.timeout)
return nil
}
// Ensure detection by the compiler
var _, _ = any(&KafkaConfig{}).(Stereotype)
var _, _ = any(&KafkaServer{}).(Stereotype)
type ContainerConfiguration ¶
type ContainerConfiguration interface {
// Logger() lets you retrieve thez default Logging. Useful from main().
Logger() Logging
// SetLoggingHandler() lets define a different log handler, override the current log mecanism.
SetLoggingHandler(handler func(io.Writer, *slog.HandlerOptions) slog.Handler)
// SetActiveProfiles() set the list of active profiles
SetActiveProfiles([]string) Error
// AddOverride() will defined a configuration to override, useful for command-line defined overrides or environment variables.
AddOverride(key, value string) Error
// AddConfigFS() will add a FS to scan for configuration
AddConfigFS(fs.FS) Error
// AddDefaultConfigFS() loads default config in the provided FS.
AddDefaultConfigFS(fs.FS) Error
// LoadDefaultConfig() loads default config.
//
// NOTE: Those will not be erased on container resets in testing.
//
// WARNING: You should not deep down any map type other that map[string]any.
LoadDefaultConfig(map[string]any) Error
// LoadDefaultConfigAt() loads default config at a given hierarchy.
//
// WARNING: You should not deep down any map type other that map[string]any.
LoadDefaultConfigAt(map[string]any, string) Error
// CopyDefaultConfig() lets you duplicate a "default" configuration key.
CopyDefaultConfig(from, to string) Error
// CopyDefaultConfigForProfile() lets you duplicate a "default" configuration key for a profile only.
CopyDefaultConfigForProfile(from, to, profile string) Error
// Initialize() will initialize the container.
Initialize() Error
// Run will call all the BeamRunner Beams.
Run()
}
ContainerConfiguration represent the interface exposed by the container to configure and initialize it.
It's mainly used from the [rays.ApplicationContext] function.
From a main() application function it will :
Lets you specify what profiles need to be activated
Add fs.FS to be parsed
Declare an override of a configuration key.
Enable scanning (disabled by default)
Set you own logging handler
Initialize the container engine
Finally Run all BeamRunner.
For a module developper it will let you define default configurations (not be erased after a test is runned).
type Controller ¶
type Controller interface {
Stereotype
// contains filtered or unexported methods
}
Controller Stereotype markker interface.
type DefaultBeam ¶
type DefaultBeam struct {
// contains filtered or unexported fields
}
DefaultBeam is the default Beam implementation.
As this is a central type in the container architecture, it has been chosen to be represented by the unique Beam interface, with a complete implementation (this).
You normally won't have to ever create a Beam yourself, and if so you should use the BeamBuilder which will return a DefaultBeam.
func (*DefaultBeam) AnnotatedType ¶
func (this *DefaultBeam) AnnotatedType() reflect.Type
AnnotatedType() implements Beam.AnnotatedType
func (*DefaultBeam) Attributes ¶
func (this *DefaultBeam) Attributes() map[string]string
Attributes implements Beam.
func (*DefaultBeam) Foundry ¶
func (this *DefaultBeam) Foundry() func(context.Context) (any, Error)
Foundry() implements Beam.Foundry.
func (*DefaultBeam) Scope ¶
func (this *DefaultBeam) Scope() BeamScope
Scope() implements Beam.Scope.
type Environment ¶
type Environment interface {
// ActiveProfiles() returns the list of active profiles
ActiveProfiles() []string
// ConfigValue() retrieve a single configuration value as a string, bool indicates if the value was found.
ConfigValue(path string) (string, bool)
// ConfigUnmarshall()
ConfigUnmarshall(path string, object any) Error
}
Environment let you access the container parameters, once the container is initialized.
This interface may be injected.
type EventFilter ¶
type EventFilter interface {
// contains filtered or unexported methods
}
EventFilter is a base marker interface representing a filter for an event.
type Foundry ¶
type Foundry[T any] struct { // contains filtered or unexported fields }
Foundry is one of the generic struct that can be directly injected with [lang.Optional].
If a Beam of type T can be injected, this struct would have that Beam foundry injected and be accessible.
This can be used to access and create Prototype Beam.
func NewFoundry ¶
NewFoundry() will create a Foundry for a type T.
Only used in testing. You shouldn't use this directly.
func (*Foundry[T]) Forge ¶
Forge will return an instance of type T. You can create a context.Context with your values added to it. if used as intended, injected, the container engine will add the following values to it :
PrototypeContextParentType : reflect.Type of the parent object it is inject to.
PrototypeContextParentInstance : (any) current instance of the parent object.
type IgnoreScanning ¶
type IgnoreScanning interface {
// contains filtered or unexported methods
}
type InitializingContext ¶
type InitializingContext interface {
// Add [ContainerContext] methods
Environment
// LoggerForClass() lets you retrieve a logger given a struct pointer.
LoggerForClass(class any) Logging
// LoggerForType() lets you retrieve a logger given a struct pointer reflect.Type;
LoggerForType(rtype reflect.Type) Logging
// FindBeams() find all the beams with a defined reflect.Type
FindBeams(reflect.Type) []Beam
// FindBeamsByAttributes() find all the beams by attributes, like "Qualifier" or "Primary".
FindBeamsByAttributes(reflect.Type, map[string]string) []Beam
// GetInstance() let you get a [Beam] created , injected and initialized instance.
//
// Mostly used inside [BeamProvider] to retrieve a parent Beam instance to call methods on it,
// letting you create child [Beam].
GetInstance(beam Beam) any
// GetMethodAnnotedType() will analyze a reflect.Method to check for an anonymous struct in its first argument,
// and return a reflect.Type (always of a struct pointer), and a reflect.Value (either struct or pointer of struct).
//
// The [reflect.Value] can be used directly as a [Beam.AnnotatedType], while the [reflect.Value] can be used as-is
// as an argument to [reflect.Method.Call].
//
// This [reflect.Value] will not have it's field injected. To do that you have to call
// [InitializingContext.InjectMethodAnnotedValue], from a the Beam foundry function.
//
// Mainly used by [BeamProvider] implementing struct.
GetMethodAnnotedType(method *reflect.Method) (reflect.Type, reflect.Value)
// InjectMethodAnnotedValue() will inject fields on a [reflect.Value].
// For this to work, it should be done from the Beam foundry method.
//
// Mainly used by [BeamProvider] implementing struct.
InjectMethodAnnotedValue(value reflect.Value, parent any) Error
}
InitializingContext represent a limited set of container functions avaiiable during a container initializing. Mainly used by BeamProvider implementations.
type InnerBeamPostConstruct ¶
type InnerBeamPostConstruct interface {
// Stereotyped (parent) struct can also contain embedded (composite) struct with their own injected types.
//
// Those inner structs will be initialized first with a pointer to their parent struct using this function.
PostConstruct(parent any) Error
}
InnerBeamPostConstruct represent an interface with a PostConstruct function for a Composite struct.
type Logging ¶
type Logging interface {
// Debug() logs at [LevelDebug].
Debug(msg string, args ...any)
// DebugContext() logs at [LevelDebug] with the given context.
DebugContext(ctx context.Context, msg string, args ...any)
// Error() logs at [LevelError].
Error(msg string, args ...any)
// ErrorContext() logs at [LevelError] with the given context.
ErrorContext(ctx context.Context, msg string, args ...any)
// Handler() returns the slog.Handler.
Handler() slog.Handler
// Info() logs at [LevelInfo].
Info(msg string, args ...any)
// InfoContext() logs at [LevelInfo] with the given context.
InfoContext(ctx context.Context, msg string, args ...any)
// Log() emits a log record with the current time and the given level and message.
// The [slog.Record]'s [slog.Attrs] consist of the [Logging]'s attributes followed by the [slog.Attrs] specified by args.
//
// The attribute arguments are processed as follows:
//
// - If an argument is an [slog.Attr], it is used as is.
// - If an argument is a string and this is not the last argument, the following argument is treated as the value and the two are combined into an [slog.Attr].
// - Otherwise, the argument is treated as a value with key "!BADKEY".
Log(ctx context.Context, level slog.Level, msg string, args ...any)
// LogAttrs() is a more efficient version of [Logging.Log] that accepts only [slog.Attrs].
LogAttrs(ctx context.Context, level slog.Level, msg string, attrs ...slog.Attr)
// Trace() logs at [LevelTrace].
Trace(msg string, args ...any)
// TraceContext() logs at [LevelTrace] with the given context.
TraceContext(ctx context.Context, msg string, args ...any)
// Warn() logs at [LevelWarn].
Warn(msg string, args ...any)
// WarnContext() logs at [LevelWarn] with the given context.
WarnContext(ctx context.Context, msg string, args ...any)
// With() returns a [Logging] that includes the given attributes in each output operation.
// Arguments are converted to attributes as if by [Logging.Log].
With(args ...any) Logging
// WithGroup() returns a [Logging] that starts a group, if name is non-empty.
// The keys of all attributes added to the [Logging] will be qualified by the given name.
// (How that qualification happens depends on the Handler.WithGroup method of the [Logging]'s Handler.)
//
// If name is empty, WithGroup returns the receiver.
WithGroup(name string) Logging
}
Logging is an interface detailing the majority of function provided by slog.Logging, adding LevelTrace support.
The default implementation is hidden inside the container internal package, as it is initialized directly by the container early on.
It is directly injectable :
import (
. "github.com/BeamFoundry/rays/pkg/core"
. "github.com/BeamFoundry/rays/pkg/lang"
)
type PaymentService struct {
Service
// Note: No pointer '*' because Logging is an interface
logger Logging `@:"Inject"`
}
func (s *PaymentService) Process(amount float64) Error {
s.logger.Trace("Entering Process method", "amount", amount) // Extremely granular logging
// Logging supports structured key-value pairs natively
s.logger.Info("Processing payment", "amount", amount)
return nil
}
It can be configured directly using the container configuration system:
rays:
logging:
# The default minimum log level
#
# Valid values are "TRACE", "DEBUG", "INFO", "WARN", "ERROR" in that order.
# A value of "INFO" for example will hide all logging from "TRACE" and "DEBUG"
#
# Type: text
# Default: INFO
level: DEBUG
# The slog handler to use.
#
# Valid values are "DEFAULT", "TEXT", or "JSON".
#
# Type: text
# Default: DEFAULT
handler: DEFAULT
# Add source location to each log entry.
#
# Type: boolean
# Default: true
source: true
# Override the log level for specific packages.
#
# Before injecting a [Logging], a new one will be created and its default level will be changed
# if the struct requesting the [Logging] has its package name referenced here.
#
# Type: Dictionary of "source: level"
#
# "source" is either a package name, the one of the struct injecting the [Logging] interface, or
# the package name followed by a slash and the struct name.
#
# It should be noted that "level" will only apply to that "source"
# and will not apply to its sub packages UNLESS it ends with a slash.
#
loggers:
github.com/BeamFoundry/rays-sample/: INFO
github.com/BeamFoundry/rays-sample/pkg/config: DEBUG
github.com/BeamFoundry/rays-sample/pkg/config/DatabaseConfig: WARN
type PostEventFilter ¶
type PostEventFilter interface {
EventFilter
// contains filtered or unexported methods
}
PostEventFilter EventFilter marker interface.
Used in ConditionalOnMissingBeam, to indicate a [Conditional] that should be checked later, after most of all other.
type PreEventFilter ¶
type PreEventFilter interface {
EventFilter
// contains filtered or unexported methods
}
PreEventFilter EventFilter marker interface.
type Primary ¶
type Primary interface {
BeamAttribute
// contains filtered or unexported methods
}
Primary is a BeamAttribute used to mark a Beam as primary.
When more than one Beam can be detected to be injected on a simple field (not a slice or map), which would result in an error, if one of them has this attribute it will be selected and no error would be reported.
type Prototype ¶
type Prototype interface {
BeamScopeAnnotation
// contains filtered or unexported methods
}
Prototype is a marker interface to be used to identify a prototype Beam.
type PrototypeContextKeyType ¶
type PrototypeContextKeyType string
PrototypeContextKeyType is the type representing a context key type for default Prototype context values.
const ( // PrototypeContextParentType represent the key used in the context to indicate a parent [reflect.Type]. // // Please see [BeamPostConstructWithContext]. PrototypeContextParentType PrototypeContextKeyType = "prototypeContextParentType" // PrototypeContextParentInstance represent the key used in the context to indicate a parent instance (any). // // Please see [BeamPostConstructWithContext]. PrototypeContextParentInstance PrototypeContextKeyType = "prototypeContextParentInstance" // PrototypeContextProxyType is a predefined key to be used in a context to represent an additional // level of parentship, between an [InnerBeamPostConstruct] embbeded structure parent and a [Prototype] Beam. PrototypeContextProxyType PrototypeContextKeyType = "prototypeContextProxyType" // PrototypeContextProxyInstance is a predefined key to be used in a context to represent an additional // level of parentship, between an [InnerBeamPostConstruct] embbeded structure parent and a [Prototype] Beam. PrototypeContextProxyInstance PrototypeContextKeyType = "prototypeContextProxyInstance" )
type Qualifier ¶
type Qualifier interface {
BeamAttribute
// contains filtered or unexported methods
}
Qualifier is a BeamAttribute used to indiquates a specific name for a Beam.
May be used in Configuration method Beam, anonymous struct first argument, as an alternate way to indicate the Beam Qualifier attribute, instead of relying on the method's name.
type Repository ¶
type Repository interface {
Stereotype
// contains filtered or unexported methods
}
Repository Stereotype marker interface.
type Server ¶
type Server interface {
BeamAttribute
// contains filtered or unexported methods
}
Server is a BeamAttribute used to indiquates for which "server" (in a multi server environment), this Beam belongs to.
It should defaults to "primary".
Think of it as if you have two web server in you application one public named "primary", and one for "management" on another port.
This let's you define [Controller]s for both servers. [Controller]s not havong this attributes should be considered for the "primary" server.
type Service ¶
type Service interface {
Stereotype
// contains filtered or unexported methods
}
Service Stereotype marker interface.
type Singleton ¶
type Singleton interface {
BeamScopeAnnotation
// contains filtered or unexported methods
}
Singleton is a marker interface to be used to identify a singleton Beam.
Completely optional, as it's the default scope of a Beam.
type Stereotype ¶
type Stereotype interface {
// contains filtered or unexported methods
}
Stereotype base marker interface
Stereotype is the kind of interface the container search in the runtime types available for Beam to register.
It's a base type, not to be used. You should use Component, Service, Configuration... instead.
You should note that the container does not make any difference between those Stereotype, except when it has to call the BeamPostConstruct.PostConstruct function.
It will be done in this order :
- ConfigurationProperties
- Configuration
- Component
- Repository
- Service
- Controller
- Application
- any other Beam implementing Stereotype
- any other Beam