Broadcaster for Multi-Sink Distribution
The Broadcaster
is a core component of the go-events
library, responsible for distributing events to multiple sinks.
Why Multi-Sink Distribution?
The Broadcaster
enables a publish-subscribe model for events, allowing multiple components within a system to register as event listeners, receive and process the same events. This architecture offers significant benefits:
- Decoupling: Event producers and consumers operate independently, reducing dependencies and promoting modularity.
- Scalability: New listeners can be added without impacting existing code, facilitating growth and expansion.
- Flexibility: Different components can subscribe to specific events based on their requirements, enabling tailored responses.
- Resilience: If a listener fails, the event distribution continues without interruption, ensuring system reliability.
Broadcaster Implementation
The Broadcaster
uses a concurrent approach, allowing multiple listeners to process events simultaneously.
Key Components:
Event
Interface: Defines the contract for events, requiring aType()
method to identify the event type.Sink
Interface: Defines the contract for event listeners, requiring aReceive(Event)
method to handle received events.Broadcaster
Struct: Manages the event distribution, containing a map of event types to a list of sinks registered for each type.
Core Functionality:
- Registering Sinks: Sinks are registered using the
Register(EventType, Sink)
method, associating the sink with a specific event type. - Broadcasting Events: Events are broadcast using the
Broadcast(Event)
method. The broadcaster first identifies the event type and then dispatches the event to all registered sinks for that type. - Unregistering Sinks: Sinks can be removed using the
Unregister(EventType, Sink)
method, ensuring they no longer receive events of the specified type.
Usage Examples
Example 1: Simple Event Broadcasting
package main
import (
"fmt"
"github.com/docker/go-events"
)
// Define a custom event type.
type MyEvent struct {
Message string
}
// Implement the Event interface.
func (e MyEvent) Type() string {
return "my.event"
}
// Define a sink that prints received events.
type PrintSink struct{}
func (s PrintSink) Receive(e events.Event) {
myEvent, ok := e.(MyEvent)
if ok {
fmt.Println("Received event:", myEvent.Message)
}
}
func main() {
// Create a broadcaster.
broadcaster := events.NewBroadcaster()
// Register a sink for "my.event".
broadcaster.Register("my.event", PrintSink{})
// Create an event instance.
myEvent := MyEvent{Message: "Hello, world!"}
// Broadcast the event.
broadcaster.Broadcast(myEvent)
}
Example 2: Multi-Sink Event Handling
package main
import (
"fmt"
"github.com/docker/go-events"
)
// Define a custom event type.
type MyEvent struct {
Message string
}
// Implement the Event interface.
func (e MyEvent) Type() string {
return "my.event"
}
// Define two sinks that handle events differently.
type PrintSink struct{}
func (s PrintSink) Receive(e events.Event) {
myEvent, ok := e.(MyEvent)
if ok {
fmt.Println("PrintSink:", myEvent.Message)
}
}
type LogSink struct{}
func (s LogSink) Receive(e events.Event) {
myEvent, ok := e.(MyEvent)
if ok {
fmt.Println("LogSink:", myEvent.Message)
}
}
func main() {
// Create a broadcaster.
broadcaster := events.NewBroadcaster()
// Register both sinks for "my.event".
broadcaster.Register("my.event", PrintSink{})
broadcaster.Register("my.event", LogSink{})
// Create an event instance.
myEvent := MyEvent{Message: "Hello, world!"}
// Broadcast the event.
broadcaster.Broadcast(myEvent)
}
Example 3: Event Type Specific Sinks
package main
import (
"fmt"
"github.com/docker/go-events"
)
// Define two event types.
type EventOne struct{}
func (e EventOne) Type() string {
return "event.one"
}
type EventTwo struct{}
func (e EventTwo) Type() string {
return "event.two"
}
// Define sinks for each event type.
type SinkOne struct{}
func (s SinkOne) Receive(e events.Event) {
fmt.Println("SinkOne received EventOne")
}
type SinkTwo struct{}
func (s SinkTwo) Receive(e events.Event) {
fmt.Println("SinkTwo received EventTwo")
}
func main() {
// Create a broadcaster.
broadcaster := events.NewBroadcaster()
// Register sinks for specific event types.
broadcaster.Register("event.one", SinkOne{})
broadcaster.Register("event.two", SinkTwo{})
// Broadcast different events.
broadcaster.Broadcast(EventOne{})
broadcaster.Broadcast(EventTwo{})
}
Source: broadcaster.go