package push import "encoding/json" // Event is the typed contract for client events emitted onto the gRPC // push stream. Implementations carry their own serialiser; push.Service // invokes Marshal at publish time to obtain the bytes that go into // `pushv1.ClientEvent.Payload`. // // Notification dispatcher builds a typed FlatBuffers Event for every // catalog kind through `notification.buildClientPushEvent`, backed by // the per-kind helpers in `pkg/transcoder/notification.go`. JSONEvent // (below) remains the safety net for kinds that arrive without a // catalog schema. type Event interface { // Kind returns the catalog kind of this event (`backend/README.md` // ยง10). Empty kind is rejected at publish time. Kind() string // Marshal returns the bytes that travel inside // `pushv1.ClientEvent.Payload`. Implementations are expected to use // FlatBuffers (preferred) or any deterministic encoding the client // can decode; the push transport treats the result as opaque // payload bytes. Marshal() ([]byte, error) } // JSONEvent is the safety-net Event implementation for kinds that // arrive without a catalog FlatBuffers schema. It serialises Payload // via encoding/json so a misconfigured producer cannot silently drop // events while a new kind is being added. // // New kinds must ship with a typed FlatBuffers schema in // `pkg/schema/fbs/notification.fbs` and a matching case in // `notification.buildClientPushEvent`; JSONEvent is not a canonical // shape, only a fallback. type JSONEvent struct { // EventKind is the catalog kind returned by Kind(). EventKind string // Payload is the JSON-serialisable map written by the producer. Payload map[string]any } // Kind returns EventKind verbatim. func (e JSONEvent) Kind() string { return e.EventKind } // Marshal returns Payload encoded as JSON. The result is treated as // opaque bytes by the push transport. func (e JSONEvent) Marshal() ([]byte, error) { return json.Marshal(e.Payload) } var _ Event = JSONEvent{}