fix: clear flap state when a host is dropped

flap._state persists at module level keyed by (host, service) and only
clears via a RECOVER-triggered quiet window. A host dropped mid-flap with
no RECOVER ever received leaves ok_since permanently None, so the
flapping flag could never clear on its own.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-07 08:35:10 -04:00
co-authored by Claude Sonnet 5
parent 136b10239f
commit a7b698e6b9
3 changed files with 33 additions and 0 deletions
+11
View File
@@ -100,6 +100,17 @@ def observe(host: str, service: str, level: str) -> str:
return SUPPRESS
def clear_host(host: str) -> None:
"""Discard all flap state for *host* (called when a host is dropped).
A dropped host may be mid-flap with no RECOVER ever received, in which
case ``ok_since`` stays ``None`` and ``_sweep`` can never clear it on its
own — the state would otherwise persist forever.
"""
for key in [k for k in _state if k[0] == host]:
del _state[key]
def flapping_services(host: str) -> list:
"""Return the services of *host* that are currently flapping.
+2
View File
@@ -14,6 +14,7 @@ import logging
from aiohttp import web
import jinja2
from . import data
from . import flap as flap_mod
from . import notify as notify_mod
from . import settings as settings_mod
from . import users as users_mod
@@ -439,6 +440,7 @@ async def start(
return web.json_response({"error": "Forbidden"}, status=403)
eventlog(uname, "INFO", "dropped")
del hbdclass.Host.hosts[uname]
flap_mod.clear_host(uname)
return web.Response(text="Done")
async def register(request):