Repository navigation
feat(replication): warn-level visibility for parked/declined blob sends - #591
Merged
Merged
Conversation
sendBlobs() had two silent failure paths that only logged at debug (production runs at warn): a send parked on the outstanding-sends concurrency cap, and a send declined outright (socket closed, or a shutdown drain in progress). Both are now throttled logger.warn lines with fileId/database/node/reason, so a starved or declined blob send is diagnosable from default logs without needing a debug-level reproduction. - New blobSendWarnThrottle.ts: pure, testable throttle/aggregate helpers (same pattern as the existing blob-send-error suppression), reused across three independent buckets (park, unpark, decline) so a burst under one cause can't drown the others. - Park threshold is configurable via HARPER_BLOB_SEND_PARK_WARN_MS (default 5000ms), matching blobSendDrain.ts's HARPER_BLOB_SEND_* env pattern. - No changes to the per-chunk hot path or send behavior — only timers/warns on the already-slow park/decline paths. Co-Authored-By: Claude Sonnet <noreply@anthropic.com>
Contributor
|
Reviewed; no blockers found. |
There was a problem hiding this comment.
Code Review
This pull request introduces a throttled-warning mechanism for blob-send operations to improve observability of starvation and decline scenarios. It adds a new utility for managing throttle states and integrates it into the replication connection logic to log warnings when sends are parked on concurrency caps or declined during shutdown. The reviewer identified an issue with the environment variable parsing for PARK_WARN_MS, where setting the value to 0 incorrectly falls back to the default of 5000 due to falsy evaluation, and provided a robust fix.
Co-Authored-By: Codex <noreply@openai.com>
Contributor
Patch cherry-pick: mergedCherry-picked onto |
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.
Summary
sendBlobs()inreplication/replicationConnection.tshad two silent paths that only logged atdebug(production runs atwarn):MAX_OUTSTANDING_BLOBS_BEING_SENT) — invisible if a stuck predecessor send saturates the cap and starves successors.Both are now throttled
logger.warnlines withfileId,database,node, and reason, so a starved/declined blob send is diagnosable from default logs.Motivation
Live incident (internal demo.reflex cluster, 5.1.19): a deploy's 26.7MB blob payload never went out to the peer for 60+ seconds while the connection was healthy and no drain was active; the peer's 20s
blobReadTimeoutfailed the deploy. Every plausible cause (parked on the cap, silent decline, starvation) only logged at debug, so post-hoc diagnosis was impossible. The trigger is rare and unreproducible, so the next occurrence needs to self-diagnose from default logs.What changed
replication/blobSendWarnThrottle.ts: pure, testable throttle/aggregate helpers, following the same throttled-suppression pattern already used for blob send errors (blobSendErrorsSuppressed/lastBlobSendErrorLoga few lines below). Three independent throttle buckets (park, unpark, decline) so a burst under one cause can't drown out the others.sendBlobs():PARK_WARN_MS-delay timer (default 5000ms, envHARPER_BLOB_SEND_PARK_WARN_MS, matchingblobSendDrain.ts'sHARPER_BLOB_SEND_*pattern) the moment a send is about to park on the cap. It only fires — and only warns — if the send is still parked once the threshold elapses; a send that acquires a slot quickly never logs anything.wsClosedpre-queue,isDrainingBlobSends()pre-queue,isDrainingBlobSends()post-queue) from silent/debug to a throttled warn stating the blob will rely on peer re-request.unitTests/replication/blobSendWarnThrottle.test.mjs), matchingblobSendDrain.test.mjs's pure-function testing style.No changes to the per-chunk hot path (
noteBlobSendProgressuntouched) or to send behavior/control-flow — only timers and warn calls on the already-slow park/decline paths.Where to look
replication/replicationConnection.ts— thesendBlobs()diff (searchparkWarn/declineWarn) is the load-bearing change; the rest of the function is untouched.replication/blobSendWarnThrottle.ts— the throttle logic itself.Notes for the reviewer
main/5.2 for now to keep patch complexity down; its 5.1 fate gets decided after diagnosis.🤖 Generated with Claude Code