64 lines
2.9 KiB
Go
64 lines
2.9 KiB
Go
// Package eventbus is enkly's thin wrapper around RabbitMQ (via
|
|
// github.com/rabbitmq/amqp091-go) for every *asynchronous*,
|
|
// fire-and-forget cross-context notification — the counterpart to the
|
|
// synchronous, request/response calls services make over gRPC (see
|
|
// api/proto). Per-service request/response traffic (e.g. the agent
|
|
// service asking billing "is this user over quota?") always uses gRPC;
|
|
// RabbitMQ is reserved for events a publisher doesn't need an answer to,
|
|
// mirroring the rule stated in the task: "gRPC for synchronous
|
|
// communication, RabbitMQ for asynchronous communication."
|
|
//
|
|
// Topology: one durable topic exchange, "enkly.events". Each event is
|
|
// published with a routing key of the form "<context>.<aggregate>.
|
|
// <event>" (e.g. "iam.user.registered"); a consumer binds a durable
|
|
// queue to the routing keys it cares about. Using a topic exchange
|
|
// rather than one queue per consumer lets a new consumer be added later
|
|
// (e.g. an analytics service) without touching the publisher.
|
|
package eventbus
|
|
|
|
// ExchangeName is the single durable topic exchange every service
|
|
// publishes domain events to.
|
|
const ExchangeName = "enkly.events"
|
|
|
|
// Routing keys. Each constant is "<owning context>.<aggregate>.<event,
|
|
// past tense>" — only the owning bounded context ever publishes to its
|
|
// own keys (see each service's internal/infrastructure/eventing
|
|
// package), but any service may subscribe.
|
|
const (
|
|
// Published by iam (services/iam) — see internal/handlers/auth.go's
|
|
// sendVerificationEmail/sendResetEmail, now decoupled from the
|
|
// synchronous request path.
|
|
RoutingKeyVerificationCodeIssued = "iam.user.verification_code_issued"
|
|
RoutingKeyPasswordResetRequested = "iam.user.password_reset_requested"
|
|
RoutingKeyUserRegistered = "iam.user.registered"
|
|
RoutingKeyUserEmailVerified = "iam.user.email_verified"
|
|
|
|
// Published by billing (services/billing).
|
|
RoutingKeySubscriptionChanged = "billing.subscription.changed"
|
|
|
|
// Published by conversation (services/conversation) — not consumed
|
|
// by anything in this port of the monolith, but kept so a future
|
|
// consumer (search indexing, analytics, audit) has something to
|
|
// bind to without a producer-side change.
|
|
RoutingKeyMessageCreated = "conversation.message.created"
|
|
)
|
|
|
|
// QueueBinding names the durable queue a consumer should declare and
|
|
// the routing key(s) it should bind, so every consumer's topology is
|
|
// declared in one place next to the keys it reads.
|
|
type QueueBinding struct {
|
|
Queue string
|
|
RoutingKeys []string
|
|
}
|
|
|
|
// NotificationQueueBindings is the notification service's subscription
|
|
// (services/notification/internal/infrastructure/eventing) — every
|
|
// event that results in an outbound email.
|
|
var NotificationQueueBindings = QueueBinding{
|
|
Queue: "enkly.notification.verification_and_reset",
|
|
RoutingKeys: []string{
|
|
RoutingKeyVerificationCodeIssued,
|
|
RoutingKeyPasswordResetRequested,
|
|
},
|
|
}
|