fix(agents-runtime): avoid stack overflow on large live batches - #4698
fix(agents-runtime): avoid stack overflow on large live batches#4698KyleAMathews wants to merge 3 commits into
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #4698 +/- ##
==========================================
- Coverage 60.20% 58.60% -1.60%
==========================================
Files 412 352 -60
Lines 44396 41030 -3366
Branches 12586 11970 -616
==========================================
- Hits 26727 24046 -2681
+ Misses 17587 16944 -643
+ Partials 82 40 -42
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Electric Agents Mobile BuildLocal mobile checks ran for commit The EAS Android preview build was skipped because the |
…into fix-streamdb-stack-overflow-pr # Conflicts: # .changeset/large-live-batches.md
Fixes large JSON StreamDB batches in the agents runtime/server by avoiding spread-based array appends and avoiding
StreamResponse.json()for server-side JSON reads. This preventsRangeError: Maximum call stack size exceededduring wake processing and manifest rehydration, with no intended behavior change.Root Cause
There were two variants of the same failure mode:
processWakeaccumulated live StreamDB change events with calls like:For sufficiently large live batches, spreading
changeEventspasses every event as a separate function argument topush. V8 has an argument/stack limit, so a large batch can throw before the runtime finishes processing the wake.StreamClient.readJsondelegated to@durable-streams/client'sStreamResponse.json(). That dependency currently flattens parsed JSON arrays internally with the same spread pattern, so large streams can also fail during server rehydration paths such as future-send/cron manifest loading:RangeError: Maximum call stack size exceeded at StreamResponseImpl.json (.../@durable-streams/client/dist/index.js:1904:11) at async StreamClient.readJson (.../packages/agents-server/src/stream-client.ts:407:12)Approach
For runtime live-batch accumulation, add a small
appendAllhelper that appends items with a loop instead of argument spreading:For server JSON reads, have
StreamClient.readJsonconsumeresponse.jsonStream()and collect items one-by-one instead of callingresponse.json():This keeps the fix local while avoiding the dependency's large-array spread path.
Key Invariants
Non-goals
@durable-streams/client; it avoids the problematic API at the agents-server call site.Trade-offs
The loop/streaming code is slightly more verbose than
push(...items)orresponse.json(), but it is safe for arbitrary batch sizes and avoids known large-array spread failure modes. A dependency-level fix would be broader, but this PR keeps the immediate agents runtime/server fix small and easy to review.Verification
Results:
Also ran:
That still fails on existing local workspace resolution/type issues around
@electric-sql/clientand related implicit-any errors, but the newstream-client.tstype error found during iteration was fixed.Files changed
packages/agents-runtime/src/process-wake.ts— replaces spread-based live-batch appends withappendAll.packages/agents-server/src/stream-client.ts— changesreadJsonto consumejsonStream()one item at a time instead ofresponse.json().packages/agents-server/test/stream-client.test.ts— adds a regression test ensuring large reads do not callStreamResponse.json()..changeset/large-live-batches.md— adds patch changesets for@electric-ax/agents-runtimeand@electric-ax/agents-server.