The gate takes owed.ended and take-in.taken from its manifest's consumes and names neither the forge bridge nor the indexer in code (milestone 47/G, the names move)
The module's own manifest is embedded (package at the module's root); an event the gate hears from another module is the consumes entry with that event's name after its owner. No new seat, no second publisher on the seat git (the lead's ruling). Rows in the manifest test, which also reads the gate's sources for those names. Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ (Joined from 2de87fd8.) Builds: design 47 G §7, §146 (GATE16); the bridge's name stays in code for the old merge follower (eb131beb left out, G §167, §542) Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
This commit is contained in:
@@ -100,7 +100,7 @@ func newTestBus(t *testing.T) *testBus {
|
||||
// The streams the events are on (mesh.mod.<module>.event.<name>, mesh.seat.<seat>.event.<name>).
|
||||
if _, err := js.CreateStream(context.Background(), jetstream.StreamConfig{Name: "EVENTS",
|
||||
Subjects: []string{"mesh.seat.git.event.>", "mesh.seat." + oc.Seat + ".event.>",
|
||||
"mesh.mod." + forgeBridgeModule + ".event.>"}}); err != nil {
|
||||
"mesh.mod.mesh-delivery-forge-bridge.event.>"}}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
return b
|
||||
|
||||
@@ -12,6 +12,7 @@ package main
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
ownmanifest "mesh-delivery-gate"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
@@ -48,12 +49,37 @@ type stepFamily struct {
|
||||
// The step events on main the record is built from. A family is added here, with its `consumes` line, when its owner
|
||||
// publishes it (design 47 *What each step says*); each other step's event is its owner's to add in the same milestone.
|
||||
var stepFamilies = []stepFamily{
|
||||
// An entry taken in (the indexer's own `take-in.taken`, ADR 0633 §1): the merges a source revision took in.
|
||||
{Pattern: indexerModule + "." + takein.TakeInTakenEvent, Owner: indexerModule, Event: takein.TakeInTakenEvent, Decode: decodeTakenIn},
|
||||
// An entry taken in (the holder of the seat mesh-catalog's own `take-in.taken`, ADR 0633 §1): the merges a source
|
||||
// revision took in. Its owner is the one the manifest consumes it from.
|
||||
family(takein.TakeInTakenEvent, decodeTakenIn),
|
||||
}
|
||||
|
||||
// indexerModule is the holder of the seat mesh-catalog whose own events the record hears.
|
||||
const indexerModule = "mesh-delivery-indexer"
|
||||
// family is a step family of an event as the manifest consumes it: `<owner>.<event>`.
|
||||
func family(event string, decode func(json.RawMessage, time.Time) ([]StepOutcome, error)) stepFamily {
|
||||
pattern := declared(event)
|
||||
owner, _, _ := strings.Cut(pattern, ".")
|
||||
return stepFamily{Pattern: pattern, Owner: owner, Event: event, Decode: decode}
|
||||
}
|
||||
|
||||
// consumed is what the gate's manifest consumes (its own manifest): every event it follows is one of them.
|
||||
var consumed = func() []string {
|
||||
c, err := ownmanifest.Consumes()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return c
|
||||
}()
|
||||
|
||||
// declared is the event the manifest consumes under this name after its owner, `<owner>.<event>`: the gate names no
|
||||
// other module in code. Empty, and so never followed or matched, when the manifest consumes none.
|
||||
func declared(event string) string {
|
||||
for _, c := range consumed {
|
||||
if _, name, ok := strings.Cut(c, "."); ok && name == event {
|
||||
return c
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// stepPatterns are the patterns of every family, in the order the manifest consumes them.
|
||||
func stepPatterns() []string {
|
||||
|
||||
@@ -93,6 +93,27 @@ func TestItClaimsTheDeliverySeatAndFollowsWhatItHandles(t *testing.T) {
|
||||
t.Errorf("the manifest still consumes %s (ADR 0539 §17)", c)
|
||||
}
|
||||
}
|
||||
// The names move (milestone 47/G): the families heard from another module are its manifest's consumes, and no Go
|
||||
// source of the gate names those modules.
|
||||
if !slices.Contains(m.Consumes, owedEndedEvent) || owedEndedEvent == "" || len(stepFamilies) != 1 ||
|
||||
!slices.Contains(m.Consumes, stepFamilies[0].Pattern) || stepFamilies[0].Owner+"."+stepFamilies[0].Event != stepFamilies[0].Pattern {
|
||||
t.Fatalf("owed.ended is %q and the step families %+v, not the manifest's consumes %v", owedEndedEvent, stepFamilies, m.Consumes)
|
||||
}
|
||||
sources, _ := filepath.Glob("*.go")
|
||||
for _, f := range sources {
|
||||
if strings.HasSuffix(f, "_test.go") {
|
||||
continue
|
||||
}
|
||||
raw, err := os.ReadFile(f)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
for _, name := range []string{`"mesh-delivery-indexer`} {
|
||||
if strings.Contains(string(raw), name) {
|
||||
t.Errorf("%s names %s in code: it is the manifest's to say", f, name)
|
||||
}
|
||||
}
|
||||
}
|
||||
if !reflect.DeepEqual(m.Consumes, followed) || !slices.Contains(m.Consumes, "mesh-delivery-forge-bridge.forge.**") {
|
||||
t.Fatalf("consumes %v, follows %v (the bridge's forge messages among them)", m.Consumes, followed)
|
||||
}
|
||||
|
||||
@@ -10,8 +10,8 @@ import (
|
||||
)
|
||||
|
||||
// owedEndedEvent is the forge bridge's word on an act owed, owed.ended on its stream forge (design 47 *What the gate owes
|
||||
// the forge*): the outcome of one id, the gate's own or the checker's.
|
||||
const owedEndedEvent = forgeBridgeModule + "." + forgemsg.OwedEndedEvent
|
||||
// the forge*): the outcome of one id, the gate's own or the checker's. Its owner is the one the manifest consumes it from.
|
||||
var owedEndedEvent = declared(forgemsg.OwedEndedEvent)
|
||||
|
||||
// OwedEnded takes the forge bridge's outcome of one act this owner said as owed. The outcome is written into the delivery
|
||||
// record that holds the pull request at that head, and only then is the act answered: taken off its delivery's or group's
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
// Package gate holds the delivery gate's own manifest, so its code takes from the manifest's declarations what it hears,
|
||||
// never another module's name written in code.
|
||||
package gate
|
||||
|
||||
import (
|
||||
_ "embed"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
//go:embed module.json
|
||||
var manifest []byte
|
||||
|
||||
// Consumes is what the gate's manifest consumes, in its order.
|
||||
func Consumes() ([]string, error) {
|
||||
var m struct {
|
||||
Consumes []string `json:"consumes"`
|
||||
}
|
||||
if err := json.Unmarshal(manifest, &m); err != nil {
|
||||
return nil, fmt.Errorf("the gate's own manifest is not readable: %w", err)
|
||||
}
|
||||
return m.Consumes, nil
|
||||
}
|
||||
Reference in New Issue
Block a user