Skip to content

fix(test): dedupe and serialize chunked batch-rerun dispatch#9

Open
crypticsaiyan wants to merge 1 commit into
TestSprite:mainfrom
crypticsaiyan:fix/batch-rerun-closure-dedup
Open

fix(test): dedupe and serialize chunked batch-rerun dispatch#9
crypticsaiyan wants to merge 1 commit into
TestSprite:mainfrom
crypticsaiyan:fix/batch-rerun-closure-dedup

Conversation

@crypticsaiyan

Copy link
Copy Markdown

Summary

Previously, running test rerun --all would split requests into chunks of 50 tests and dispatch all chunks concurrently using Promise.all. However, the backend's producer/teardown deduplication logic operates within a single request, not across concurrent requests. If two tests in different chunks shared a project's producer or teardown, the backend would independently decide "not yet triggered" for both, causing the shared dependency to execute multiple times.

Note: This concurrent dispatch bug applied to both the initial batch dispatch and the deferred-retry loop.

The Fix

Implemented sequential chunk dispatch and a client-side deduplication defense layer to prevent double-execution:

  • Sequential Dispatch: Replaced Promise.all with sequential execution (one await per chunk). By the time chunk N is sent, chunk N-1 has already landed server-side, allowing the backend to correctly deduplicate shared dependencies against the previous chunk.
  • Client-Side Defense: Added dedupeBatchRerunAccepted to drop duplicate testId entries from the aggregated accepted list, and mergeBatchRerunClosureByProject to safely merge closure.byProject entries without double-counting. The CLI now emits a warning to stderr if it detects and filters out a duplicate trigger.
  • Fixture Update: Fixed a pre-existing test fixture (D3: batch rerun summary...) that was artificially relying on the old double-counting bug.

Testing & Validation

Regression Test: Added new test cases in src/commands/test.rerun.spec.ts to verify serialization and deduplication.

  • Concurrency limit: Simulated timed mock responses to prove that chunks are strictly dispatched sequentially (concurrency never exceeds 1).
  • Client deduplication: Simulated a backend incorrectly accepting a shared producer across two chunks to assert that the CLI successfully deduplicates the entry and emits a stderr warning.

CI Gates: All local checks pass.

  • npm run lint & npm run format:check
  • npm run typecheck
  • npm test (1449 tests passing)
  • npm run test:coverage (≥80% threshold met; actual ~87%)

Files Changed:

  • src/commands/test.ts
  • src/commands/test.rerun.spec.ts

Batch-rerun chunks (>50 testIds) were dispatched concurrently via
Promise.all. The backend's producer/teardown closure dedup happens
per-request, not across requests, so two concurrent chunks sharing a
project's producer could each independently decide to trigger it,
double-running the producer or teardown.

Dispatch chunks sequentially in both the initial and deferred-retry
paths, closing the race at the source. Also dedupe the aggregated
accepted[] by testId and merge closure.byProject across chunks as a
defensive second layer, warning on stderr if a duplicate trigger is
detected.

Fixed a pre-existing test whose fixture relied on the old
double-counting behavior (same accepted entry returned from every
retry call).
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.

1 participant