- Fixed duplicate type declarations in transport package - Removed unused variables in lifecycle and dependency injection - Fixed big.Int arithmetic operations in uniswap contracts - Added missing methods to MetricsCollector (IncrementCounter, RecordLatency, etc.) - Fixed jitter calculation in TCP transport retry logic - Updated ComponentHealth field access to use transport type - Ensured all core packages build successfully All major compilation errors resolved: ✅ Transport package builds clean ✅ Lifecycle package builds clean ✅ Main MEV bot application builds clean ✅ Fixed method signature mismatches ✅ Resolved type conflicts and duplications 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
662 lines
18 KiB
Go
662 lines
18 KiB
Go
package lifecycle
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"reflect"
|
|
"sync"
|
|
)
|
|
|
|
// Container provides dependency injection functionality
|
|
type Container struct {
|
|
services map[reflect.Type]*ServiceDescriptor
|
|
instances map[reflect.Type]interface{}
|
|
namedServices map[string]*ServiceDescriptor
|
|
namedInstances map[string]interface{}
|
|
singletons map[reflect.Type]interface{}
|
|
factories map[reflect.Type]FactoryFunc
|
|
interceptors []Interceptor
|
|
config ContainerConfig
|
|
mu sync.RWMutex
|
|
parent *Container
|
|
scoped map[string]*Container
|
|
}
|
|
|
|
// ServiceDescriptor describes how a service should be instantiated
|
|
type ServiceDescriptor struct {
|
|
ServiceType reflect.Type
|
|
Implementation reflect.Type
|
|
Lifetime ServiceLifetime
|
|
Factory FactoryFunc
|
|
Instance interface{}
|
|
Name string
|
|
Dependencies []reflect.Type
|
|
Tags []string
|
|
Metadata map[string]interface{}
|
|
Interceptors []Interceptor
|
|
}
|
|
|
|
// ServiceLifetime defines the lifetime of a service
|
|
type ServiceLifetime string
|
|
|
|
const (
|
|
Transient ServiceLifetime = "transient" // New instance every time
|
|
Singleton ServiceLifetime = "singleton" // Single instance for container lifetime
|
|
Scoped ServiceLifetime = "scoped" // Single instance per scope
|
|
)
|
|
|
|
// FactoryFunc creates service instances
|
|
type FactoryFunc func(container *Container) (interface{}, error)
|
|
|
|
// Interceptor can intercept service creation and method calls
|
|
type Interceptor interface {
|
|
Intercept(ctx context.Context, target interface{}, method string, args []interface{}) (interface{}, error)
|
|
}
|
|
|
|
// ContainerConfig configures the container behavior
|
|
type ContainerConfig struct {
|
|
EnableReflection bool `json:"enable_reflection"`
|
|
EnableCircularDetection bool `json:"enable_circular_detection"`
|
|
EnableInterception bool `json:"enable_interception"`
|
|
EnableValidation bool `json:"enable_validation"`
|
|
MaxDepth int `json:"max_depth"`
|
|
CacheInstances bool `json:"cache_instances"`
|
|
}
|
|
|
|
// ServiceBuilder provides a fluent interface for service registration
|
|
type ServiceBuilder struct {
|
|
container *Container
|
|
serviceType reflect.Type
|
|
implType reflect.Type
|
|
lifetime ServiceLifetime
|
|
factory FactoryFunc
|
|
instance interface{}
|
|
name string
|
|
tags []string
|
|
metadata map[string]interface{}
|
|
interceptors []Interceptor
|
|
}
|
|
|
|
// NewContainer creates a new dependency injection container
|
|
func NewContainer(config ContainerConfig) *Container {
|
|
container := &Container{
|
|
services: make(map[reflect.Type]*ServiceDescriptor),
|
|
instances: make(map[reflect.Type]interface{}),
|
|
namedServices: make(map[string]*ServiceDescriptor),
|
|
namedInstances: make(map[string]interface{}),
|
|
singletons: make(map[reflect.Type]interface{}),
|
|
factories: make(map[reflect.Type]FactoryFunc),
|
|
interceptors: make([]Interceptor, 0),
|
|
config: config,
|
|
scoped: make(map[string]*Container),
|
|
}
|
|
|
|
// Set default configuration
|
|
if container.config.MaxDepth == 0 {
|
|
container.config.MaxDepth = 10
|
|
}
|
|
|
|
return container
|
|
}
|
|
|
|
// Register registers a service type with its implementation
|
|
func (c *Container) Register(serviceType, implementationType interface{}) *ServiceBuilder {
|
|
c.mu.Lock()
|
|
defer c.mu.Unlock()
|
|
|
|
sType := reflect.TypeOf(serviceType)
|
|
if sType.Kind() == reflect.Ptr {
|
|
sType = sType.Elem()
|
|
}
|
|
if sType.Kind() == reflect.Interface {
|
|
sType = reflect.TypeOf(serviceType).Elem()
|
|
}
|
|
|
|
implType := reflect.TypeOf(implementationType)
|
|
if implType.Kind() == reflect.Ptr {
|
|
implType = implType.Elem()
|
|
}
|
|
|
|
return &ServiceBuilder{
|
|
container: c,
|
|
serviceType: sType,
|
|
implType: implType,
|
|
lifetime: Transient,
|
|
tags: make([]string, 0),
|
|
metadata: make(map[string]interface{}),
|
|
interceptors: make([]Interceptor, 0),
|
|
}
|
|
}
|
|
|
|
// RegisterInstance registers a specific instance
|
|
func (c *Container) RegisterInstance(serviceType interface{}, instance interface{}) *ServiceBuilder {
|
|
c.mu.Lock()
|
|
defer c.mu.Unlock()
|
|
|
|
sType := reflect.TypeOf(serviceType)
|
|
if sType.Kind() == reflect.Ptr {
|
|
sType = sType.Elem()
|
|
}
|
|
if sType.Kind() == reflect.Interface {
|
|
sType = reflect.TypeOf(serviceType).Elem()
|
|
}
|
|
|
|
return &ServiceBuilder{
|
|
container: c,
|
|
serviceType: sType,
|
|
instance: instance,
|
|
lifetime: Singleton,
|
|
tags: make([]string, 0),
|
|
metadata: make(map[string]interface{}),
|
|
interceptors: make([]Interceptor, 0),
|
|
}
|
|
}
|
|
|
|
// RegisterFactory registers a factory function for creating instances
|
|
func (c *Container) RegisterFactory(serviceType interface{}, factory FactoryFunc) *ServiceBuilder {
|
|
c.mu.Lock()
|
|
defer c.mu.Unlock()
|
|
|
|
sType := reflect.TypeOf(serviceType)
|
|
if sType.Kind() == reflect.Ptr {
|
|
sType = sType.Elem()
|
|
}
|
|
if sType.Kind() == reflect.Interface {
|
|
sType = reflect.TypeOf(serviceType).Elem()
|
|
}
|
|
|
|
return &ServiceBuilder{
|
|
container: c,
|
|
serviceType: sType,
|
|
factory: factory,
|
|
lifetime: Transient,
|
|
tags: make([]string, 0),
|
|
metadata: make(map[string]interface{}),
|
|
interceptors: make([]Interceptor, 0),
|
|
}
|
|
}
|
|
|
|
// Resolve resolves a service instance by type
|
|
func (c *Container) Resolve(serviceType interface{}) (interface{}, error) {
|
|
sType := reflect.TypeOf(serviceType)
|
|
if sType.Kind() == reflect.Ptr {
|
|
sType = sType.Elem()
|
|
}
|
|
if sType.Kind() == reflect.Interface {
|
|
sType = reflect.TypeOf(serviceType).Elem()
|
|
}
|
|
|
|
return c.resolveType(sType, make(map[reflect.Type]bool), 0)
|
|
}
|
|
|
|
// ResolveNamed resolves a named service instance
|
|
func (c *Container) ResolveNamed(name string) (interface{}, error) {
|
|
c.mu.RLock()
|
|
defer c.mu.RUnlock()
|
|
|
|
// Check if instance already exists
|
|
if instance, exists := c.namedInstances[name]; exists {
|
|
return instance, nil
|
|
}
|
|
|
|
// Get service descriptor
|
|
descriptor, exists := c.namedServices[name]
|
|
if !exists {
|
|
return nil, fmt.Errorf("named service not found: %s", name)
|
|
}
|
|
|
|
return c.createInstance(descriptor, make(map[reflect.Type]bool), 0)
|
|
}
|
|
|
|
// ResolveAll resolves all services with a specific tag
|
|
func (c *Container) ResolveAll(tag string) ([]interface{}, error) {
|
|
c.mu.RLock()
|
|
defer c.mu.RUnlock()
|
|
|
|
var instances []interface{}
|
|
|
|
for _, descriptor := range c.services {
|
|
for _, serviceTag := range descriptor.Tags {
|
|
if serviceTag == tag {
|
|
instance, err := c.createInstance(descriptor, make(map[reflect.Type]bool), 0)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to resolve service with tag %s: %w", tag, err)
|
|
}
|
|
instances = append(instances, instance)
|
|
break
|
|
}
|
|
}
|
|
}
|
|
|
|
return instances, nil
|
|
}
|
|
|
|
// TryResolve attempts to resolve a service, returning nil if not found
|
|
func (c *Container) TryResolve(serviceType interface{}) interface{} {
|
|
instance, err := c.Resolve(serviceType)
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
return instance
|
|
}
|
|
|
|
// IsRegistered checks if a service type is registered
|
|
func (c *Container) IsRegistered(serviceType interface{}) bool {
|
|
sType := reflect.TypeOf(serviceType)
|
|
if sType.Kind() == reflect.Ptr {
|
|
sType = sType.Elem()
|
|
}
|
|
if sType.Kind() == reflect.Interface {
|
|
sType = reflect.TypeOf(serviceType).Elem()
|
|
}
|
|
|
|
c.mu.RLock()
|
|
defer c.mu.RUnlock()
|
|
|
|
_, exists := c.services[sType]
|
|
return exists
|
|
}
|
|
|
|
// CreateScope creates a new scoped container
|
|
func (c *Container) CreateScope(name string) *Container {
|
|
c.mu.Lock()
|
|
defer c.mu.Unlock()
|
|
|
|
scope := &Container{
|
|
services: make(map[reflect.Type]*ServiceDescriptor),
|
|
instances: make(map[reflect.Type]interface{}),
|
|
namedServices: make(map[string]*ServiceDescriptor),
|
|
namedInstances: make(map[string]interface{}),
|
|
singletons: make(map[reflect.Type]interface{}),
|
|
factories: make(map[reflect.Type]FactoryFunc),
|
|
interceptors: make([]Interceptor, 0),
|
|
config: c.config,
|
|
parent: c,
|
|
scoped: make(map[string]*Container),
|
|
}
|
|
|
|
c.scoped[name] = scope
|
|
return scope
|
|
}
|
|
|
|
// GetScope retrieves a named scope
|
|
func (c *Container) GetScope(name string) (*Container, bool) {
|
|
c.mu.RLock()
|
|
defer c.mu.RUnlock()
|
|
|
|
scope, exists := c.scoped[name]
|
|
return scope, exists
|
|
}
|
|
|
|
// AddInterceptor adds a global interceptor
|
|
func (c *Container) AddInterceptor(interceptor Interceptor) {
|
|
c.mu.Lock()
|
|
defer c.mu.Unlock()
|
|
c.interceptors = append(c.interceptors, interceptor)
|
|
}
|
|
|
|
// GetRegistrations returns all service registrations
|
|
func (c *Container) GetRegistrations() map[reflect.Type]*ServiceDescriptor {
|
|
c.mu.RLock()
|
|
defer c.mu.RUnlock()
|
|
|
|
registrations := make(map[reflect.Type]*ServiceDescriptor)
|
|
for t, desc := range c.services {
|
|
registrations[t] = desc
|
|
}
|
|
return registrations
|
|
}
|
|
|
|
// Validate validates all service registrations
|
|
func (c *Container) Validate() error {
|
|
c.mu.RLock()
|
|
defer c.mu.RUnlock()
|
|
|
|
if !c.config.EnableValidation {
|
|
return nil
|
|
}
|
|
|
|
for serviceType, descriptor := range c.services {
|
|
if err := c.validateDescriptor(serviceType, descriptor); err != nil {
|
|
return fmt.Errorf("validation failed for service %s: %w", serviceType.String(), err)
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// Dispose cleans up the container and all instances
|
|
func (c *Container) Dispose() error {
|
|
c.mu.Lock()
|
|
defer c.mu.Unlock()
|
|
|
|
// Dispose all scoped containers
|
|
for _, scope := range c.scoped {
|
|
scope.Dispose()
|
|
}
|
|
|
|
// Clear all maps
|
|
c.services = make(map[reflect.Type]*ServiceDescriptor)
|
|
c.instances = make(map[reflect.Type]interface{})
|
|
c.namedServices = make(map[string]*ServiceDescriptor)
|
|
c.namedInstances = make(map[string]interface{})
|
|
c.singletons = make(map[reflect.Type]interface{})
|
|
c.factories = make(map[reflect.Type]FactoryFunc)
|
|
c.scoped = make(map[string]*Container)
|
|
|
|
return nil
|
|
}
|
|
|
|
// Private methods
|
|
|
|
func (c *Container) resolveType(serviceType reflect.Type, resolving map[reflect.Type]bool, depth int) (interface{}, error) {
|
|
if depth > c.config.MaxDepth {
|
|
return nil, fmt.Errorf("maximum resolution depth exceeded for type %s", serviceType.String())
|
|
}
|
|
|
|
// Check for circular dependencies
|
|
if c.config.EnableCircularDetection && resolving[serviceType] {
|
|
return nil, fmt.Errorf("circular dependency detected for type %s", serviceType.String())
|
|
}
|
|
|
|
c.mu.RLock()
|
|
defer c.mu.RUnlock()
|
|
|
|
// Check if singleton instance exists
|
|
if instance, exists := c.singletons[serviceType]; exists {
|
|
return instance, nil
|
|
}
|
|
|
|
// Check if cached instance exists
|
|
if c.config.CacheInstances {
|
|
if instance, exists := c.instances[serviceType]; exists {
|
|
return instance, nil
|
|
}
|
|
}
|
|
|
|
// Get service descriptor
|
|
descriptor, exists := c.services[serviceType]
|
|
if !exists {
|
|
// Try parent container
|
|
if c.parent != nil {
|
|
return c.parent.resolveType(serviceType, resolving, depth+1)
|
|
}
|
|
return nil, fmt.Errorf("service not registered: %s", serviceType.String())
|
|
}
|
|
|
|
resolving[serviceType] = true
|
|
defer delete(resolving, serviceType)
|
|
|
|
return c.createInstance(descriptor, resolving, depth+1)
|
|
}
|
|
|
|
func (c *Container) createInstance(descriptor *ServiceDescriptor, resolving map[reflect.Type]bool, depth int) (interface{}, error) {
|
|
// Use existing instance if available
|
|
if descriptor.Instance != nil {
|
|
return descriptor.Instance, nil
|
|
}
|
|
|
|
// Use factory if available
|
|
if descriptor.Factory != nil {
|
|
instance, err := descriptor.Factory(c)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("factory failed for %s: %w", descriptor.ServiceType.String(), err)
|
|
}
|
|
|
|
if descriptor.Lifetime == Singleton {
|
|
c.singletons[descriptor.ServiceType] = instance
|
|
}
|
|
|
|
return c.applyInterceptors(instance, descriptor)
|
|
}
|
|
|
|
// Create instance using reflection
|
|
if descriptor.Implementation == nil {
|
|
return nil, fmt.Errorf("no implementation or factory provided for %s", descriptor.ServiceType.String())
|
|
}
|
|
|
|
instance, err := c.createInstanceByReflection(descriptor, resolving, depth)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// Store singleton
|
|
if descriptor.Lifetime == Singleton {
|
|
c.singletons[descriptor.ServiceType] = instance
|
|
}
|
|
|
|
return c.applyInterceptors(instance, descriptor)
|
|
}
|
|
|
|
func (c *Container) createInstanceByReflection(descriptor *ServiceDescriptor, resolving map[reflect.Type]bool, depth int) (interface{}, error) {
|
|
if !c.config.EnableReflection {
|
|
return nil, fmt.Errorf("reflection is disabled")
|
|
}
|
|
|
|
implType := descriptor.Implementation
|
|
if implType.Kind() == reflect.Ptr {
|
|
implType = implType.Elem()
|
|
}
|
|
|
|
// Find constructor (assumes first constructor or struct creation)
|
|
var constructorFunc reflect.Value
|
|
|
|
// Look for constructor function
|
|
_ = "New" + implType.Name() // constructorName not used yet
|
|
if implType.PkgPath() != "" {
|
|
// Try to find package-level constructor
|
|
// This is simplified - in a real implementation you'd use build tags or reflection
|
|
// to find the actual constructor functions
|
|
}
|
|
|
|
// Create instance
|
|
if constructorFunc.IsValid() {
|
|
// Use constructor function
|
|
return c.callConstructor(constructorFunc, resolving, depth)
|
|
} else {
|
|
// Create struct directly
|
|
return c.createStruct(implType, resolving, depth)
|
|
}
|
|
}
|
|
|
|
func (c *Container) createStruct(structType reflect.Type, resolving map[reflect.Type]bool, depth int) (interface{}, error) {
|
|
// Create new instance
|
|
instance := reflect.New(structType)
|
|
elem := instance.Elem()
|
|
|
|
// Inject dependencies into fields
|
|
for i := 0; i < elem.NumField(); i++ {
|
|
field := elem.Field(i)
|
|
fieldType := elem.Type().Field(i)
|
|
|
|
// Check for dependency injection tags
|
|
if tag := fieldType.Tag.Get("inject"); tag != "" {
|
|
if !field.CanSet() {
|
|
continue
|
|
}
|
|
|
|
var dependency interface{}
|
|
var err error
|
|
|
|
if tag == "true" || tag == "" {
|
|
// Inject by type
|
|
dependency, err = c.resolveType(field.Type(), resolving, depth)
|
|
} else {
|
|
// Inject by name
|
|
dependency, err = c.ResolveNamed(tag)
|
|
}
|
|
|
|
if err != nil {
|
|
// Check if injection is optional
|
|
if optionalTag := fieldType.Tag.Get("optional"); optionalTag == "true" {
|
|
continue
|
|
}
|
|
return nil, fmt.Errorf("failed to inject dependency for field %s: %w", fieldType.Name, err)
|
|
}
|
|
|
|
field.Set(reflect.ValueOf(dependency))
|
|
}
|
|
}
|
|
|
|
return instance.Interface(), nil
|
|
}
|
|
|
|
func (c *Container) callConstructor(constructor reflect.Value, resolving map[reflect.Type]bool, depth int) (interface{}, error) {
|
|
constructorType := constructor.Type()
|
|
args := make([]reflect.Value, constructorType.NumIn())
|
|
|
|
// Resolve constructor arguments
|
|
for i := 0; i < constructorType.NumIn(); i++ {
|
|
argType := constructorType.In(i)
|
|
arg, err := c.resolveType(argType, resolving, depth)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to resolve constructor argument %d (%s): %w", i, argType.String(), err)
|
|
}
|
|
args[i] = reflect.ValueOf(arg)
|
|
}
|
|
|
|
// Call constructor
|
|
results := constructor.Call(args)
|
|
if len(results) == 0 {
|
|
return nil, fmt.Errorf("constructor returned no values")
|
|
}
|
|
|
|
instance := results[0].Interface()
|
|
|
|
// Check for error result
|
|
if len(results) > 1 && !results[1].IsNil() {
|
|
if err, ok := results[1].Interface().(error); ok {
|
|
return nil, fmt.Errorf("constructor error: %w", err)
|
|
}
|
|
}
|
|
|
|
return instance, nil
|
|
}
|
|
|
|
func (c *Container) applyInterceptors(instance interface{}, descriptor *ServiceDescriptor) (interface{}, error) {
|
|
if !c.config.EnableInterception {
|
|
return instance, nil
|
|
}
|
|
|
|
// Apply service-specific interceptors
|
|
for _, interceptor := range descriptor.Interceptors {
|
|
// Apply interceptor (simplified - real implementation would create proxies)
|
|
_ = interceptor
|
|
}
|
|
|
|
// Apply global interceptors
|
|
for _, interceptor := range c.interceptors {
|
|
// Apply interceptor (simplified - real implementation would create proxies)
|
|
_ = interceptor
|
|
}
|
|
|
|
return instance, nil
|
|
}
|
|
|
|
func (c *Container) validateDescriptor(serviceType reflect.Type, descriptor *ServiceDescriptor) error {
|
|
// Validate that implementation implements the service interface
|
|
if descriptor.Implementation != nil {
|
|
if serviceType.Kind() == reflect.Interface {
|
|
if !descriptor.Implementation.Implements(serviceType) {
|
|
return fmt.Errorf("implementation %s does not implement interface %s",
|
|
descriptor.Implementation.String(), serviceType.String())
|
|
}
|
|
}
|
|
}
|
|
|
|
// Validate dependencies
|
|
for _, depType := range descriptor.Dependencies {
|
|
if !c.IsRegistered(depType) && (c.parent == nil || !c.parent.IsRegistered(depType)) {
|
|
return fmt.Errorf("dependency %s is not registered", depType.String())
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// ServiceBuilder methods
|
|
|
|
// AsSingleton sets the service lifetime to singleton
|
|
func (sb *ServiceBuilder) AsSingleton() *ServiceBuilder {
|
|
sb.lifetime = Singleton
|
|
return sb
|
|
}
|
|
|
|
// AsTransient sets the service lifetime to transient
|
|
func (sb *ServiceBuilder) AsTransient() *ServiceBuilder {
|
|
sb.lifetime = Transient
|
|
return sb
|
|
}
|
|
|
|
// AsScoped sets the service lifetime to scoped
|
|
func (sb *ServiceBuilder) AsScoped() *ServiceBuilder {
|
|
sb.lifetime = Scoped
|
|
return sb
|
|
}
|
|
|
|
// WithName sets a name for the service
|
|
func (sb *ServiceBuilder) WithName(name string) *ServiceBuilder {
|
|
sb.name = name
|
|
return sb
|
|
}
|
|
|
|
// WithTag adds a tag to the service
|
|
func (sb *ServiceBuilder) WithTag(tag string) *ServiceBuilder {
|
|
sb.tags = append(sb.tags, tag)
|
|
return sb
|
|
}
|
|
|
|
// WithMetadata adds metadata to the service
|
|
func (sb *ServiceBuilder) WithMetadata(key string, value interface{}) *ServiceBuilder {
|
|
sb.metadata[key] = value
|
|
return sb
|
|
}
|
|
|
|
// WithInterceptor adds an interceptor to the service
|
|
func (sb *ServiceBuilder) WithInterceptor(interceptor Interceptor) *ServiceBuilder {
|
|
sb.interceptors = append(sb.interceptors, interceptor)
|
|
return sb
|
|
}
|
|
|
|
// Build finalizes the service registration
|
|
func (sb *ServiceBuilder) Build() error {
|
|
sb.container.mu.Lock()
|
|
defer sb.container.mu.Unlock()
|
|
|
|
descriptor := &ServiceDescriptor{
|
|
ServiceType: sb.serviceType,
|
|
Implementation: sb.implType,
|
|
Lifetime: sb.lifetime,
|
|
Factory: sb.factory,
|
|
Instance: sb.instance,
|
|
Name: sb.name,
|
|
Tags: sb.tags,
|
|
Metadata: sb.metadata,
|
|
Interceptors: sb.interceptors,
|
|
}
|
|
|
|
// Store by type
|
|
sb.container.services[sb.serviceType] = descriptor
|
|
|
|
// Store by name if provided
|
|
if sb.name != "" {
|
|
sb.container.namedServices[sb.name] = descriptor
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// DefaultInterceptor provides basic interception functionality
|
|
type DefaultInterceptor struct {
|
|
name string
|
|
}
|
|
|
|
func NewDefaultInterceptor(name string) *DefaultInterceptor {
|
|
return &DefaultInterceptor{name: name}
|
|
}
|
|
|
|
func (di *DefaultInterceptor) Intercept(ctx context.Context, target interface{}, method string, args []interface{}) (interface{}, error) {
|
|
// Basic interception - could add logging, metrics, etc.
|
|
return nil, nil
|
|
}
|