Files
poimen/tasks/T7.5-partition-keys-on-adapters.md

87 lines
3.5 KiB
Markdown

# T7.5 — Partition keys on adapters
| Field | Value |
|---|---|
| Phase | P7 — Distribution |
| Size | S — under 1 day |
| Status | Not started |
| Flags | — |
| Spec | inlined below |
| Blocks | — |
## Goal
Every broker adapter sets the partition key from `(TenantId, RunId)`. Never from
a correlation id.
## Facts (inlined — no spec read needed)
- **Per-run total order, nothing promised across runs.** Downstream consumers
must therefore partition by run key.
- A **correlation id collapses unrelated runs onto one partition while splitting
single runs across several** — the exact inversion of the ordering contract.
- The same reasoning drives the outbox key shape: per `BranchKey`, ascending
`Lsn`, which is what gives the relay its defined order.
- Ordering guarantees are only as strong as the weakest adapter, so this applies
to every adapter shipped, not just the first one.
## Steps
1. Define one helper that derives the partition key from `(TenantId, RunId)` and
make every adapter call it. A single function is what makes this auditable.
2. Remove any adapter parameter that lets a caller supply their own partition
key. If one is needed for an external contract, name it explicitly and
document that ordering is then the caller's problem.
3. Wire the helper into the relay's publish path (T7.4).
4. Test: two runs sharing a correlation id land on different partitions.
5. Test: all events of one run land on a single partition — assert across a run
that spans branches and attempts.
## Acceptance
- Two runs sharing a correlation land on **different partitions**.
- One run's events **never split across partitions**.
## Verify
**Harness:** a broker (or fake) exposing the partition assignment per message.
**Integration test**`tests/it_partition_keys.rs`:
1. Two runs sharing one correlation id. Assert their events land on **different**
partitions.
2. One run spanning multiple branches, attempts and steps. Assert **every** event
lands on a **single** partition.
3. Two tenants with colliding `RunId` values. Assert they do not share a
partition — the tenant must be in the key.
4. Assert every shipped adapter derives its key through the one shared helper —
an audit test enumerating adapters and asserting each calls it.
5. Assert no public adapter parameter allows a caller-supplied partition key; if
one exists for an external contract, assert it is separately named and
documented.
6. Stability: the same `(TenantId, RunId)` maps to the same partition across
process restarts.
**Command:** `cargo test -p distribution partition_keys`
**False pass:**
- Step 2 with a short run whose events happen to hash to one partition regardless.
Use a run long enough that a per-event key would demonstrably split it, and
assert the partition set has size exactly 1.
- Step 1 passing by coincidence with only two runs — use 50 correlated pairs and
assert the distribution is spread.
- Step 4 omitted: one adapter doing it correctly proves nothing about the next
one added, and ordering is only as strong as the weakest adapter.
## Traps
- Using a correlation id because it is already threaded through the request. It
is the natural choice and it breaks the only ordering promise the system makes.
- Hashing `RunId` alone without the tenant. Two tenants can then collide on one
partition and, worse, the key stops being tenant-scoped.
---
Background (not required to do this task):
[rust-agentic-sys.md](../../../rust-agentic-sys.md) §8.3, §9.2 ·
[rust-agentic-task.md](../../../rust-agentic-task.md)