carlos / platform Public

activator: a beacon to a hibernating route leaves lastActive alone

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Paul Campbell pushed by paul@keymail.dev 062be28235e9f3b7c38076323606e2a885f52288 parent beb0460
1 file changed, +40 −0
  • internal/activator/activator_test.go +40 −0
diff --git a/internal/activator/activator_test.go b/internal/activator/activator_test.go
index 5893ae761..8ead7934a 100644
--- a/internal/activator/activator_test.go
+++ b/internal/activator/activator_test.go
@@ -3995,3 +3995,43 @@ func TestChildProcStopClosesTheControlSocketWhenTheChildIsAlreadyGone(t *testing
t.Fatalf("control socket after Stop on an exited child: stat err = %v, want it unlinked", err)
}
}
+
+// A beacon to a hibernating route is answered by the edge before the
+// activator branch: lastActive is untouched and nothing is started
+// (spec §4: nothing here wakes an instance).
+func TestBrowserBeaconDoesNotStampActivity(t *testing.T) {
+ const host = "beacon.bab.oncarlos.com"
+ a, b, clk, reg := testActivator(t, time.Hour)
+ rt := testRoute(host)
+ arrangeAwake(t, a, rt)
+ if err := reg.Upsert(rt); err != nil {
+ t.Fatalf("Upsert %s: %v", rt.Host, err)
+ }
+ a.mu.Lock()
+ before := a.entries[rt.Host].lastActive
+ a.mu.Unlock()
+ clk.advance(time.Minute)
+ _, _, starts0 := b.counts()
+
+ e, err := edge.New(reg, a)
+ if err != nil {
+ t.Fatal(err)
+ }
+ rec := httptest.NewRecorder()
+ req := httptest.NewRequest("POST", "https://"+host+"/__carlos/a", strings.NewReader(`{"name":"n"}`))
+ req.Host = host
+ req.Header.Set("Origin", "https://"+host)
+ e.ServeHTTP(rec, req)
+ if rec.Code != http.StatusAccepted {
+ t.Fatalf("status %d", rec.Code)
+ }
+ a.mu.Lock()
+ after := a.entries[rt.Host].lastActive
+ a.mu.Unlock()
+ if !after.Equal(before) {
+ t.Errorf("lastActive moved %v -> %v", before, after)
+ }
+ if _, _, starts := b.counts(); starts != starts0 {
+ t.Errorf("a beacon started an instance")
+ }
+}