CommandBus: stream existence hints on command registration (NewStream, Existing, Any) #36

Open
opened 2026-02-20 01:15:32 +00:00 by ash · 0 comments
Owner

What

When registering a command handler, declare a stream existence hint:

bus.Register(CreateOrder{}, orderDecider, eskit.HintNewStream)
bus.Register(ShipOrder{}, orderDecider, eskit.HintExisting)
bus.Register(AddItem{}, orderDecider, eskit.HintAny)  // default

Behavior

  • HintNewStream: Skip loading events from store. Pass zero-state to Decide(). Use expectedVersion=0 on append. OCC catches races. Saves a read round-trip on create commands.
  • HintExisting: Load events. If stream is empty/not found → return error immediately without calling Decide(). Fast-fail for commands on non-existent streams.
  • HintAny: Current default behavior. Load → Decide → Append.

Key: these are performance hints, not business rules

  • The Decider still owns all business logic
  • If hint is wrong, OCC or Decider catches it — correctness never compromised
  • Hints are declared once at registration, not per-call

Reference

Myrra has this on command registration (StreamMustExist, StreamMustNotExist, Any).

Benchmark

  • Measure: read cost on empty stream vs skipping read (HintNewStream)
  • Measure: cost of wasted Decide call vs fast-fail (HintExisting)
  • Per store: Memory, SQLite, Postgres, NATS
  • Prove whether the optimization actually matters

Tests

  • HintNewStream: create succeeds, duplicate create fails (OCC)
  • HintExisting: command on existing stream works, command on non-existent fast-fails
  • HintAny: same as current behavior
  • Wrong hint + correct decider: still correct result
  • Benchmark: HintNewStream vs HintAny on create throughput
## What When registering a command handler, declare a stream existence hint: ```go bus.Register(CreateOrder{}, orderDecider, eskit.HintNewStream) bus.Register(ShipOrder{}, orderDecider, eskit.HintExisting) bus.Register(AddItem{}, orderDecider, eskit.HintAny) // default ``` ## Behavior - **HintNewStream**: Skip loading events from store. Pass zero-state to Decide(). Use expectedVersion=0 on append. OCC catches races. Saves a read round-trip on create commands. - **HintExisting**: Load events. If stream is empty/not found → return error immediately without calling Decide(). Fast-fail for commands on non-existent streams. - **HintAny**: Current default behavior. Load → Decide → Append. ## Key: these are performance hints, not business rules - The Decider still owns all business logic - If hint is wrong, OCC or Decider catches it — correctness never compromised - Hints are declared once at registration, not per-call ## Reference Myrra has this on command registration (StreamMustExist, StreamMustNotExist, Any). ## Benchmark - Measure: read cost on empty stream vs skipping read (HintNewStream) - Measure: cost of wasted Decide call vs fast-fail (HintExisting) - Per store: Memory, SQLite, Postgres, NATS - Prove whether the optimization actually matters ## Tests - HintNewStream: create succeeds, duplicate create fails (OCC) - HintExisting: command on existing stream works, command on non-existent fast-fails - HintAny: same as current behavior - Wrong hint + correct decider: still correct result - Benchmark: HintNewStream vs HintAny on create throughput
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
ash/eskit#36
No description provided.