registry: pin fleet-projection stability and scoping
Two gaps the Task 10 review named in the fingerprint tests. The stability loop only ever ran with region 'eu' rows — zero of which match the projection — so the GROUP_CONCAT path whose instability would mean a 2s reload storm on every fleet box forever was never exercised at all. TestFingerprintStableWithFleetRoutes seeds three fleet-placed routes with mixed FleetBox values (stamped, stamped differently, placed but unstamped) plus one ordinary route, guards that the projection is actually non-empty, and then asserts stability across the five polls. Nothing noticed if the projection's WHERE ever widened, which would put every ordinary route write into a values list. The fleet-less test now asserts the fingerprint's final component is empty (a trailing ':') — the scoping claim itself, checked rather than asserted in a comment.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 file changed,
+49
−0
internal/registry/fleets_test.go+49 −0
diff --git a/internal/registry/fleets_test.go b/internal/registry/fleets_test.go| index 6c3012419..6ca730ad6 100644 |
| --- a/internal/registry/fleets_test.go |
| +++ b/internal/registry/fleets_test.go |
| @@ -475,6 +475,55 @@ func TestFingerprintStableWithoutFleetRoutes(t *testing.T) { |
| t.Fatalf("fingerprint flapped with no writes at all: %q then %q", first, again) |
| } |
| } |
| + // The scoping claim itself, pinned: with no fleet-placed route in the |
| + // table the projection must be the EMPTY string — the fingerprint's last |
| + // component, hence a trailing ':'. Nothing else notices if that WHERE |
| + // clause ever widens (dropping the filter, or matching a bare region code |
| + // like the "eu" rows above), and a widened projection would put every |
| + // ordinary route write into a values list — turning any route edit on a |
| + // non-fleet box into a fingerprint change it does not need, and putting |
| + // hostnames' worth of text through a 2s poll for nothing. |
| + if !strings.HasSuffix(first, ":") { |
| + t.Fatalf("fingerprint = %q, want an empty final component (trailing ':') when no route is fleet-placed — the projection's WHERE has widened beyond fleet rows", first) |
| + } |
| +} |
| + |
| +// The other half of the stability question, and the one that actually |
| +// exercises the concat: with fleet-placed routes present the projection is |
| +// non-empty and built by GROUP_CONCAT over an ORDER BY subquery. If that |
| +// order were not stable across identical polls, the edge would see a |
| +// "changed" fingerprint every 2 seconds and reload forever — on every box |
| +// running a fleet, permanently. Mixed FleetBox values (one stamped, one |
| +// stamped differently, one placed but unstamped) so a reordering has |
| +// something to reorder. |
| +func TestFingerprintStableWithFleetRoutes(t *testing.T) { |
| + reg := openTestRegistry(t) |
| + for _, rt := range []Route{ |
| + {Host: "one.example", Kind: "instance", Region: PlacementTarget("pi"), FleetBox: "box-a"}, |
| + {Host: "two.example", Kind: "instance", Region: PlacementTarget("pi"), FleetBox: "box-b"}, |
| + {Host: "three.example", Kind: "instance", Region: PlacementTarget("eleven"), FleetBox: ""}, |
| + {Host: "four.example", Kind: "service", Addr: "127.0.0.1:1"}, // not fleet-placed |
| + } { |
| + if err := reg.Upsert(rt); err != nil { |
| + t.Fatal(err) |
| + } |
| + } |
| + first, err := reg.Fingerprint() |
| + if err != nil { |
| + t.Fatal(err) |
| + } |
| + if strings.HasSuffix(first, ":") { |
| + t.Fatalf("fingerprint = %q, want a NON-empty final component — with three fleet-placed routes the projection this test exists to exercise is empty, so the stability loop below proves nothing", first) |
| + } |
| + for i := 0; i < 5; i++ { |
| + again, err := reg.Fingerprint() |
| + if err != nil { |
| + t.Fatal(err) |
| + } |
| + if again != first { |
| + t.Fatalf("fingerprint flapped across identical polls with fleet routes present: %q then %q — every edge running a fleet would reload every 2s forever", first, again) |
| + } |
| + } |
| } |
| // TestFleetPlacement pins the "fleet/<name>" grammar Route.Region carries |