B5g7-2: the indexer takes a pushed message alike with a merged one
Its head stands where a merged message's merge stands: forgeKind, pending refs, the newest load and the revision's head. Builds: design 47 G §509, §714, A-269 Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
This commit is contained in:
@@ -245,6 +245,7 @@ func handle(ctx context.Context, m delivered, ix *index.Indexer, heard index.Sto
|
||||
if f.Merge != "" {
|
||||
h.Commit = f.Merge
|
||||
}
|
||||
f = index.RevisionForm(f) // a pushed message is taken in as a merged one is, its head where the merge stands (§509, A-269)
|
||||
var applied index.Applied
|
||||
if f.Kind == forgemsg.ForgeMerged && h.Sequence > 0 {
|
||||
// A merge is taken in only by the indexer its revision names (ADR 0633 §1): kept in pending until then.
|
||||
@@ -282,7 +283,7 @@ func forgeKind(data []byte) (string, bool) {
|
||||
return "", true
|
||||
}
|
||||
switch probe.Kind {
|
||||
case forgemsg.ForgePull, forgemsg.ForgeMerged, forgemsg.ForgeRefused, forgemsg.ForgeOpen:
|
||||
case forgemsg.ForgePull, forgemsg.ForgeMerged, forgemsg.ForgePushed, forgemsg.ForgeRefused, forgemsg.ForgeOpen:
|
||||
return probe.Kind, true
|
||||
}
|
||||
return probe.Kind, false
|
||||
|
||||
@@ -258,3 +258,12 @@ func ptr[T any](v T) *T { return &v }
|
||||
|
||||
// noWire is a finding writer that is none: a non-nil WireWriter for the test of which emitter is made.
|
||||
type noWire struct{ views.WireWriter }
|
||||
|
||||
// Design 47 G §509, §714, A-269: the indexer takes a pushed message alike with a merged one.
|
||||
func TestTheIndexerTakesAPushedMessage(t *testing.T) {
|
||||
for _, kind := range []string{forgemsg.ForgeMerged, forgemsg.ForgePushed} {
|
||||
if got, known := forgeKind([]byte(`{"kind":"` + kind + `"}`)); !known || got != kind {
|
||||
t.Errorf("forgeKind(%s) = %q, %v, want it taken", kind, got, known)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -136,10 +136,20 @@ func DecodePending(data []byte) (Pending, forgemsg.Forge, error) {
|
||||
if err != nil {
|
||||
return p, f, fmt.Errorf("its merged message: %w", err)
|
||||
}
|
||||
if f.Kind != forgemsg.ForgeMerged {
|
||||
return p, f, fmt.Errorf("a pending value holds a %s message, not a merged one", f.Kind)
|
||||
if f.Kind != forgemsg.ForgeMerged && f.Kind != forgemsg.ForgePushed {
|
||||
return p, f, fmt.Errorf("a pending value holds a %s message, not a merged or pushed one", f.Kind)
|
||||
}
|
||||
return p, f, nil
|
||||
return p, RevisionForm(f), nil
|
||||
}
|
||||
|
||||
// RevisionForm is a message the take-in holds as a revision's member (design 47 G §509, §714, A-269): a pushed message's head
|
||||
// stands where a merged message's merge stands, so pending refs, the newest load and the revision's head key on it alike.
|
||||
// A merged message is returned as it is.
|
||||
func RevisionForm(f forgemsg.Forge) forgemsg.Forge {
|
||||
if f.Kind == forgemsg.ForgePushed {
|
||||
f.Kind, f.Merge = forgemsg.ForgeMerged, f.Head
|
||||
}
|
||||
return f
|
||||
}
|
||||
|
||||
func encodePending(p Pending) ([]byte, error) {
|
||||
@@ -247,6 +257,7 @@ func (ix *Indexer) load(ctx context.Context, e PendingEntry) (PendingEntry, erro
|
||||
if err != nil {
|
||||
return e, fmt.Errorf("the forge bridge's answer for %s is not a forge message: %w", e.Key, err)
|
||||
}
|
||||
f = RevisionForm(f)
|
||||
if f.Kind != forgemsg.ForgeMerged || f.Repository != e.Forge.Repository || f.Merge != e.Forge.Merge || (e.Forge.Number > 0 && f.Number != e.Forge.Number) {
|
||||
return e, fmt.Errorf("the forge bridge's answer is not the merge %s#%d at %s that %s refers to", e.Forge.Repository, e.Forge.Number, e.Forge.Merge, e.Key)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
package index
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"testing"
|
||||
|
||||
"git.novox.be/novox/mesh-delivery/modules/mesh-delivery-forge-bridge/forgemsg"
|
||||
)
|
||||
|
||||
// Design 47 G §509, §714, A-269: a pushed message's head stands where a merged message's merge stands: the pending value keeps
|
||||
// it as its ref, the newest load reads it from the bridge's answer and the pending value read back holds it alike.
|
||||
func TestAPushedMessageStandsInTheRevisionWhereAMergedMessageDoes(t *testing.T) {
|
||||
b := newTakeInBed(t)
|
||||
head := "5555555555555555555555555555555555555555"
|
||||
pushed := b.base
|
||||
pushed.Kind, pushed.Number, pushed.Merge, pushed.Base, pushed.Branch, pushed.Head = forgemsg.ForgePushed, 0, "", "", "feat/x", head
|
||||
data, err := forgemsg.EncodeForge(pushed)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
b.bridge[pushed.Repository+"@"+head] = data // the bridge answers by the head, where a merge's commit would stand
|
||||
|
||||
f := RevisionForm(pushed)
|
||||
if f.Kind != forgemsg.ForgeMerged || f.Merge != head {
|
||||
t.Fatalf("RevisionForm = %s %q, want a merged form at the head", f.Kind, f.Merge)
|
||||
}
|
||||
value, err := encodePending(Pending{Seq: 9, Ref: refOf(f)})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
_, got, err := DecodePending(value)
|
||||
if err != nil || got.Merge != head {
|
||||
t.Fatalf("DecodePending of the ref = %+v, %v, want the head as its merge", got, err)
|
||||
}
|
||||
// A value an earlier indexer wrote with the pushed message whole reads alike.
|
||||
whole, _ := json.Marshal(Pending{V: 1, Seq: 9, Forge: data})
|
||||
if _, got, err = DecodePending(whole); err != nil || got.Merge != head || got.Kind != forgemsg.ForgeMerged {
|
||||
t.Fatalf("DecodePending of the whole message = %+v, %v", got, err)
|
||||
}
|
||||
// The load reads the bridge's pushed answer for the ref and accepts it.
|
||||
loaded, err := b.ix.load(context.Background(), PendingEntry{Key: "m.9", Value: Pending{Seq: 9}, Forge: RevisionForm(pushed), Light: true})
|
||||
if err != nil || loaded.Forge.Merge != head || loaded.Light {
|
||||
t.Fatalf("load = %+v, %v, want the pushed message read at the head", loaded.Forge, err)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user