Event bus
pkg/events defines an Event containing type, string-map payload, and occurrence timestamp, plus the Bus publish/subscribe boundary and named event constants. Declaring an event constant does not mean every matching business operation already publishes it.
InMemoryBus invokes registered handlers synchronously before publish returns. It is useful for tests and offline composition. RabbitMQBus uses a durable topic exchange (prescriptoo.events by default), JSON serialization, routing by event type, and one server-named queue for each subscription to preserve fan-out. Subscriptions end with the bus connection. The running API constructs RabbitMQ, while offline contract generation uses documentation-safe dependencies.
Publish provider-owned canonical events after authoritative changes. The bus does not supply an outbox or make database commits and publication atomic. Review the current handlers and error policy before assuming retries, long-lived durable subscriptions, or exactly-once processing.
package events_test
import (
"context"
"fmt"
"github.com/prescriptoo/prescriptoo-api/pkg/events"
)
// InMemoryBus invokes each matching subscriber before Publish returns.
func ExampleInMemoryBus_Publish() {
bus := events.NewInMemoryBus()
if err := bus.Subscribe(events.UserRegistered, func(event events.Event) {
fmt.Println("Registered:", event.Payload["user_id"])
}); err != nil {
panic(err)
}
if err := bus.Publish(context.Background(), events.Event{
Type: events.UserRegistered, Payload: map[string]string{"user_id": "example-user"},
}); err != nil {
panic(err)
}
// Output: Registered: example-user
}Unit tests cover configuration validation, handler invocation, and panic recovery without requiring a broker. Any deployment-level broker/fan-out verification must be run separately.
Code reference
See the generated events package.