The controller's outbound link behind a seam, with both transports
Step 3.4, first half. Every one of these took an *amqp.Channel, so the transport reached every caller and swapping it meant touching all of them. The seam turned out to be small — the controller sends exactly two kinds of message that expect no answer — which is the same measurement that said this bus could be replaced at all. Bus is stated in the mesh's words, not a transport's: PublishEvent and PublishDeclaration. Two implementations, both shipping, because steps 1 to 4 leave every node on AMQP and the NATS one is selected at the rollout. Both ship is also what makes them comparable: one conformance fixture holds both to the same envelope, and the NATS one is checked against a real server reading back from the stream rather than from the code that wrote it. Still on *amqp.Channel: RequestBuild and Ask, which carry reply-queue machinery, and the whole consume side — the control loop, enrolment, serve.
This commit is contained in:
+7
-25
@@ -6,9 +6,6 @@ import (
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
amqp "github.com/rabbitmq/amqp091-go"
|
||||
)
|
||||
|
||||
// Emitting a module event from Go.
|
||||
@@ -29,32 +26,17 @@ const (
|
||||
|
||||
// EmitEvent publishes one module event, in the envelope the sdk's consumers expect.
|
||||
//
|
||||
// Persistent, because an event that a broker restart loses is not an announcement. The publish is
|
||||
// not confirmed here: the caller has already done the work the event describes, and a build that
|
||||
// succeeded must not be reported as failed because saying so failed.
|
||||
func EmitEvent(ctx context.Context, channel *amqp.Channel, eventType, source, node string, body any) error {
|
||||
// The envelope is the transport's to write (bus.go) and this is only what goes in it, which is
|
||||
// what lets one conformance fixture hold both implementations to the same headers.
|
||||
func EmitEvent(ctx context.Context, bus Bus, eventType, source, node string, body any) error {
|
||||
payload, err := json.Marshal(body)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot serialise a %s event: %w", eventType, err)
|
||||
}
|
||||
id, err := eventID()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return channel.PublishWithContext(ctx, EventsExchange, eventType, false, false, amqp.Publishing{
|
||||
ContentType: "application/json",
|
||||
DeliveryMode: amqp.Persistent,
|
||||
MessageId: id,
|
||||
Timestamp: time.Now().UTC(),
|
||||
Body: payload,
|
||||
Headers: amqp.Table{
|
||||
"x-event-id": id,
|
||||
"x-source": source,
|
||||
"x-node": node,
|
||||
"x-time": time.Now().UTC().Format(time.RFC3339),
|
||||
"content-type": "application/json",
|
||||
},
|
||||
})
|
||||
// The publish is not confirmed by the caller: it has already done the work the event
|
||||
// describes, and a build that succeeded must not be reported as failed because saying so
|
||||
// failed. Each transport decides what "published" means for it.
|
||||
return bus.PublishEvent(ctx, eventType, source, node, payload)
|
||||
}
|
||||
|
||||
// eventID is what a consumer deduplicates on: delivery is at-least-once, so a handler must be able
|
||||
|
||||
Reference in New Issue
Block a user