improve(gasless): isolate each record in restructureGaslessDeposits - #3747
Open
droplet-rl wants to merge 1 commit into
Open
improve(gasless): isolate each record in restructureGaslessDeposits#3747droplet-rl wants to merge 1 commit into
droplet-rl wants to merge 1 commit into
Conversation
restructureGaslessDeposits() maps the whole API response in a single flatMap, so one record that won't restructure -- an unparseable depositId, an unexpected witness shape -- rejects the entire query. The API re-supplies every pending record on the next poll, so a single malformed record starves every healthy message indefinitely. Extract the per-record work and isolate it: a record that throws is logged and skipped, the rest are returned. The body moves unchanged, so most of this diff is the reindent. Co-Authored-By: Claude <noreply@anthropic.com>
droplet-rl
requested review from
bmzig,
dijanin-brat,
mrice32,
nicholaspai and
pxrl
as code owners
August 25, 2026 12:16
droplet-rl
added a commit
that referenced
this pull request
Aug 25, 2026
evaluateApiSignatures() has no per-message error boundary, so one bad message takes down the whole poll. The API re-supplies it next tick, so it does so once per tick indefinitely. Add the boundary, and split the two failure classes it catches, because they want opposite handling: Malformed -- a derivation from the message payload throws. Deterministic, so the message is dropped permanently and logged once per requestId. _isProcessable() checks these at ingestion in _queryGaslessApi(), which is also the only boundary initialize()'s observation pass gets: a message whose inputToken won't parse used to fail every restart before any healthy sibling was reached. Operational -- an RPC or submission failure inside the state machine. Never dropped; an outage hits every message at once, so treating one as unprocessable would exclude healthy deposits with it. The message is deferred: the fill lock is handed back, or later deposits from the same depositor strand on an owner that is gone, and the state rewinds to unclaimed only while nothing can be on chain yet. Past DEPOSIT_SUBMIT it stays put, since re-running from INITIAL could submit the deposit twice. restructureGaslessDeposits() needed the same isolation one level lower; that is #3747, submitted separately. Co-Authored-By: Claude <noreply@anthropic.com>
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.
Split out of #3745 to keep that PR reviewable.
restructureGaslessDeposits()maps the whole API response in oneflatMap, so a single record that won't restructure (unparseabledepositId, unexpected witness shape) rejects the entire query. The API re-supplies every pending record next poll, so one malformed record starves every healthy message indefinitely — before any per-message guard downstream can run.Extracts the per-record work and isolates it: a record that throws is logged and skipped, the rest are returned. The body moves unchanged, so most of the diff is the reindent.
🤖 Generated with Claude Code