OUT-4099 + OUT-4100: Assembly 429 backpressure + per-direction fan-out with per-portal fairness - #141
Merged
Conversation
Assembly returns no retry-after header and recovers in ~1s. Previously a 429 fell through to blind exponential backoff and escalated to the 2-5 min task-level retry, parking files. Now a Copilot 429 waits ~1s (only before an actual retry, not the final give-up) and the Copilot path retries up to 6 times so a burst self-corrects inside withRetry. Dropbox callers keep their existing 3-retry behaviour via a new configurable `retries` option. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Replace the per-page batchTriggerAndWait convoy with accumulate-then-fan-out: each direction lists all pages first, then dispatches files in chunks (BATCH_CHUNK_SIZE, within Trigger.dev's 500-item batch limit). Chunks are awaited sequentially since Trigger.dev forbids parallel waits. Each file run is keyed by concurrencyKey=portalId so one busy portal can no longer starve others. The A->D-before-D->A ordering barrier is preserved (each direction awaits its own fan-out) and the channel is marked synced only after it. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Greptile SummaryThe PR improves rate-limit recovery for Assembly operations and replaces page-level synchronization batches with sequential, portal-keyed fan-out.
Confidence Score: 5/5The PR appears safe to merge. No blocking failure remains. Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[Assembly-to-Dropbox listing] --> B[Collect all valid pages]
B --> C[Portal-keyed sequential fan-out]
C --> D[Dropbox-to-Assembly listing]
D --> E[Collect all valid pages]
E --> F[Portal-keyed sequential fan-out]
F --> G[Persist cursor and completed state]
B -->|listing failure| H[Dispatch discovered work]
D -->|listing failure| H
H --> I[Fail without advancing state]
Reviews (3): Last reviewed commit: "fix(OUT-4100): don't advance sync state ..." | Re-trigger Greptile |
…ge options - initiate* now wrap pagination in try/catch: if a later page fails, files already discovered are still fanned out, then the error is rethrown so the channel isn't marked synced and the cursor isn't advanced on an incomplete listing (a later run re-lists from root; mapping-based filtering dedupes). - fanOutAndWait merges concurrencyKey into existing item options instead of replacing them, so future scheduling options aren't silently dropped. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Collaborator
Author
|
@greptileai review again |
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Collaborator
Author
|
@greptileai review again |
priosshrsth
approved these changes
Aug 26, 2026
SandipBajracharya
changed the base branch from
main
to
feature/performance-improvements
August 26, 2026 08:59
SandipBajracharya
merged commit Aug 26, 2026
384d03c
into
feature/performance-improvements
11 checks passed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Implements two throughput improvements from the Performance & Reliability Improvements milestone.
OUT-4099 — Recover quickly from Assembly rate-limit errors
Assembly returns no
retry-afterheader and recovers in ~1s, but a 429 previously fell through to blind exponential backoff and escalated to the 2–5 min task-level retry, parking files.withRetry.withRetrygains a configurableretriesoption; Dropbox callers keep their existing 3-retry behaviour (no blanket change).OUT-4100 — Fan out files per direction, keyed per portal
Replaces the per-page
batchTriggerAndWaitconvoy.BATCH_CHUNK_SIZE = 150, within Trigger.dev's 500-item batch limit).Promise.allaround wait functions throws).concurrencyKey = portalId, so one busy portal can no longer starve others in the shared 25-slot pool.Testing
withRetry.test.ts(429 wait, no-wait-on-final-attempt, Dropbox-429 gating, configurable retries) andfanOut.test.ts(chunking, per-item concurrencyKey, empty short-circuit, and a guard that batches never wait in parallel — proven to fail if reverted toPromise.all).pnpm typecheckandpnpm lintclean.Known trade-offs / follow-ups (not in this PR)
BATCH_CHUNK_SIZE = 150, heavy channels (>150 files) still have a between-batch convoy (~same granularity asmain's per-page). A two-level batch fan-out would remove it — noted as a possible follow-up if heavy channels prove common.Validation still needed
The integration harness can't model Trigger.dev's queue concurrency, batch limits, or the parallel-wait guard (inline SDK double). A heavy-file channel run against a real Trigger.dev instance is needed to confirm
BATCH_CHUNK_SIZEis safe and to measure real throughput (see the manual load-testing plan).🤖 Generated with Claude Code