Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
90ec782
docs(run-engine): spike design for RunQueue fair-queueing bake-off
1stvamp Jul 23, 2026
4b1c6e0
docs(run-engine): implementation plan for fair-queueing spike
1stvamp Jul 23, 2026
fa6af6b
test(run-engine): spike queue reader over master queue
1stvamp Jul 23, 2026
603488e
test(run-engine): spike seeded workload generator
1stvamp Jul 23, 2026
bf4ffa8
test(run-engine): spike fairness/latency metrics
1stvamp Jul 23, 2026
4aae14a
test(run-engine): spike driver over real RunQueue
1stvamp Jul 23, 2026
b837e10
feat(run-engine): spike SFQ, DRR, stride selectors and CoDel wrapper
1stvamp Jul 23, 2026
8940e40
feat(run-engine): spike bench matrix, scenarios, and results
1stvamp Jul 23, 2026
e882ba0
docs(run-engine): fair-queueing spike findings
1stvamp Jul 23, 2026
b19f4ef
test(run-engine): address spike review (multi-seed, CoDel, honesty)
1stvamp Jul 23, 2026
6ab36c4
test(run-engine): address inquisition (metric, floor, honesty)
1stvamp Jul 23, 2026
a693a68
docs(run-engine): design for per-concurrency-key fairness spike
1stvamp Jul 23, 2026
32f9a03
docs(run-engine): plan for per-concurrency-key fairness spike
1stvamp Jul 23, 2026
9a14dda
test(run-engine): CK-index reader for per-concurrency-key spike
1stvamp Jul 23, 2026
ba1e5b5
test(run-engine): ckIndex rescorer drives real Lua pick order
1stvamp Jul 23, 2026
7b087fd
test(run-engine): CK-keyed SFQ/DRR/stride/CoDel disciplines
1stvamp Jul 23, 2026
5c7cd12
test(run-engine): CK driver over real dequeue Lua via ckIndex rescore
1stvamp Jul 23, 2026
b8d21d2
feat(run-engine): CK fairness bench, scenarios, results, findings
1stvamp Jul 23, 2026
b9a6557
test(run-engine): address CK review (real age scenarios, honesty)
1stvamp Jul 23, 2026
82c9590
docs(run-engine): reconcile fairness spike with the caps plan of record
1stvamp Jul 23, 2026
1afa147
test(run-engine): caps-vs-scheduling bench over the real CK Lua gates
1stvamp Jul 23, 2026
c59a159
test(run-engine): address caps-vs-scheduling review
1stvamp Jul 23, 2026
9b8440c
test(run-engine): cross-task total-cap bench (the total cap's real job)
1stvamp Jul 23, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 69 additions & 0 deletions docs/superpowers/plans/2026-07-23-fair-queueing-ck-spike.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# Per-concurrency-key fairness spike Implementation Plan

> **For agentic workers:** REQUIRED SUB-SKILL: superpowers:subagent-driven-development or executing-plans. Steps use checkbox syntax.

**Goal:** Rank baseline (age-order) vs SFQ/DRR/stride/CoDel on per-concurrency-key fairness by driving the real CK-dequeue Lua and controlling `ckIndex` scores.

**Architecture:** Enqueue runs across many concurrency keys under one base queue via the real `RunQueue`. For candidates, rewrite the `ckIndex` ZSET scores before each dequeue round so the unmodified `dequeueMessagesFromCkQueueTracked` Lua serves keys in the discipline's order; baseline leaves scores untouched (production). Reuse the base-queue spike's workload and metrics.

**Tech Stack:** TypeScript, vitest, `@internal/testcontainers`, `@internal/run-engine` (RunQueue, keyProducer), `@internal/redis`.

## Global Constraints

- All code under `internal-packages/run-engine/src/run-queue/fairness-spike-ck/`. Reuse `../fairness-spike/harness/{workload,metrics}.ts` and disciplines where they transfer. Throwaway; delete before merge.
- Fairness group = concurrency key. One org/project/env, one base queue, many CKs.
- No production Lua edits. The `ckIndex` rescore sweep is the only affordance; discipline state advances via an `onServiced(concurrencyKey)` hook.
- Determinism: seeded workload; logical clock owned by the driver.
- Verify: `cd internal-packages/run-engine && pnpm run test ./src/run-queue/fairness-spike-ck/<file> --run`.
- Commit with `but` on `chore/fair-queueing-ck-spike` (stacked on `chore/fair-queueing-spike`).

---

### Task 1: ckReader — read ckIndex members + head scores

**Files:** Create `fairness-spike-ck/ckReader.ts`; Test `fairness-spike-ck/tests/ckReader.test.ts`.

**Produces:** `type ActiveCk = { ckQueue: string; concurrencyKey: string; headScore: number }`; `class CkReader { constructor(redis, keys); readActiveCks(baseQueue): Promise<ActiveCk[]> }`. Reads `ZRANGE ckIndexKey WITHSCORES` for the base queue; member is the prefixless CK-queue name; `concurrencyKey` from `descriptorFromQueue(keyPrefix+member)`.

- [ ] Write `redisTest`: enqueue 2 runs with concurrencyKeys "ck1","ck2" under one base queue via real RunQueue; assert readActiveCks returns both with numeric headScores. First discover the exact ckIndex member format by dumping `ZRANGE ckIndexKey 0 -1` (grep enqueueMessageCkTracked Lua for the `ZADD ckIndexKey` member).
- [ ] Implement; run; commit.

### Task 2: ckRescorer — write discipline order into ckIndex

**Files:** Create `fairness-spike-ck/ckRescorer.ts`; Test `tests/ckRescorer.test.ts`.

**Produces:** `async function rescoreCkIndex(redis, keys, baseQueue, order: string[] /* ckQueues, highest priority first */, now: number)`. Assigns scores `now - (order.length - i)` so the highest-priority CK gets the smallest (oldest) score, all `<= now`, order-preserving. ZADD each member.

- [ ] Write `redisTest`: enqueue CKs, rescore with a chosen order, assert `ZRANGEBYSCORE ckIndexKey -inf now` returns that order.
- [ ] Implement; run; commit.

### Task 3: CK disciplines

**Files:** Create `fairness-spike-ck/disciplines.ts`; Test `tests/disciplines.test.ts`.

**Produces:** a `CkDiscipline` interface `{ name; order(active: ActiveCk[]): string[] /* ckQueues, best first */; onServiced(concurrencyKey): void; reset() }` with `Sfq`, `Drr`, `Stride` keyed by concurrency key, plus `Codel` wrapper and `Baseline` (order = by headScore asc, i.e. no rescore needed). Reuse the monotonic-floor SFQ/stride and DRR logic from the base-queue spike (import or copy the core, keyed by concurrencyKey).

- [ ] Unit tests mirroring the base-queue spike (under-served key first; 3:1 weight ratio if weights used; CoDel hoist/revert).
- [ ] Implement; run; commit.

### Task 4: ckDriver — enqueue, rescore, real dequeue, hold, ack

**Files:** Create `fairness-spike-ck/harness/ckDriver.ts`; Test `tests/ckDriver.smoke.test.ts`; fidelity test `tests/fidelity.test.ts`.

**Produces:** `runCkScenario(config): Promise<RunMetrics>` reusing `../fairness-spike/harness/metrics.ts`. Loop per instant: release holds (ack), enqueue arrivals (with concurrencyKey), for candidate: compute discipline order over active CKs and `rescoreCkIndex`; call `testDequeueFromMasterQueue`; record per-key events; `onServiced`; hold. Baseline skips the rescore.

- [ ] Fidelity test: baseline path per-key dequeue counts equal a direct `testDequeueFromMasterQueue`-only run (no rescore) — confirms the harness matches production age-order.
- [ ] Smoke: balanced CKs drain fully and no key starves under a fair discipline.
- [ ] Implement; run; commit.

### Task 5: scenarios + bench + FINDINGS

**Files:** Create `fairness-spike-ck/harness/ckScenarios.ts`, `ckFairnessSpike.bench.test.ts`, `FINDINGS.md`.

- [ ] Scenarios ckSkew / ckBalanced / ckTrickle, multi-seed (3), five selectors; write results JSON; print table.
- [ ] Run the matrix; sanity-check baseline starves under ckSkew and at least one candidate fixes it (or record if not).
- [ ] Write FINDINGS with proof/disproof per discipline at the CK grain and whether the base-queue ranking carried over. Commit.

## Self-Review

Covers the spec: ckReader (T1), rescorer (T2), disciplines incl. baseline (T3), driver + fidelity anchor (T4), scenarios/bench/findings (T5). Grain = concurrency key throughout. Reuses workload/metrics from the base-queue spike. The rescore affordance and onServiced seam are Global Constraints.
Loading
Loading