Send a CloudEvent over NATS¶
Publishing¶
nats.Header is defined as map[string][]string, the same type
Marshal returns, so this is a
type conversion rather than a copy:
headers, body, err := cloudevents.Marshal(e)
if err != nil {
return err
}
err = conn.PublishMsg(&nats.Msg{
Subject: "orders.created",
Header: nats.Header(headers),
Data: body,
})
Use go/nats's client rather than a bare nats.Conn. This module
has no opinion about which you use, but that one is where the bounded subscriptions and the shed
reporting live.
Subscribing¶
sub, err := client.Subscribe(ctx, "orders.created", func(msg *nats.Msg) {
e, err := cloudevents.Unmarshal(msg.Header, msg.Data)
if err != nil {
refused.Add(1)
logger.Error("refused a CloudEvent", "id", e.ID, "err", err)
return
}
handle(e)
})
Route on the type, not on the subject¶
A NATS subject and a CloudEvent type say overlapping things, and the temptation is to encode the
type into the subject and stop setting the attribute. Do not: the attribute is what makes the event
readable by a consumer that is not on NATS, and the round trip through HTTP or an object store keeps
it while the subject is lost at the first hop.
Publish to a subject that names the stream, and let type name the occurrence.
What this does not do¶
There is no Send(conn, subject, event) helper here, and there will not be one. It would have to
import nats.go, which would put NATS in the dependency graph of every service that sends a
CloudEvent over HTTP. Spec 0001 D4, and TestNoTransportIsImported enforces it.