fix: WAL replay hang when flush doesn't progress - #21176
Conversation
|
Claude finished @DylanGuedes's task in 3m 41s —— View job Code Review
The fix is well-reasoned and correctly addresses the hang. The
|
|
Claude finished @DylanGuedes's task in 3m 41s —— View job Code Review
The fix is well-reasoned and correctly addresses the hang. The
|
What this PR does / why we need it:
During WAL replay, the ingester uses a backpressure loop to throttle recovery when in-memory bytes exceed 90% of
ReplayMemoryCeiling. If the flush never reduces memory — because the storage backend is slow, unavailable, or chunks haven't been marked as flushed yet — the loop had no exit condition and would spin forever. This caused ingester pods to hang at startup with no error logged and no corruption detected; the only visible signal wasloki_ingester_wal_replay_activeremaining stuck at 1.replay_controller.go—WithBackPressureReplayMemoryCeiling == 0: previously, a zero ceiling computed a threshold of 0, causing the loop to fire immediately on any non-zero byte count. Now backpressure is skipped entirely when the ceiling is unset.WAL replay flush made no progress: 4.0 GB in use, ceiling 3.6 GB; cannot recoverUsing
totalSubtractedrather than a before/after comparison ofcurrentBytesavoids a false positive: replay runsGOMAXPROCSworkers concurrently, and other workers can legitimately callAdd()while a flush is in progress, pushingcurrentBytesback above the pre-flush snapshot even when the flush genuinely freed memory.Four new test cases:
TestReplayControllerZeroCeiling— verifies backpressure is bypassed and the flusher is never called when ReplayMemoryCeiling is zeroTestReplayControllerNoProgressFlush— verifies an error is returned when the flusher is a complete no-opTestReplayControllerPartialProgressFlush— verifies an error is returned when the flusher makes partial progress on the first call but stalls on subsequent calls, which is the realistic scenario when a degraded backend drains some chunks but cannot keep upTestReplayControllerNoSpuriousErrorOnConcurrentAdd— verifies that a concurrentAdd()racing with a genuine flush does not cause a false no-progress errorWhich issue(s) this PR fixes:
Fixes #
Special notes for your reviewer:
Checklist
CONTRIBUTING.mdguide (required)featPRs are unlikely to be accepted unless a case can be made for the feature actually being a bug fix to existing behavior.docs/sources/setup/upgrade/_index.mddeprecated-config.yamlanddeleted-config.yamlfiles respectively in thetools/deprecated-config-checkerdirectory. Example PR