Reduce departure latency from 30min worst-case to 6min

Watchdog timeout and departure debounce were both 900s — stacked,
worst-case VACANT alert was 30 minutes after leaving. With active ARP
scanning every 30s we can confirm absence quickly, so both timers drop
to 180s. Override via NET_ALERTER_WATCHDOG_TIMEOUT and
NET_ALERTER_DEPARTURE_DEBOUNCE env vars.
This commit is contained in:
Cobra
2026-04-15 14:50:19 -04:00
parent 44c8e87959
commit d8c742cea6
+7 -6
View File
@@ -83,7 +83,8 @@ _churn_tracker = {} # {mac: [timestamps of departure events]}
_churn_lock = threading.Lock()
CHURN_THRESHOLD = 3 # cycles in window before suppression
CHURN_WINDOW_SEC = 1800 # 30 minutes
WATCHDOG_TIMEOUT_SEC = int(os.getenv("NET_ALERTER_WATCHDOG_TIMEOUT", "900"))
WATCHDOG_TIMEOUT_SEC = int(os.getenv("NET_ALERTER_WATCHDOG_TIMEOUT", "180"))
DEPARTURE_DEBOUNCE_SEC = int(os.getenv("NET_ALERTER_DEPARTURE_DEBOUNCE", "180"))
# Mobile device OUI prefixes for personal device detection
MOBILE_DEVICE_OUIS = {
@@ -1142,8 +1143,8 @@ def on_arrival(mac: str, ip: str, hostname: str = "") -> None:
def on_departure(mac: str) -> None:
"""
Handle device departure with 15-minute debounce.
Only sends alert if device still gone after 15 min.
Handle device departure with debounce.
Only sends alert if device still gone after DEPARTURE_DEBOUNCE_SEC.
"""
with known_lock:
if mac not in known_devices:
@@ -1175,7 +1176,7 @@ def on_departure(mac: str) -> None:
known_devices[mac]['departing'] = True
known_devices[mac]['depart_initiated'] = time.time()
# Start 15-minute debounce timer
# Start departure debounce timer
# Extract timer to cancel outside of lock to avoid deadlock
timer_to_cancel = None
with departure_lock:
@@ -1211,13 +1212,13 @@ def on_departure(mac: str) -> None:
logging.info(msg)
send_alert(msg)
timer = threading.Timer(900.0, send_departure_alert) # 15 min = 900 sec
timer = threading.Timer(float(DEPARTURE_DEBOUNCE_SEC), send_departure_alert)
timer.daemon = True
timer.name = f'departure-debounce-{mac}'
departure_timers[mac] = timer
timer.start()
logging.debug(f"Departure debounce started for {mac}, will alert in 15 min if still gone")
logging.debug(f"Departure debounce started for {mac}, will alert in {DEPARTURE_DEBOUNCE_SEC}s if still gone")
def get_primary_interface() -> str: