events

package module
v0.0.2 Latest Latest
Warning

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

Go to latest
Published: Jul 15, 2026 License: MIT Imports: 1 Imported by: 0

README

events

Typed pub/sub contract: Publisher/Subscriber decoupled from the broker implementation. A domain module fires and listens to events without knowing whether delivery happens in-process (module-to-module, same binary) or over the wire (push to a browser via SSE).

Why

Every module used to redeclare its own EventPublisher, and none of them agreed: some took payload any, some threaded a context through the call, none had a Subscriber at all. A module that wanted to react to another module's event had nothing typed to depend on but that module's own ad-hoc interface.

Quick Start

import "github.com/tinywasm/events"

const TopicItemCreated = "catalog.item.created"

type ItemCreated struct{ ID, Name string }

func (e *ItemCreated) IsNil() bool { return e == nil }
func (e *ItemCreated) EncodeFields(w model.FieldWriter) {
    w.String("id", e.ID)
    w.String("name", e.Name)
}

// A module that publishes depends on events.Publisher only.
func (m *Module) create(item CatalogItem) {
    // … persist …
    m.pub.Publish(events.Event{Topic: TopicItemCreated, Payload: &ItemCreated{ID: item.Id, Name: item.Name}})
}

// A module that reacts depends on events.Subscriber only.
func (m *Notifier) Init(sub events.Subscriber) {
    sub.Subscribe(TopicItemCreated, func(e events.Event) {
        if item, ok := e.Payload.(*ItemCreated); ok {
            m.notify(item.Name)
        }
    })
}

Neither module imports the other, and neither imports a concrete broker. The composition root builds ONE broker and hands each module the narrower contract (Publisher or Subscriber) it declared it needs.

Contracts

  • Event: Topic string + Payload model.Encodable — never any.
  • Handler: func(Event) — what a subscriber registers.
  • Publisher: Publish(Event) — fire-and-forget.
  • Subscriber: Subscribe(topic string, h Handler) — fan-out: every Subscribe on the same topic receives the event.
  • Broker: Publisher + Subscriber — the full contract a composition root injects.
  • mock: the reference Broker — synchronous, in-process. Used both as the real module-to-module implementation inside a single binary and as the test double.
  • conformance: conformance.Run(t, conformance.Factory{New: ...}) — the executable behavior contract every Broker must pass, the same role router/conformance plays for router.Router.

Design

An event's Payload travels as the concrete Go value the publisher built. An in-process broker (mock.Broker) delivers it as-is — no serialization. A broker that crosses a real wire (github.com/tinywasm/sse, pushing to a browser) encodes Payload via its own EncodeFields when it needs to; that is the broker's concern, never the contract's or the module's.

No any in the public API surface beyond the one Go interface value (model.Encodable) every typed payload already satisfies.

Documentation

Overview

Package events is the typed pub/sub contract: a Publisher a domain module fires events through, and a Subscriber it (or another module) listens on — decoupled from whatever broker actually moves the message.

Before this package, every module redeclared its own EventPublisher, and none of them agreed: some took `payload any`, some threaded a context.Context through the call, none had a Subscriber at all. A module that published had to invent the interface its consumer would satisfy; a module that wanted to react to another module's event had nothing to depend on but that ad-hoc, per-module type.

This package is the contract both sides depend on instead. A module imports events + model — never a concrete broker (an in-process broker for module-to-module delivery, github.com/tinywasm/sse for push to the browser) — and the composition root injects the Broker.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Broker added in v0.0.2

type Broker interface {
	Publisher
	Subscriber
}

Broker is the full contract a composition root wires in: publish and subscribe together. Implementations: github.com/tinywasm/events/mock (in-process, for module-to-module delivery and tests) and github.com/tinywasm/sse (push to the browser).

type Event added in v0.0.2

type Event struct {
	// Topic identifies the kind of event, e.g. "catalog.item.created". The
	// publishing module exports it as a typed constant; a subscriber imports
	// that constant rather than repeating the string — the same convention as
	// an RPC operation name.
	Topic string
	// Payload is the event's data. A subscriber that needs the concrete shape
	// type-asserts it: the topic is the shared vocabulary between publisher and
	// subscriber, so both already agree on which concrete type travels on it.
	Payload model.Encodable
}

Event is one message on a topic: a name plus a typed payload — never `any`. Payload travels as the concrete Go value the publisher built. An in-process broker delivers it as-is, with no serialization. A broker that crosses a real wire (SSE to a browser) encodes Payload via its own EncodeFields when it needs to — that is the broker's concern, not this contract's.

type Handler added in v0.0.2

type Handler func(Event)

Handler receives one delivered Event.

type Publisher added in v0.0.2

type Publisher interface {
	Publish(e Event)
}

Publisher fires an event. Fire-and-forget: this contract makes no delivery-order or delivery-guarantee promise beyond "every currently-registered Subscriber for Event.Topic is invoked" — a broker that offers more (durability, ordering across processes) exposes that as its own, separately documented behavior.

type Subscriber added in v0.0.2

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

Subscriber registers a Handler for a topic. Multiple Subscribe calls on the same topic all receive the event (fan-out).

Directories

Path Synopsis
Package conformance is the executable contract of events.Broker.
Package conformance is the executable contract of events.Broker.
Package mock is the canonical in-process events.Broker: synchronous, in-memory fan-out.
Package mock is the canonical in-process events.Broker: synchronous, in-memory fan-out.

Jump to

Keyboard shortcuts

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