core

package
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Oct 10, 2026 License: MIT Imports: 11 Imported by: 1

Documentation

Index

Constants

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

func FindTypesImplementingInterface(iface reflect.Type, ifaces ...reflect.Type) []reflect.Type

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 :

  1. A pointer or nil-pointer to a struct.

  2. An interface.

  3. 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

func UnprotectValue(value reflect.Value) reflect.Value

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 BeamScope

type BeamScope = Enum[BeamScopes]

BeamScope is a type alias for Enum[BeamScopes].

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 :

  1. 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".

  2. AppAuditor will be registered, as its ConditionalOnProperty "app.audit.enabled" is "true", and can be injected.

  3. 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.

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.

func (*DefaultBeam) Type

func (this *DefaultBeam) Type() reflect.Type

Type() implements Beam.Type.

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

func NewFoundry[T any](furnace func(context.Context) (any, Error)) Foundry[T]

NewFoundry() will create a Foundry for a type T.

Only used in testing. You shouldn't use this directly.

func (*Foundry[T]) Forge

func (this *Foundry[T]) Forge(ctx context.Context) (T, Error)

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 :

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 :

type TxManager

type TxManager[T any] interface {
	Start(context.Context) *T
	Get() *T
	End()
}

Represent a TransactionManager for a <T> type.

Jump to

Keyboard shortcuts

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