events

package
v0.1.1 Latest Latest
Warning

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

Go to latest
Published: Jun 11, 2026 License: MIT Imports: 2 Imported by: 0

README

events

import "github.com/brpaz/lib-go/events"

Package events provides a synchronous, in-process event bus for decoupled communication between components.

The Bus dispatches events to registered handlers in the order they were subscribed. Publishing is synchronous — Publish returns only after every handler has run (or the first one returns an error).

Defining events

Each event is a small, immutable type that implements Event by returning a stable string key:

type OrderPlacedEvent struct {
    OrderID string
    Total   int64
}

func (e OrderPlacedEvent) EventType() string { return "order.placed" }
Publishing

Services hold a Publisher (or the concrete *Bus) and call Publish after the primary operation succeeds:

_ = s.publisher.Publish(ctx, OrderPlacedEvent{
    OrderID: order.ID,
    Total:   order.Total,
})

Use _ = to swallow the error when handler failures must not abort the primary operation. Return the error when cleanup is a hard requirement.

Subscribing

Register handlers against the shared Bus during startup:

bus.Subscribe("order.placed", func(ctx context.Context, e events.Event) error {
    evt := e.(OrderPlacedEvent)
    return invoicing.CreateDraft(ctx, evt.OrderID, evt.Total)
})
Testing

Pass NoopPublisher when a component needs a Publisher but the test doesn't care about events, and FakePublisher to assert which events were published:

pub := events.NewFakePublisher()
svc := NewOrderService(pub)

_ = svc.Place(ctx, order)
assert.Equal(t, []events.Event{
    OrderPlacedEvent{OrderID: order.ID, Total: order.Total},
}, pub.Published())
Swapping the implementation

Code should depend on the Publisher interface rather than *Bus directly. This allows swapping to a distributed broker (e.g. NATS, Kafka) by providing a different implementation at the wiring layer without touching the rest of the codebase.

Index

type Bus

Bus is a synchronous, in-process event bus.

type Bus struct {
    // contains filtered or unexported fields
}

func New
func New() *Bus

New returns a ready-to-use Bus.

func (*Bus) Publish
func (b *Bus) Publish(ctx context.Context, event Event) error

Publish calls all handlers registered for event.EventType() in order. Returns the first handler error encountered; remaining handlers are not called.

func (*Bus) Subscribe
func (b *Bus) Subscribe(eventType string, h Handler)

Subscribe registers h to be called whenever an event of the given type is published.

type Event

Event is implemented by all domain events.

type Event interface {
    EventType() string
}

type FakePublisher

FakePublisher records every published event instead of dispatching it. Use it in tests to assert which events a service published, without wiring a Bus and handlers. Safe for concurrent use.

type FakePublisher struct {
    // contains filtered or unexported fields
}

func NewFakePublisher
func NewFakePublisher() *FakePublisher

NewFakePublisher creates an empty FakePublisher.

func (*FakePublisher) Publish
func (p *FakePublisher) Publish(_ context.Context, event Event) error

Publish records event and returns nil.

func (*FakePublisher) Published
func (p *FakePublisher) Published() []Event

Published returns a copy of every event recorded so far, in publish order.

type Handler

Handler is a function that handles a published event.

type Handler func(ctx context.Context, event Event) error

type NoopPublisher

NoopPublisher discards every event. Use it as a default Publisher when events are disabled or irrelevant to the code under test.

type NoopPublisher struct{}

func NewNoopPublisher
func NewNoopPublisher() NoopPublisher

NewNoopPublisher returns a ready-to-use NoopPublisher.

func (NoopPublisher) Publish
func (NoopPublisher) Publish(_ context.Context, _ Event) error

Publish does nothing and returns nil.

type Publisher

Publisher is responsible for publishing events to subscribers. Implementations can be in-process (like the provided Bus) or distributed (e.g., using a message broker).

type Publisher interface {
    Publish(ctx context.Context, event Event) error
}

type Subscriber

Subscriber allows registration of handlers for specific event types.

type Subscriber interface {
    Subscribe(eventType string, h Handler)
}

Generated by gomarkdoc

Documentation

Overview

Package events provides a synchronous, in-process event bus for decoupled communication between components.

The Bus dispatches events to registered handlers in the order they were subscribed. Publishing is synchronous — Publish returns only after every handler has run (or the first one returns an error).

Defining events

Each event is a small, immutable type that implements Event by returning a stable string key:

type OrderPlacedEvent struct {
    OrderID string
    Total   int64
}

func (e OrderPlacedEvent) EventType() string { return "order.placed" }

Publishing

Services hold a Publisher (or the concrete *Bus) and call Publish after the primary operation succeeds:

_ = s.publisher.Publish(ctx, OrderPlacedEvent{
    OrderID: order.ID,
    Total:   order.Total,
})

Use _ = to swallow the error when handler failures must not abort the primary operation. Return the error when cleanup is a hard requirement.

Subscribing

Register handlers against the shared Bus during startup:

bus.Subscribe("order.placed", func(ctx context.Context, e events.Event) error {
    evt := e.(OrderPlacedEvent)
    return invoicing.CreateDraft(ctx, evt.OrderID, evt.Total)
})

Testing

Pass NoopPublisher when a component needs a Publisher but the test doesn't care about events, and FakePublisher to assert which events were published:

pub := events.NewFakePublisher()
svc := NewOrderService(pub)

_ = svc.Place(ctx, order)
assert.Equal(t, []events.Event{
    OrderPlacedEvent{OrderID: order.ID, Total: order.Total},
}, pub.Published())

Swapping the implementation

Code should depend on the Publisher interface rather than *Bus directly. This allows swapping to a distributed broker (e.g. NATS, Kafka) by providing a different implementation at the wiring layer without touching the rest of the codebase.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Bus

type Bus struct {
	// contains filtered or unexported fields
}

Bus is a synchronous, in-process event bus.

func New

func New() *Bus

New returns a ready-to-use Bus.

func (*Bus) Publish

func (b *Bus) Publish(ctx context.Context, event Event) error

Publish calls all handlers registered for event.EventType() in order. Returns the first handler error encountered; remaining handlers are not called.

func (*Bus) Subscribe

func (b *Bus) Subscribe(eventType string, h Handler)

Subscribe registers h to be called whenever an event of the given type is published.

type Event

type Event interface {
	EventType() string
}

Event is implemented by all domain events.

type FakePublisher

type FakePublisher struct {
	// contains filtered or unexported fields
}

FakePublisher records every published event instead of dispatching it. Use it in tests to assert which events a service published, without wiring a Bus and handlers. Safe for concurrent use.

func NewFakePublisher

func NewFakePublisher() *FakePublisher

NewFakePublisher creates an empty FakePublisher.

func (*FakePublisher) Publish

func (p *FakePublisher) Publish(_ context.Context, event Event) error

Publish records event and returns nil.

func (*FakePublisher) Published

func (p *FakePublisher) Published() []Event

Published returns a copy of every event recorded so far, in publish order.

type Handler

type Handler func(ctx context.Context, event Event) error

Handler is a function that handles a published event.

type NoopPublisher

type NoopPublisher struct{}

NoopPublisher discards every event. Use it as a default Publisher when events are disabled or irrelevant to the code under test.

func NewNoopPublisher

func NewNoopPublisher() NoopPublisher

NewNoopPublisher returns a ready-to-use NoopPublisher.

func (NoopPublisher) Publish

func (NoopPublisher) Publish(_ context.Context, _ Event) error

Publish does nothing and returns nil.

type Publisher

type Publisher interface {
	Publish(ctx context.Context, event Event) error
}

Publisher is responsible for publishing events to subscribers. Implementations can be in-process (like the provided Bus) or distributed (e.g., using a message broker).

type Subscriber

type Subscriber interface {
	Subscribe(eventType string, h Handler)
}

Subscriber allows registration of handlers for specific event types.

Jump to

Keyboard shortcuts

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