mirror of
https://github.com/MacRimi/ProxMenux.git
synced 2026-04-17 17:42:19 +00:00
Update notification service
This commit is contained in:
@@ -578,14 +578,19 @@ class TaskWatcher:
|
||||
# ── Cross-source dedup: yield to PVE webhook for backup/replication ──
|
||||
# The webhook delivers richer data (full logs, sizes, durations).
|
||||
# If the webhook already delivered this event within 120s, skip.
|
||||
# For backup events, PVE sends ONE webhook for the entire vzdump job
|
||||
# (covering all VMs), while TaskWatcher sees individual per-VM tasks.
|
||||
# So we check by event_type ONLY (no VMID) -- if ANY backup_complete
|
||||
# arrived from webhook recently, skip ALL backup_complete from tasks.
|
||||
_WEBHOOK_TYPES = {'backup_complete', 'backup_fail', 'backup_start',
|
||||
'replication_complete', 'replication_fail'}
|
||||
if event_type in _WEBHOOK_TYPES and self._webhook_delivered:
|
||||
import time as _time
|
||||
dedup_key = f"{event_type}:{vmid}"
|
||||
last_webhook = self._webhook_delivered.get(dedup_key, 0)
|
||||
if _time.time() - last_webhook < 120:
|
||||
return # Webhook already delivered this with richer data
|
||||
# Check type-only key first (covers multi-VM jobs)
|
||||
type_key = f"{event_type}:"
|
||||
for dkey, dtime in self._webhook_delivered.items():
|
||||
if dkey.startswith(type_key) and (_time.time() - dtime) < 120:
|
||||
return # Webhook already delivered this with richer data
|
||||
|
||||
self._queue.put(NotificationEvent(
|
||||
event_type, severity, data, source='tasks',
|
||||
@@ -1025,17 +1030,16 @@ class ProxmoxHookWatcher:
|
||||
data['duration'] = dur_m.group(1).strip()
|
||||
|
||||
# Record this event for cross-source dedup.
|
||||
# TaskWatcher checks this dict before emitting backup/replication
|
||||
# events so it yields to the richer webhook data.
|
||||
# TaskWatcher iterates this dict checking if any key with the same
|
||||
# event_type prefix was delivered recently (within 120s).
|
||||
import time
|
||||
if not hasattr(self, '_delivered'):
|
||||
self._delivered = {}
|
||||
dedup_key = f"{event_type}:{entity_id}"
|
||||
self._delivered[dedup_key] = time.time()
|
||||
# Cleanup old entries
|
||||
self._delivered[f"{event_type}:{entity_id}"] = time.time()
|
||||
# Cleanup old entries (use del, NOT reassign -- TaskWatcher holds a ref)
|
||||
if len(self._delivered) > 200:
|
||||
cutoff = time.time() - 300
|
||||
self._delivered = {k: v for k, v in self._delivered.items() if v > cutoff}
|
||||
stale = [k for k, v in self._delivered.items() if v < cutoff]
|
||||
for k in stale:
|
||||
del self._delivered[k]
|
||||
|
||||
event = NotificationEvent(
|
||||
event_type=event_type,
|
||||
|
||||
@@ -653,6 +653,14 @@ class NotificationManager:
|
||||
if event.severity == 'CRITICAL' and cooldown_str is None:
|
||||
cooldown = 60
|
||||
|
||||
# Backup/replication events: each execution is unique and should
|
||||
# always be delivered. A 10s cooldown prevents exact duplicates
|
||||
# (webhook + tasks) but allows repeated backup jobs to report.
|
||||
_ALWAYS_DELIVER = {'backup_complete', 'backup_fail', 'backup_start',
|
||||
'replication_complete', 'replication_fail'}
|
||||
if event.event_type in _ALWAYS_DELIVER and cooldown_str is None:
|
||||
cooldown = 10
|
||||
|
||||
# Check against last sent time using stable fingerprint
|
||||
last_sent = self._cooldowns.get(event.fingerprint, 0)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user