Skip to content

test: property-check write-queue serialization and clamp invariants#575

Merged
ndycode merged 2 commits into
mainfrom
claude/audit-56-write-queue-property
Jun 11, 2026
Merged

test: property-check write-queue serialization and clamp invariants#575
ndycode merged 2 commits into
mainfrom
claude/audit-56-write-queue-property

Conversation

@ndycode

@ndycode ndycode commented Jun 10, 2026

Copy link
Copy Markdown
Owner

Summary

Second property suite of this wave (sibling: #574; complements the example-based #567). The settings write queue is the per-path serialization primitive behind every settings write — its Windows-safety claim is precisely a concurrency invariant, which is the kind of thing the repo's test/property/ tradition exists to pin across the whole input space rather than at hand-picked points. This adds test/property/settings-write-queue.property.test.ts (2 fast-check properties).

Invariants pinned

  • Serialization under any schedule: for arbitrary schedules of up to 12 tasks spread over three path keys, with each task independently succeeding, failing once retryably (EBUSY) then succeeding, or failing fatally (ENOSPC):
    • every key's invocations form contiguous groups in submission order — a task's retries can never interleave with another task on the same path;
    • fatal tasks reject with their own error and never block successors on the same key;
    • every task runs at least once, on its own key.
      Each property iteration uses a unique key namespace so the module-level queue map never couples runs.
  • Retry-after clamping: any positive 429 retryAfterMs hint (up to 2×10⁹) produces exactly one sleep of max(10, min(30000, round(hint))) — used verbatim inside the range, clamped at the 10ms floor and the 30s ceiling outside it.

Validation

  • vitest run test/property/settings-write-queue.property.test.ts — 2/2 passing (default fast-check run counts)
  • npm run typecheck — clean
  • npx eslint test/property/settings-write-queue.property.test.ts --max-warnings=0 — clean

https://claude.ai/code/session_01XNtnkLbBiXZxfQQYLMpucB


Generated by Claude Code

note: greptile review for oc-chatgpt-multi-auth. cite files like lib/foo.ts:123. confirm regression tests + windows concurrency/token redaction coverage.

Greptile Summary

adds test/property/settings-write-queue.property.test.ts with two fast-check properties pinning the write-queue's concurrency and rate-limit invariants. both previously-flagged gaps — windows-relevant errno codes and retry-budget exhaustion — are addressed.

  • serialization property: covers all four task behaviors (ok, flaky, fatal, exhausted) and all five windows-relevant errno codes (EBUSY, EPERM, EACCES, EAGAIN, ENOTEMPTY); checks contiguous per-key grouping, correct outcomes, exhausted-task retry count, and "every task ran at least once on its own key."
  • clamp property: verifies that any positive 429 retryAfterMs hint (1..2×10⁹) produces exactly one sleep of max(10, min(30000, round(hint))); uses a unique key per iteration to avoid coupling runs through the module-level queue map.

Confidence Score: 5/5

test-only addition with no changes to production code; safe to merge

the new test file exercises all retryable windows errno codes, all four task behaviors including retry-budget exhaustion, per-key serialization contiguity, and the 429 clamp formula — the two previously flagged gaps are both addressed and the implementation logic is sound

no files require special attention

Important Files Changed

Filename Overview
test/property/settings-write-queue.property.test.ts adds two fast-check properties covering queue serialization (all 4 behaviors incl. exhausted, all 5 windows-relevant errno codes) and 429 clamp; logic is sound, minor nits around a magic retry-count and integer-only rounding coverage

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[fc.asyncProperty: arbSchedule] --> B[schedule.map: submit tasks]
    B --> C{spec.behavior}
    C -->|ok| D[return result-taskIndex]
    C -->|flaky| E{flakyFailed?}
    E -->|no| F[throw retryableCode\nadd to flakyFailed]
    E -->|yes| D
    C -->|fatal| G[throw ENOSPC\nnon-retryable]
    C -->|exhausted| H[throw retryableCode\nevery attempt]
    F -->|retry| E
    H -->|retry x4| I[budget exhausted\nthrow lastError]
    G --> J[reject immediately\ndon't block successors]
    D --> K[outcome: ok]
    I --> L[outcome: error]
    J --> L
    K --> M[Assert: contiguous groups\nper key in submission order]
    L --> M
    M --> N[Assert: exhausted tasks\ninvoked exactly SETTINGS_WRITE_MAX_ATTEMPTS times]
    N --> O[Assert: every task ran\nat least once on its own key]
Loading

Fix All in Codex

Prompt To Fix All With AI
Fix the following 3 code review issues. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 3
test/property/settings-write-queue.property.test.ts:3
the exhausted-invocation count is hardcoded to `4`, but the source exports `SETTINGS_WRITE_MAX_ATTEMPTS`. if that constant is bumped (e.g. to 5) the assertion silently checks the wrong number and could pass or fail incorrectly depending on the new value — import the constant so the check stays in sync automatically.

```suggestion
import { withQueuedRetry, SETTINGS_WRITE_MAX_ATTEMPTS } from "../../lib/codex-manager/settings-write-queue.js";
```

### Issue 2 of 3
test/property/settings-write-queue.property.test.ts:88-96
**magic retry-count decoupled from source constant** — the `4` here shadows `SETTINGS_WRITE_MAX_ATTEMPTS = 4` from the source module. if that constant is bumped to 5 the assertion would still check 4 and silently pass with a wrong expectation. import and use `SETTINGS_WRITE_MAX_ATTEMPTS` directly so the check stays tied to the real budget.

### Issue 3 of 3
test/property/settings-write-queue.property.test.ts:126
**rounding branch never exercised**`fc.integer` always produces whole numbers, so `Math.round(retryAfterMs)` is a no-op on every iteration and the rounding code in `resolveRetryDelayMs` is never actually tested. switching to `fc.float({ min: 1, max: 2_000_000_000, noNaN: true })` would exercise the round-up/round-down paths at the clamp boundaries (e.g. `29999.6` rounds to `30000`, `10.4` rounds to `10`).

Reviews (2): Last reviewed commit: "test: draw transient codes from the full..." | Re-trigger Greptile

fast-check properties over withQueuedRetry, complementing the
example-based suite:

- for ANY schedule of ok/flaky/fatal tasks across three keys, every
  key's invocations form contiguous groups in submission order
  (retries never interleave with another task), fatal tasks reject
  without blocking successors, and every task runs on its own key
- any positive 429 retry-after hint is clamped into the 10ms..30s
  range and used verbatim within it

https://claude.ai/code/session_01XNtnkLbBiXZxfQQYLMpucB
@chatgpt-codex-connector

Copy link
Copy Markdown

Codex usage limits have been reached for code reviews. Please check with the admins of this repo to increase the limits by adding credits.
Credits must be used to enable repository wide code reviews.

@coderabbitai

coderabbitai Bot commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

@ndycode, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 6 minutes and 40 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: db1d5ff7-473c-4ae1-943b-6d796ffabd34

📥 Commits

Reviewing files that changed from the base of the PR and between b566656 and 3e85766.

📒 Files selected for processing (1)
  • test/property/settings-write-queue.property.test.ts
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/audit-56-write-queue-property
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch claude/audit-56-write-queue-property

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Comment thread test/property/settings-write-queue.property.test.ts Outdated
Comment thread test/property/settings-write-queue.property.test.ts
…ustion

From review: flaky and the new exhausted behavior throw any of the
five retryable Windows codes (EPERM/EACCES dominate in practice, not
just EBUSY), and the exhausted variant pins that a task burning the
whole four-attempt budget rejects with the retryable error while its
key's successors still run.

https://claude.ai/code/session_01XNtnkLbBiXZxfQQYLMpucB
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants