feat(monitor): appendfsync=always main-thread blocking advisory (valkey#3515) - #375
Conversation
|
@claude review |
|
@BugBot review |
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit 8f96986. Configure here.
KIvanow
left a comment
There was a problem hiding this comment.
one issue plus a correctness nit.
-
Dead escalation path for appendfsync=always. aof_delayed_fsync is only incremented in the everysec branch of flushAppendOnlyFile() - in always mode the fsync is inline and the counter never moves. So the delayedFsyncRisingStreak >= 1 escalation on the always path (config-hazard.ts:486) can't fire in the field, and the tests exercising it (escalates when aof_delayed_fsync is rising, and the service delayed:5→9 case) validate a scenario that only exists with synthetic input - which reads as coverage we don't actually have. Please drop the delayed-fsync signal from the always branch (keep it for everysec, where it's the correct signal); real always escalation already comes from the aof-fsync-always LATENCY event and aof_last_write_status, which stay.
-
While you're in there - LATENCY freshness compares two clocks. Date.now() is the monitor host; spikeAtSeconds is the monitored server's time(NULL). Skew makes the 300s window wrong both ways (stale spikes read fresh, fresh ones suppressed), undercutting the freshness fix from the second commit. Anchor "now" to the server (TIME / INFO uptime) or track deltas across probes.
…ey#3515) - New config-hazard evaluator: appendfsync=always with AOF on raises a low-severity advisory on config alone, escalating to a warning hazard when symptoms confirm blocking (aof_delayed_fsync rising across probes, aof-fsync-always/aof-write LATENCY events, or a failing aof_last_write_status) - everysec is flagged only when aof_delayed_fsync climbs on two consecutive probes (the background fsync backing up), never on config - Service probes appendfsync + INFO persistence + LATENCY LATEST on the existing TTL-cached path; symptom probe failures degrade to the config-only advisory instead of suppressing it - Dashboard banner gains an advisory presentation (info icon, muted) alongside the existing hazard/unverified states
LATENCY LATEST entries persist until LATENCY RESET, so a single past aof-fsync-always/aof-write spike would escalate the advisory to a hazard forever. Filter entries by their spike timestamp (5-minute freshness window) so escalation mirrors the fresh-rise discipline of the aof_delayed_fsync path.
…nc=always - Remove aof_delayed_fsync from the always-branch symptoms: the engine only increments it in the everysec branch of flushAppendOnlyFile(), so the escalation could never fire in the field - Anchor LATENCY spike freshness to the monitored server's clock via TIME instead of the monitor host's Date.now(), which made the 300s window wrong in both directions under skew - Replace the tests covering the dead path with negative assertions, and add skew coverage in both directions
8f96986 to
69d941d
Compare
|
Both fixed. 1. Dead escalation path — you're right, 2. Clock skew —
|
Summary
Adds the AOF fsync-policy advisory from valkey-io/valkey#3515 to the config-hazard subsystem (the sibling of #337's valkey#3983 hazard): with
appendfsync always, every write fsyncs synchronously on the main thread, so disk latency becomes command latency. The broader upstream AOF-modernization work (WAL headers, io_uring, direct I/O) is unshipped and not pollable — the misconfiguration and its symptom are observable today.Detection (per the issue's guardrails)
appendonly=no→ no-op (managed/ephemeral instances with AOF intentionally off never fire).appendfsync=alwayswith no symptoms → low-severity advisory (severity: info,status: advisory): the config is a latency risk, considereverysecunless per-write durability is a hard requirement.aof_delayed_fsyncrising across probes,aof-fsync-always/aof-writeLATENCY events, oraof_last_write_status != ok.appendfsync=everysecstays quiet unlessaof_delayed_fsyncclimbs on two consecutive probes (the once-per-second background fsync itself backing up).Changes
evaluateAppendfsyncHazardpure evaluator inconfig-hazard.ts;ConfigHazardFindingwidened (new ids,infoseverity,advisorystatus).ConfigHazardServiceprobesappendfsync, INFO persistence, and LATENCY LATEST on the existing TTL-cached path, tracking a per-connection rising streak foraof_delayed_fsync. Symptom probe failures degrade to config-only evaluation instead of suppressing the advisory.ConfigHazardBannergains an advisory presentation (info icon, muted border) alongside hazard/unverified.Test plan
tsc --noEmitclean for api and web.Closes #368
Note
Medium Risk
Adds read-only Redis probes on the health-polling path with nuanced escalation logic; failures degrade safely but incorrect LATENCY freshness or streak logic could cause false positives/negatives.
Overview
Extends the config-hazard monitor with appendfsync detection (valkey#3515): when AOF is on,
appendfsync=alwayssurfaces as a low-severity advisory unless freshaof-fsync-always/aof-writeLATENCY spikes or badaof_last_write_statusescalate to a hazard;everysecstays silent untilaof_delayed_fsyncrises on two consecutive TTL probes.ConfigHazardServicenow aggregates ACL and appendfsync findings, probesCONFIG GET appendfsync, INFO persistence,LATENCY LATEST(300s freshness using serverTIMEto avoid clock skew), and tracks per-connection delayed-fsync streaks. Symptom probe failures fall back to config-only advisory evaluation.Shared
ConfigHazardFindingtypes gain new ids,infoseverity, andadvisorystatus. The dashboard ConfigHazardBanner shows all active findings with status-specific presentation (including the new advisory style) instead of hiding advisories.Reviewed by Cursor Bugbot for commit 69d941d. Bugbot is set up for automated code reviews on this repo. Configure here.