The bus on NATS: both transports behind seams, and the rollout switch #87
@@ -27,6 +27,14 @@ const TheBuildMachine = "mesh-build-machine"
|
||||
func BuildWork() string { return "mesh.seat." + TheBuildMachine + ".accept.build" }
|
||||
func BuildOutcome() string { return "mesh.seat." + TheBuildMachine + ".event.built" }
|
||||
|
||||
// KeyRoleBuilt is the build outcome under the role's name, on the bus the mesh runs on today.
|
||||
//
|
||||
// The same event as KeyModuleBuilt and published beside it, because a catalogue installed before this
|
||||
// change listens for the module's name and one installed after listens for the role's. Both, until
|
||||
// this bus retires: a rename needs publisher and subscriber to change together, and a deployment
|
||||
// cannot promise which arrives first.
|
||||
const KeyRoleBuilt = "built"
|
||||
|
||||
// Builders is how work reaches a build machine and how the outcome comes back.
|
||||
type Builders interface {
|
||||
// Submit asks for one build and waits for its outcome.
|
||||
|
||||
@@ -161,8 +161,26 @@ func (b *currentBuild) Announce(ctx context.Context, result BuildResult) error {
|
||||
if result.Failed != "" || result.Commit == "" {
|
||||
return nil
|
||||
}
|
||||
return EmitEvent(ctx, OverCurrent{Channel: b.channel}, KeyModuleBuilt, "builder", b.on,
|
||||
announcementOf(result))
|
||||
|
||||
// **Announced under both names on this bus, for exactly as long as this bus lives.**
|
||||
//
|
||||
// A build's outcome belongs to the role now (novox/hq ADR 0121), so a catalogue built from the
|
||||
// current manifests listens for the role's name. A catalogue that is *already running* listens for
|
||||
// the module's, because that is what it was told when it was installed. A rename on a live bus
|
||||
// needs the publisher and the subscriber to change together, and a merge cannot promise that: one
|
||||
// of them is deployed first, and in that window the graph silently stops being updated — which is
|
||||
// the failure this whole change was cleaning up after.
|
||||
//
|
||||
// So both, and the order stops mattering. The module's own name goes with the bus, in step 5's
|
||||
// retirement list; nothing has ever run on the bus being built, so there is no legacy name there
|
||||
// and this doubling has no counterpart.
|
||||
announced := announcementOf(result)
|
||||
if err := EmitEvent(ctx, OverCurrent{Channel: b.channel}, KeyModuleBuilt, "builder", b.on,
|
||||
announced); err != nil {
|
||||
return err
|
||||
}
|
||||
return EmitEvent(ctx, OverCurrent{Channel: b.channel}, KeyRoleBuilt, TheBuildMachine, b.on,
|
||||
announced)
|
||||
}
|
||||
|
||||
func (b *currentBuild) Done() error { return b.delivery.Ack(false) }
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
package link
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// **The old bus announces a build under both names, and that is not belt-and-braces.**
|
||||
//
|
||||
// A build's outcome belongs to the role now, so a catalogue built from the current manifests listens
|
||||
// for the role's name — and a catalogue already running listens for the module's, because that is what
|
||||
// it was told when it was installed. A rename on a live bus needs publisher and subscriber to change
|
||||
// together, which a deployment cannot promise: one arrives first, and in that window the module graph
|
||||
// silently stops being updated.
|
||||
//
|
||||
// Caught by asking what merging this would do to the mesh that is actually running, which is the only
|
||||
// place the question could have been asked — the tests were green and both buses were self-consistent.
|
||||
func TestTheOldBusAnnouncesABuildUnderBothNames(t *testing.T) {
|
||||
// The routing key a catalogue installed before the change is bound to.
|
||||
if KeyModuleBuilt != "module.builder.built" {
|
||||
t.Fatalf("the module's own name is %q; a catalogue already running is bound to the old one",
|
||||
KeyModuleBuilt)
|
||||
}
|
||||
// And the local name a catalogue built from the current manifests declares, which the old bus's
|
||||
// client turns into `module.<role>.built`.
|
||||
if KeyRoleBuilt != "built" {
|
||||
t.Fatalf("the role's event is %q, and a holder emits its verbs bare", KeyRoleBuilt)
|
||||
}
|
||||
if TheBuildMachine != "mesh-build-machine" {
|
||||
t.Fatalf("the role is %q", TheBuildMachine)
|
||||
}
|
||||
// The two must differ, or one publish would serve both and this doubling would be pointless.
|
||||
if strings.HasSuffix(KeyModuleBuilt, "."+TheBuildMachine+"."+KeyRoleBuilt) {
|
||||
t.Fatal("the two names are the same, so nothing was renamed and this is dead weight")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user