← 1.0.0 scope SAPE-19

Declare an operation against a running daemon — frame 13

Status
Done
Version
1.0.0
Component
protocol, server
Commits
72f6b2c, 59909d0, 44b8298
Opened
ISS-2, ISS-7, ISS-8, ISS-13

Description

store.DeclareOperation could only be reached through sapedb apply, and that command opens the database file directly and takes the exclusive lock — a run while the server is up is refused. So adding one operation meant stopping the server, applying, and starting it again: every live connection dropped, for a change that writes one key.

Frame type 13, Declare (internal/protocol/frame.go:57), sends the same declaration down a connection that already exists. internal/server/declare.go is the handler.

It is not a second, looser way in:

Why it was in 1.0.0

Frame numbers 1…13 freeze at the tag. Adding a frame type afterwards is additive and cheap; leaving a gap where Declare should have been, and filling it later, is not. And the product's whole claim is that a declaration is the only way into a database — a product where declaring one requires taking the database down is a claim with an asterisk on it.

How it was verified

  1. TestDeclaringNeedsMoreThanAConnectionString (internal/server/declare_test.go:112) — the operator proof, not the connection string, is what opens this path.
  2. TestDeclaringTheSameNameAgainIsANewVersionAndTheOldOneStillRuns (declare_test.go:160) and TestADeclarationOverTheWireSurvivesTheServerBeingRestarted (declare_test.go:365).
  3. TestDeclaringFromManyConnectionsAtOnceIsOneWriterAtATime (declare_test.go:281) — this takes the write lock, not the read one, and that is measured rather than asserted.
  4. Same rules as apply: TestDeclaringOverTheWireRefusesExactlyWhatApplyRefuses (internal/cli/declare_apply_test.go:44) runs one table down both paths; TestAScanDeclaredOverTheWireMustSayHowManyRowsItMayReturn (declare_test.go:50) and TestACountDeclaredOverTheWireMustSayHowFarItWalks (internal/server/count_limit_test.go:27) cover the two limit rules.
  5. TestEveryRequestFixtureDecodesIntoTheStructThatServesIt (internal/server/fixture_decode_test.go:28) is the general form of a guard that existed for exactly one frame, which is why the others were free to drift. It found one: the invoke case in fixtures/frames.json carried {"op": ...} while call's field has always been json:"command". Both sides round-tripped perfectly because both were reading the same wrong file, and that file is published as the conformance specification other languages build against. Fixed in 59909d0.
  6. TestDeclaringOverTheWireGoesIntoTheLogWithAnActor (internal/server/declare_actor_test.go:41) — 44b8298 gave DeclareOperation a Caller so the change log says who.

What it did not do