Documentation
¶
Overview ¶
Package goevent provides a type-safe, flexible event bus wrapper for Go.
GoEvent supports two drivers:
- Memory driver (default): In-memory EventBus for same-process communication
- Redis driver: Redis pub/sub for distributed multi-process/multi-server communication
Features:
- Type-safe interfaces instead of reflection-based handlers
- Configurable sync/async execution per listener
- Per-event waiting with DispatchHandle
- Built-in error collection and reporting
- Thread-safe operations with proper synchronization
Basic usage (memory driver):
bus := goevent.New()
bus.RegisterListener(&MyListener{})
handle := bus.Dispatch(&MyEvent{})
handle.Wait() // Wait for completion
Distributed usage (Redis driver):
bus := goevent.NewWithConfig(&goevent.Config{
Driver: goevent.DriverRedis,
Redis: &goevent.RedisConfig{
Addr: "localhost:6379",
},
})
bus.RegisterListener(&MyListener{})
handle := bus.Dispatch(&MyEvent{})
Index ¶
- func RegisterEventType(event Event)
- func RegisterEventTypeAs(typeName string, event Event)
- type Config
- type DispatchHandle
- type Driver
- type DriverType
- type Event
- type EventError
- type EventHandler
- type EventRegistry
- type GoEvent
- func (ge *GoEvent) ClearErrors()
- func (ge *GoEvent) Close() error
- func (ge *GoEvent) Dispatch(event Event) *DispatchHandle
- func (ge *GoEvent) GetErrors() []*EventError
- func (ge *GoEvent) RegisterListener(listeners ...Listener)
- func (ge *GoEvent) UnregisterListenersForEvent(eventName string) error
- func (ge *GoEvent) Wait()
- type Listener
- type ListenerOptions
- type ListenerWithOptions
- type RedisConfig
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func RegisterEventType ¶ added in v1.1.0
func RegisterEventType(event Event)
RegisterEventType registers an event type for deserialization This must be called for all event types when using the Redis driver Typically called in init() functions
The event.Name() is used as the registry key, enabling cross-service communication where different services can have the same logical event with different package names.
Example:
func init() {
goevent.RegisterEventType(&UserCreatedEvent{})
// Registers with key from event.Name(), e.g., "user.created"
}
func RegisterEventTypeAs ¶ added in v1.1.0
RegisterEventTypeAs registers an event type with a custom type name This allows explicit control over the registry key, useful for: - Event versioning (e.g., "order.created.v1") - Custom naming conventions - Migrating between naming schemes
Example:
func init() {
goevent.RegisterEventTypeAs("order.created.v1", &OrderCreatedEvent{})
}
Types ¶
type Config ¶ added in v1.1.0
type Config struct {
// Driver specifies which driver to use (memory or redis)
Driver DriverType
// Redis configuration (required when Driver is DriverRedis)
Redis *RedisConfig
}
Config configures the GoEvent instance
type DispatchHandle ¶
type DispatchHandle struct {
// contains filtered or unexported fields
}
DispatchHandle represents a handle to a specific event dispatch It allows waiting for and collecting errors from that specific dispatch
func (*DispatchHandle) Done ¶
func (dh *DispatchHandle) Done() <-chan struct{}
Done returns a channel that closes when all handlers complete Useful for select statements
func (*DispatchHandle) GetErrors ¶
func (dh *DispatchHandle) GetErrors() []*EventError
GetErrors returns errors that occurred during this specific dispatch
func (*DispatchHandle) Wait ¶
func (dh *DispatchHandle) Wait()
Wait blocks until all async handlers for this specific dispatch complete
type Driver ¶ added in v1.1.0
type Driver interface {
// Publish sends an event to all registered listeners
// Returns an error if the event cannot be published
Publish(eventName string, handle *DispatchHandle, event Event) error
// Subscribe registers a handler for an event
// isAsync indicates if the handler should execute asynchronously
Subscribe(eventName string, handler EventHandler, isAsync bool) error
// Unsubscribe removes all handlers for a specific event
// This is idempotent - calling it multiple times for the same event is safe
// Returns nil if the event was not subscribed or if unsubscribe succeeded
Unsubscribe(eventName string) error
// Wait blocks until all pending async operations complete
// For memory driver: waits for all async handlers
// For Redis driver: waits for local async handlers only
Wait()
// Close cleanly shuts down the driver and releases resources
Close() error
}
Driver abstracts the underlying event dispatch mechanism Implementations include in-memory (memoryDriver) and distributed (redisDriver)
type DriverType ¶ added in v1.1.0
type DriverType string
DriverType specifies which driver implementation to use
const ( // DriverMemory uses in-memory EventBus for same-process communication DriverMemory DriverType = "memory" // DriverRedis uses Redis pub/sub for distributed communication DriverRedis DriverType = "redis" )
type EventError ¶
EventError wraps errors that occur during event handling
func (*EventError) Error ¶
func (e *EventError) Error() string
type EventHandler ¶ added in v1.1.0
type EventHandler func(handle *DispatchHandle, event Event)
EventHandler is the normalized handler signature used by drivers The handler receives the dispatch handle and event to process
type EventRegistry ¶ added in v1.1.0
type EventRegistry struct {
// contains filtered or unexported fields
}
EventRegistry manages event type registration for deserialization Required for Redis driver to reconstruct typed events from JSON
func (*EventRegistry) Create ¶ added in v1.1.0
func (er *EventRegistry) Create(typeName string, payloadJSON json.RawMessage) (Event, error)
Create creates a new event instance from a type name and payload Returns an error if the type is not registered
func (*EventRegistry) IsRegistered ¶ added in v1.1.0
func (er *EventRegistry) IsRegistered(typeName string) bool
IsRegistered checks if an event type is registered
func (*EventRegistry) Register ¶ added in v1.1.0
func (er *EventRegistry) Register(event Event)
Register adds an event type to the registry using event.Name() as the key Deprecated: Use RegisterEventType() instead
func (*EventRegistry) RegisterAs ¶ added in v1.1.0
func (er *EventRegistry) RegisterAs(typeName string, event Event)
RegisterAs adds an event type to the registry with a custom type name
type GoEvent ¶
type GoEvent struct {
// contains filtered or unexported fields
}
GoEvent is a type-safe event bus with pluggable drivers
func New ¶
func New() *GoEvent
New creates a new GoEvent instance with the default in-memory driver This provides backward compatibility with existing code
func NewWithConfig ¶ added in v1.1.0
NewWithConfig creates a new GoEvent instance with custom configuration If cfg is nil, defaults to memory driver
func (*GoEvent) ClearErrors ¶
func (ge *GoEvent) ClearErrors()
ClearErrors clears all recorded errors
func (*GoEvent) Close ¶ added in v1.1.0
Close cleanly shuts down the event bus and releases resources This should be called when the event bus is no longer needed It waits for all pending handlers to complete before closing
func (*GoEvent) Dispatch ¶
func (ge *GoEvent) Dispatch(event Event) *DispatchHandle
Dispatch publishes an event to all registered listeners and returns a handle The handle can be used to wait for this specific dispatch to complete and retrieve errors that occurred during this dispatch
For memory driver: Wait() blocks until all handlers complete For Redis driver: Wait() only blocks for LOCAL handlers (not remote processes)
func (*GoEvent) GetErrors ¶
func (ge *GoEvent) GetErrors() []*EventError
GetErrors returns all errors that occurred during event handling This method is thread-safe
func (*GoEvent) RegisterListener ¶
RegisterListener registers one or more listeners to the event bus If a listener implements ListenerWithOptions and Options().Async is true, it will execute asynchronously. Otherwise, it executes synchronously.
func (*GoEvent) UnregisterListenersForEvent ¶ added in v1.1.0
UnregisterListenersForEvent removes all listeners for a specific event After calling this, no listeners will handle events with this name This is thread-safe and can be called while events are being dispatched
Example:
evt.UnregisterListenersForEvent("user.created")
type Listener ¶
Listener represents a basic event listener By default, listeners execute synchronously
type ListenerOptions ¶
type ListenerOptions struct {
// Async determines if the listener should execute asynchronously
Async bool
}
ListenerOptions provides configuration for how a listener should execute
type ListenerWithOptions ¶
type ListenerWithOptions interface {
Listener
Options() ListenerOptions
}
ListenerWithOptions represents a listener with custom execution options
type RedisConfig ¶ added in v1.1.0
type RedisConfig struct {
// Connection settings
Addr string // Redis server address (e.g., "localhost:6379")
Password string // Redis password (empty string if no password)
DB int // Redis database number (0-15)
// Pub/Sub settings
ChannelPrefix string // Prefix for Redis channels (default: "goevent:")
// Serialization settings
MaxEventSize int // Maximum event size in bytes (default: 1MB)
// Connection pooling (optional)
PoolSize int // Maximum number of socket connections (default: 10)
MinIdleConns int // Minimum number of idle connections (default: 0)
// Timeouts (optional)
DialTimeout time.Duration // Timeout for establishing connections (default: 5s)
ReadTimeout time.Duration // Timeout for socket reads (default: 3s)
WriteTimeout time.Duration // Timeout for socket writes (default: 3s)
// TLS configuration (optional)
TLSConfig *tls.Config
}
RedisConfig configures the Redis driver