Documentation
¶
Overview ¶
Package relay provides a high-throughput, type-safe pub/sub event bus with sharded subscriber storage, configurable backpressure, and graceful shutdown.
Create a bus with NewChanBus, subscribe with Subscribe or SubscribeContext, and broadcast events with Broadcast or TryBroadcast.
Index ¶
- Variables
- type AggregateStats
- type BroadcastResult
- type Bus
- type ChanBus
- func (c *ChanBus[T]) Broadcast(event T) BroadcastResult
- func (c *ChanBus[T]) Close() error
- func (c *ChanBus[T]) CloseGracefully(ctx context.Context) error
- func (c *ChanBus[T]) Len() int
- func (c *ChanBus[T]) Stats() AggregateStats
- func (c *ChanBus[T]) Subscribe(options ...ChanSubscriptionOption) (Subscription[T], error)
- func (c *ChanBus[T]) SubscribeContext(ctx context.Context, options ...ChanSubscriptionOption) (Subscription[T], error)
- func (c *ChanBus[T]) TryBroadcast(event T) (BroadcastResult, bool)
- type ChanBusOption
- func WithBroadcastCallback(cb func(duration time.Duration, alive, dropped int)) ChanBusOption
- func WithContext(ctx context.Context) ChanBusOption
- func WithPoolSize(poolSize int) ChanBusOption
- func WithShardCount(shardCount int) ChanBusOption
- func WithSlowSubscriberPolicy(policy SlowSubscriberPolicy) ChanBusOption
- func WithSlowSubscriberTimeout(timeout time.Duration) ChanBusOption
- func WithSubscriptionBackpressure(backpressure int) ChanBusOption
- type ChanSubscription
- type ChanSubscriptionOption
- type Shards
- func (s *Shards[T]) All() []*ChanSubscription[T]
- func (s *Shards[T]) Cleanup()
- func (s *Shards[T]) Len() int
- func (s *Shards[T]) Snapshot() []*subList[T]
- func (s *Shards[T]) Subscribe(sub *ChanSubscription[T]) int
- func (s *Shards[T]) Unsubscribe(sub *ChanSubscription[T])
- func (s *Shards[T]) UnsubscribeAt(idx int, sub *ChanSubscription[T])
- type SlowSubscriberPolicy
- type Subscription
- type SubscriptionStats
Constants ¶
This section is empty.
Variables ¶
Functions ¶
This section is empty.
Types ¶
type AggregateStats ¶
AggregateStats holds bus-wide delivery metrics across all active subscriptions.
type BroadcastResult ¶
type BroadcastResult struct {
// contains filtered or unexported fields
}
BroadcastResult allows waiting for a broadcast to finish.
func (BroadcastResult) Wait ¶
func (b BroadcastResult) Wait() error
Wait blocks until the broadcast completes and returns an error if the bus was closed before or during the broadcast (ErrBusClosed) or if the broadcast was rejected due to a full semaphore (ErrBroadcastFull).
func (BroadcastResult) WaitContext ¶
func (b BroadcastResult) WaitContext(ctx context.Context) error
WaitContext blocks until the broadcast completes or ctx is cancelled. It may return ErrBusClosed or ErrBroadcastFull.
type Bus ¶
type Bus[T any] interface { // Broadcast sends an event to all active subscribers. It returns // immediately; use BroadcastResult.Wait() to block until delivery is // complete. If poolSize > 0, Broadcast blocks until the semaphore has room. Broadcast(event T) BroadcastResult // TryBroadcast attempts to broadcast without blocking. It returns (result, // true) on success, or (result, false) if the semaphore is saturated. // The result's Wait() will return ErrBroadcastFull. TryBroadcast(event T) (BroadcastResult, bool) // Subscribe creates a new subscription with the bus defaults. Additional // ChanSubscriptionOption values may override those defaults. Subscribe(options ...ChanSubscriptionOption) (Subscription[T], error) // SubscribeContext creates a subscription tied to the given context. When // ctx is cancelled, the subscription is automatically unsubscribed. SubscribeContext(ctx context.Context, options ...ChanSubscriptionOption) (Subscription[T], error) // Len returns the total number of subscribers currently connected to the bus. Len() int // Stats returns aggregate delivery statistics across all active subscriptions. Stats() AggregateStats // Close force-closes the bus immediately. In-flight broadcasts are not // waited for. Close() error // CloseGracefully rejects new operations, waits for in-flight broadcasts // to finish (or until ctx is cancelled), and then closes the bus. CloseGracefully(ctx context.Context) error }
Bus[T] is a type-safe event broadcaster. Implementations must be safe for concurrent use by multiple goroutines.
type ChanBus ¶
type ChanBus[T any] struct { // contains filtered or unexported fields }
func NewChanBus ¶
func NewChanBus[T any](options ...ChanBusOption) *ChanBus[T]
NewChanBus creates a new event bus with the provided options.
func (*ChanBus[T]) Broadcast ¶
func (c *ChanBus[T]) Broadcast(event T) BroadcastResult
Broadcast sends the event to all active subscribers. It blocks until the semaphore has room (if poolSize is configured), then returns immediately; use BroadcastResult.Wait() to block until the fan-out is complete.
func (*ChanBus[T]) CloseGracefully ¶
CloseGracefully initiates a graceful shutdown. It rejects new subscriptions and broadcasts, waits for all in-flight broadcasts to complete (or until ctx is cancelled), and then closes the bus. If ctx expires before all broadcasts finish, the bus is force-closed and ctx.Err() is returned.
func (*ChanBus[T]) Len ¶
Len returns the total number of subscribers currently connected to the bus.
func (*ChanBus[T]) Stats ¶
func (c *ChanBus[T]) Stats() AggregateStats
Stats returns aggregate statistics across all active subscriptions.
func (*ChanBus[T]) Subscribe ¶
func (c *ChanBus[T]) Subscribe(options ...ChanSubscriptionOption) (Subscription[T], error)
func (*ChanBus[T]) SubscribeContext ¶
func (c *ChanBus[T]) SubscribeContext(ctx context.Context, options ...ChanSubscriptionOption) (Subscription[T], error)
SubscribeContext creates a new subscription attached to ctx.
func (*ChanBus[T]) TryBroadcast ¶
func (c *ChanBus[T]) TryBroadcast(event T) (BroadcastResult, bool)
TryBroadcast attempts to broadcast immediately. It returns the result and true on success, or false if the broadcast semaphore is saturated.
type ChanBusOption ¶
type ChanBusOption func(cfg *busConfig)
ChanBusOption configures a ChanBus during construction.
func WithBroadcastCallback ¶
func WithBroadcastCallback(cb func(duration time.Duration, alive, dropped int)) ChanBusOption
WithBroadcastCallback attaches a callback that is invoked after every broadcast completes. It receives the broadcast duration, the number of active (alive) subscribers, and how many events were dropped.
func WithContext ¶
func WithContext(ctx context.Context) ChanBusOption
WithContext sets the parent context for the bus. When this context is cancelled, all operations (Subscribe, Broadcast) will fail with ErrBusClosed.
func WithPoolSize ¶
func WithPoolSize(poolSize int) ChanBusOption
WithPoolSize caps the number of concurrent broadcast goroutines. A value of 0 means unlimited; values > 0 create a semaphore of that size. If the semaphore is full, Broadcast blocks until room is available, while TryBroadcast returns ErrBroadcastFull. Defaults to runtime.GOMAXPROCS(0).
func WithShardCount ¶
func WithShardCount(shardCount int) ChanBusOption
WithShardCount sets the number of subscriber shards. Higher values reduce subscribe/unsubscribe contention but increase the cost of snapshots. Defaults to runtime.GOMAXPROCS(0).
func WithSlowSubscriberPolicy ¶
func WithSlowSubscriberPolicy(policy SlowSubscriberPolicy) ChanBusOption
WithSlowSubscriberPolicy selects how the bus treats a subscriber whose buffer is full. Block waits, Drop skips immediately, Timeout gives up after WithSlowSubscriberTimeout. Defaults to Block.
func WithSlowSubscriberTimeout ¶
func WithSlowSubscriberTimeout(timeout time.Duration) ChanBusOption
WithSlowSubscriberTimeout sets the per-subscriber timeout used by the Timeout policy. Has no effect on Block or Drop policies.
func WithSubscriptionBackpressure ¶
func WithSubscriptionBackpressure(backpressure int) ChanBusOption
WithSubscriptionBackpressure sets the default buffer size for every subscriber created by this bus. Individual subscriptions may override this with SubWithBackpressure. A value of 0 creates an unbuffered channel.
type ChanSubscription ¶
type ChanSubscription[T any] struct { // contains filtered or unexported fields }
func NewChanSubscription ¶
func NewChanSubscription[T any](options ...ChanSubscriptionOption) *ChanSubscription[T]
func (*ChanSubscription[T]) Close ¶
func (c *ChanSubscription[T]) Close() error
func (*ChanSubscription[T]) Listen ¶
func (c *ChanSubscription[T]) Listen(ctx context.Context) (T, error)
func (*ChanSubscription[T]) Stats ¶
func (c *ChanSubscription[T]) Stats() SubscriptionStats
func (*ChanSubscription[T]) String ¶
func (c *ChanSubscription[T]) String() string
func (*ChanSubscription[T]) Unsubscribe ¶
func (c *ChanSubscription[T]) Unsubscribe()
type ChanSubscriptionOption ¶
type ChanSubscriptionOption func(cfg *chanSubscriptionConfig)
ChanSubscriptionOption configures an individual subscription during creation.
func SubWithBackpressure ¶
func SubWithBackpressure(backpressure int) ChanSubscriptionOption
SubWithBackpressure sets the size of the subscription's internal buffer. A value of 0 creates an unbuffered channel.
func SubWithContext ¶
func SubWithContext(ctx context.Context) ChanSubscriptionOption
SubWithContext sets the parent context for the subscription. When this context is cancelled, Listen returns the context error.
func SubWithUnsubscribeCallback ¶
func SubWithUnsubscribeCallback(unsubscribeCallback func()) ChanSubscriptionOption
SubWithUnsubscribeCallback registers a function that is called when the subscription is unsubscribed. The bus also installs its own internal callback to remove the subscription from the shard; both are executed.
type Shards ¶
type Shards[T any] struct { // contains filtered or unexported fields }
Shards holds subscriber lists partitioned across K shards.
func (*Shards[T]) All ¶
func (s *Shards[T]) All() []*ChanSubscription[T]
All returns every subscription in every shard.
func (*Shards[T]) Cleanup ¶
func (s *Shards[T]) Cleanup()
Cleanup removes dead subscriptions from every shard.
func (*Shards[T]) Snapshot ¶
func (s *Shards[T]) Snapshot() []*subList[T]
Snapshot returns a copy of all current shard lists.
func (*Shards[T]) Subscribe ¶
func (s *Shards[T]) Subscribe(sub *ChanSubscription[T]) int
Subscribe places sub into the next shard by round-robin. On success it returns the shard index that was chosen.
func (*Shards[T]) Unsubscribe ¶
func (s *Shards[T]) Unsubscribe(sub *ChanSubscription[T])
Unsubscribe scans all shards when the shard index is unknown. Prefer UnsubscribeAt.
func (*Shards[T]) UnsubscribeAt ¶
func (s *Shards[T]) UnsubscribeAt(idx int, sub *ChanSubscription[T])
UnsubscribeAt removes sub from shard idx only.
type SlowSubscriberPolicy ¶
type SlowSubscriberPolicy int
SlowSubscriberPolicy controls how the bus behaves when a subscriber's channel is full or the subscriber is otherwise slow to consume events.
const ( // SlowSubscriberPolicyBlock waits until the subscriber has room in its // buffer or until the subscriber/bus context is cancelled. SlowSubscriberPolicyBlock SlowSubscriberPolicy = iota // SlowSubscriberPolicyDrop skips the subscriber immediately if its buffer // is full. No event is lost for other subscribers. SlowSubscriberPolicyDrop // SlowSubscriberPolicyTimeout attempts delivery for up to the configured // duration (see WithSlowSubscriberTimeout) before skipping the subscriber. SlowSubscriberPolicyTimeout )
type Subscription ¶
type Subscription[T any] interface { Listen(ctx context.Context) (T, error) Unsubscribe() Stats() SubscriptionStats String() string Close() error }
Subscription[T] represents a single consumer attached to a Bus.
type SubscriptionStats ¶
SubscriptionStats holds per-subscription delivery metrics.