Skip to content

fix: ClusterBackup watchdog + heartbeat; backup-restore doc + power-loss drill#57

Merged
emrebulutlar merged 1 commit into
mainfrom
fix/cluster-backup-watchdog
Jul 4, 2026
Merged

fix: ClusterBackup watchdog + heartbeat; backup-restore doc + power-loss drill#57
emrebulutlar merged 1 commit into
mainfrom
fix/cluster-backup-watchdog

Conversation

@emrebulutlar

Copy link
Copy Markdown
Member

Closes #36 (P1.3, v0.3.0-beta). Companion PR in admin-gateway (env fix + freshness surfacing) — merge both; the admin-gateway one carries the actual unwedge.

See the commit message for the full root-cause chain. Highlights:

  • Live-diagnosed the silent stall: missing CLUSTER_ADDRESSES → single consensus endpoint → SourceType.LEADER exclusion → infinite nextCursor() loop (agent wedged mid-call, ~90% of a core, zero errors/logs, mark-file activity frozen, consensus subscription unbound by client timeout). Aeron 1.51 single-endpoint edge case; our config was the trigger.
  • Watchdog: response-side progress tracking, BACKUP_STALL_EXIT_SEC (300s) → halt(3) → PM restart under the crash-loop cap. Heartbeat JSON every 5s for admin freshness reporting.
  • docs/backup-restore.md (architecture, RPO ≈ live-log lag bounded by 60s query interval, restore procedures) + tools/durability/backup_restore_drill.sh (build(deps-dev): bump org.apache.maven.plugins:maven-surefire-plugin from 3.2.5 to 3.5.6 #9 exit criterion; destructive, ack-flag-gated, NOT yet run).
  • Live-verified: first successful backup cycle since Jul 2; snapshots retrieved, live log tracking, backup-info fresh:true.

🤖 Generated with Claude Code

…oss drill (match#36, admin-gateway#9)

Root cause of the silent stall (live-diagnosed): the PM launched
ClusterBackupApp with no environment, so CLUSTER_ADDRESSES defaulted to
"localhost" = ONE consensus endpoint (node0's member-facing port). With
SourceType.LEADER, the moment the leader was any node but 0, the agent
excluded its only endpoint and wedged in PublicationGroup.nextCursor()'s
do-while forever: no duty cycle -> no client keepalives -> its own driver
timed the client out and unbound the consensus-response subscription; no
errors, no stall events, mark-file activity frozen, one core burned at
~90% for days while the process looked "running". (Companion env fix in
admin-gateway; the single-endpoint+exclusion infinite loop is an Aeron
1.51 edge case worth reporting upstream.) Separately, the local archive
conductor died under storm load (ConductorServiceTimeoutException,
service interval 25s > 10s) with the same silent outcome.

Defenses added here:
- backup-watchdog thread: tracks RESPONSE-side listener callbacks only
  (backup response, recording-log update, live-log advance — query sends
  don't count, a wedged agent still sends). No progress for
  BACKUP_STALL_EXIT_SEC (default 300s, env-overridable) -> loud FATAL +
  Runtime.halt(3) so the PM restarts the whole stack fresh, bounded by
  the PM crash-loop cap. halt, not exit: shutdown hooks can block on the
  same wedged agents.
- heartbeat backup-progress.json written atomically every 5s next to the
  backup data (pid, last query/response/live-log ms, live-log position,
  snapshots retrieved, stall count, OK/STALLED) — consumed by the admin
  gateway's backup-info/status freshness reporting.
- listener now logs backup responses + recording-log updates (~1/min).
- docs/backup-restore.md: architecture, RPO/RTO, freshness monitoring,
  single-node + full-cluster restore procedures.
- tools/durability/backup_restore_drill.sh: scripted power-loss drill
  (kill -9 all, wipe /dev/shm, restore every node from disk, verify
  consensus); gated behind an explicit acknowledgement flag.

Live-verified with the admin-gateway env fix: first successful backup
cycle since Jul 2 — response from leader (member 1), 2 snapshots
retrieved, recording.log populated, live-log position advancing,
heartbeat state OK, backup-info fresh:true.

Closes #36

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@emrebulutlar
emrebulutlar merged commit ac56a66 into main Jul 4, 2026
2 checks passed
@emrebulutlar
emrebulutlar deleted the fix/cluster-backup-watchdog branch July 4, 2026 03:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[P1.3] ClusterBackup node stalls silently with empty state dir ("progress has stalled")

1 participant