Skip to content

Add WolverineHeartbeat emission (CritterWatch#72)#2688

Merged
jeremydmiller merged 1 commit intomainfrom
feat/cw72-heartbeats
May 7, 2026
Merged

Add WolverineHeartbeat emission (CritterWatch#72)#2688
jeremydmiller merged 1 commit intomainfrom
feat/cw72-heartbeats

Conversation

@jeremydmiller
Copy link
Copy Markdown
Member

Summary

Ships the emit side of node-level heartbeats so external monitors (e.g. CritterWatch) can detect when a Wolverine node has gone dark. Operators opt in with one line and route heartbeats wherever they want via the normal publish pipeline.

opts.EnableHeartbeats(TimeSpan.FromSeconds(10));
opts.PublishMessage<WolverineHeartbeat>().ToRabbitExchange(\"monitoring\");

What shipped

  • HeartbeatPolicy on WolverineOptions.HeartbeatEnabled (default true) and Interval (default 30s).
  • WolverineHeartbeat record — ServiceName, NodeNumber, SentAt, Uptime.
  • HeartbeatBackgroundServiceBackgroundService that publishes on each interval tick using new MessageBus(runtime).PublishAsync(...). Bails out early when Enabled == false. Swallows-and-logs publish exceptions so a transport hiccup never crashes the host.
  • EnableHeartbeats(TimeSpan?) extension — wires the singleton + hosted service registration; supplied interval (when given) overrides the policy.
  • Docs page at docs/guide/runtime/heartbeats.md with a quickstart, field reference, and configuration notes; linked from the General nav.

What's out of scope

The consumption side — tracking received heartbeats per node, alerting on missing ones, and visualizing health — is intentionally CritterWatch's job and lives in that repo (CritterWatch#72).

Test coverage

Added src/Testing/CoreTests/Runtime/Heartbeat/HeartbeatBackgroundServiceTests.cs with five tests covering:

  • Repeated publishes at the configured interval (50ms cadence over ~250ms ⇒ ≥2 publishes).
  • Heartbeats carry ServiceName and NodeNumber from WolverineOptions/Durability.
  • No publishes happen when HeartbeatPolicy.Enabled == false.
  • EnableHeartbeats sets the policy and registers the hosted service in WolverineOptions.Services.
  • EnableHeartbeats() without an interval preserves the default 30-second cadence.

dotnet test src/Testing/CoreTests/CoreTests.csproj is green on net8.0, net9.0, and net10.0 (1538 / 1542 / 1542 tests, 0 failures).

Companion work

This pairs with CW#73 (active-pull node health checks) and CW#70 (transport health probes) for a coherent monitoring story: heartbeats are the cheap passive signal, the other two cover "alive but degraded" cases.

Test plan

  • dotnet build src/Wolverine/Wolverine.csproj — clean.
  • dotnet test src/Testing/CoreTests/CoreTests.csproj — passing on all three target frameworks.
  • Reviewer eyes on the publish-via-MessageBus approach and the placement of EnableHeartbeats (chose top-level WolverineOptionsExtensions.cs to match the plan; happy to relocate next to the heartbeat folder if preferred).

🤖 Generated with Claude Code

Periodic node liveness signal emitted via the normal publish pipeline.
Operators opt in with `opts.EnableHeartbeats(...)` and route heartbeats
to their monitoring stack (e.g. CritterWatch) with a publish rule.

- HeartbeatPolicy on WolverineOptions.Heartbeat (Enabled, Interval)
- WolverineHeartbeat record (ServiceName, NodeNumber, SentAt, Uptime)
- HeartbeatBackgroundService publishes on each interval tick
- EnableHeartbeats(TimeSpan?) extension wires the hosted service

The consumption side (tracking + alerting on missing heartbeats) lives
in CritterWatch and is intentionally out of scope here.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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.

1 participant