You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
## Summary
Phase 3.D PR 3 of the split-queue FIFO rollout (per §11 of
`docs/design/2026_04_26_proposed_sqs_split_queue_fifo.md`). Adds the
partitioned-keyspace constructors without touching the legacy keyspace
or any existing call site. The §11 PR 2 dormancy gate still rejects
`PartitionCount > 1` at `CreateQueue`, so these helpers are dead code in
production until PR 5 atomically lifts the gate and wires the data-plane
fanout.
## Keyspace shape
```
legacy: !sqs|msg|<family>|<queue>|<gen>|<rest>
partitioned: !sqs|msg|<family>|p|<queue>|<partition>|<gen>|<rest>
```
The `p|` discriminator after the family prefix is safe by construction:
`validateQueueName` forbids `|` in queue names, and the queue segment is
base32-raw-URL encoded (cannot start with the literal byte `'p'`
followed by `'|'`). The partition is a 4-byte big-endian `uint32` so a
prefix scan `!sqs|msg|<family>|p|<queue>|<partition>|` picks exactly one
partition's keys.
## What's added
- Constants: `sqsPartitionedDiscriminator`,
`SqsPartitionedMsg{Data,Vis,Dedup,Group,ByAge}Prefix`.
- Constructors: `sqsPartitionedMsg{Data,Vis,Dedup,Group,ByAge}Key`,
`sqsPartitionedMsgVisPrefixForQueue`,
`sqsPartitionedMsgByAgePrefixForQueueAllPartitions`.
- Reaper helper: `sqsMsgByAgePrefixesForQueue` returns the `{legacy,
partitioned}` pair so the reaper enumerates both keyspaces during
cleanup.
- Parser: `parseSqsPartitionedMsgByAgeKey` with the matching record type
`sqsPartitionedMsgByAgeRecord` (legacy `parseSqsMsgByAgeKey` is
unchanged).
- Helper: `appendU32` for the 4-byte partition segment.
## What's NOT added
- No existing call site changes — every current `sqsMsgDataKey` /
`sqsMsgVisKey` / etc. invocation keeps using the legacy constructor, so
existing queues stay byte-identical on disk.
- No dispatch wrapper. PR 5 will add the if/else dispatch at each call
site once `partitionFor` is wired into the send/receive paths (per the
§3.1 design choice of "dispatch at the call site, no variadic, no silent
argument loss").
## Test plan
`adapter/sqs_keys_test.go` covers:
- [x] Byte-distinct legacy vs partitioned across all 5 families (data,
vis, dedup, group, byage).
- [x] Per-partition isolation: a partition-k vis prefix never matches a
partition-(k+1) key.
- [x] Determinism: same inputs yield byte-identical keys across calls.
- [x] Round-trip parse for partitioned byage keys at corner partition
values (0, 7, 31).
- [x] Mutual rejection: legacy parser rejects partitioned keys and vice
versa (the dual-parse contract).
- [x] Reaper enumeration helper returns both prefixes in `{legacy,
partitioned}` order.
- [x] Discriminator constants all end with `p|`.
- [x] Different queue names produce different keys at the same
`(partition, gen)`.
- [x] `go test -race ./adapter/...` clean.
- [x] `golangci-lint ./adapter/...` clean.
## Self-review (per CLAUDE.md "Self-review of code changes")
1. **Data loss** — No FSM, Pebble, or retention path is touched. Legacy
constructors are unchanged on every byte and call site, so existing
queues are byte-identical on disk. The new partitioned helpers are dead
code until PR 5 lifts the dormancy gate, so no production data lands
under the partitioned prefix in this PR. No issue.
2. **Concurrency / distributed failures** — No new goroutine, lock, or
Raft path. The constructors are pure byte-builders. The reaper helper
returns a fresh slice per call. No issue.
3. **Performance** — New constructors are one allocation each, sized
like the legacy ones. The reaper enumeration adds at most one extra
`Range` iteration per queue (over the partitioned prefix, which is empty
for legacy queues). Hot path (Send/Receive) is untouched. No issue.
4. **Data consistency** — The `p|` discriminator + base32 queue segment
combination is verified non-overlapping. Legacy and partitioned
keyspaces cannot collide. Mutual-rejection tests assert each parser
refuses the other's keyspace. No issue.
5. **Test coverage** — 7 new test functions covering byte layout,
per-partition isolation, determinism, round-trip parse, mutual
rejection, reaper enumeration, and discriminator-constant invariants. PR
7 lands the HT-FIFO Jepsen suite per §11.
0 commit comments