fix(server): restore keeps connectivity alert for connections dropped to unknown

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Uc9V1v7iXruubpoLiSE24M
This commit is contained in:
2026-09-21 09:34:38 -04:00
co-authored by Claude Sonnet 5
parent c3736f47ee
commit 3970f4cdde
2 changed files with 51 additions and 1 deletions
+5 -1
View File
@@ -351,6 +351,7 @@ def restore_connection_timers(hbdclass, ctx):
restored += 1
elif state == hbdclass.Connection.OVERDUE:
host_overdue = host.status() == "overdue"
elapsed_overdue = now - conn.statetime
remaining = DROPOVERDUE - elapsed_overdue
if remaining <= 1:
@@ -360,6 +361,9 @@ def restore_connection_timers(hbdclass, ctx):
"Marking %s/%s UNKNOWN (overdue %.1f days)",
uname, afam, elapsed_overdue / 86400,
)
# A connection dropped to UNKNOWN keeps its alert, like the
# UNKNOWN branch above and on_unknown do.
host_overdue = True
else:
conn.reset_overdue_timer(remaining, on_unknown)
logger.debug(
@@ -369,7 +373,7 @@ def restore_connection_timers(hbdclass, ctx):
# Ensure the connectivity alert is set — it may be missing if
# hbd was shut down before the on_overdue callback had a chance
# to record it.
if host.status() == "overdue":
if host_overdue:
_set_connectivity_alert(host, afam, "CRITICAL")
restored += 1
+46
View File
@@ -171,3 +171,49 @@ def test_restore_skips_absent_and_sets_no_alert_for_simplex():
c.cancel_overdue_timer()
asyncio.run(scenario())
def _past_drop(conn):
conn.state, conn.statetime = C.OVERDUE, time.time() - (udp.DROPOVERDUE + 10)
def test_restore_past_drop_window_keeps_alert_single_family():
ctx = _ctx()
async def scenario():
_fresh("pres-drop-single")
_send("pres-drop-single", "127.0.0.1", ctx)
h = hbdclass.Host.hosts["pres-drop-single"]
_past_drop(h.connections["IPv4"])
udp.restore_connection_timers(hbdclass, ctx)
assert h.connections["IPv4"].state == C.UNKNOWN
assert "connectivity.IPv4" in h.alert_states
asyncio.run(scenario())
def test_restore_past_drop_window_keeps_alerts_dual_family():
ctx = _ctx()
async def scenario():
h = _dual_stack("pres-drop-dual", ctx)
for c in h.connections.values():
_past_drop(c)
udp.restore_connection_timers(hbdclass, ctx)
assert {"connectivity.IPv4", "connectivity.IPv6"} <= set(h.alert_states)
asyncio.run(scenario())
def test_v4_only_host_overdue_is_single_critical(monkeypatch):
events = _events(monkeypatch)
ctx = _ctx()
_fresh("pres-v4only")
_send("pres-v4only", "127.0.0.1", ctx)
h = hbdclass.Host.hosts["pres-v4only"]
on_overdue, _ = udp._make_timer_callbacks("pres-v4only", h, ctx)
asyncio.run(on_overdue(h.connections["IPv4"]))
assert [e for e in events if e[0] == "CRITICAL"] == [("CRITICAL", "IPv4 overdue")]
assert "connectivity.IPv4" in h.alert_states
asyncio.run(on_overdue(h.connections["IPv4"]))
assert len([e for e in events if e[0] == "CRITICAL"]) == 1