mirror of
https://github.com/MacRimi/ProxMenux.git
synced 2026-04-29 19:06:37 +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 ──
|
# ── Cross-source dedup: yield to PVE webhook for backup/replication ──
|
||||||
# The webhook delivers richer data (full logs, sizes, durations).
|
# The webhook delivers richer data (full logs, sizes, durations).
|
||||||
# If the webhook already delivered this event within 120s, skip.
|
# 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',
|
_WEBHOOK_TYPES = {'backup_complete', 'backup_fail', 'backup_start',
|
||||||
'replication_complete', 'replication_fail'}
|
'replication_complete', 'replication_fail'}
|
||||||
if event_type in _WEBHOOK_TYPES and self._webhook_delivered:
|
if event_type in _WEBHOOK_TYPES and self._webhook_delivered:
|
||||||
import time as _time
|
import time as _time
|
||||||
dedup_key = f"{event_type}:{vmid}"
|
# Check type-only key first (covers multi-VM jobs)
|
||||||
last_webhook = self._webhook_delivered.get(dedup_key, 0)
|
type_key = f"{event_type}:"
|
||||||
if _time.time() - last_webhook < 120:
|
for dkey, dtime in self._webhook_delivered.items():
|
||||||
return # Webhook already delivered this with richer data
|
if dkey.startswith(type_key) and (_time.time() - dtime) < 120:
|
||||||
|
return # Webhook already delivered this with richer data
|
||||||
|
|
||||||
self._queue.put(NotificationEvent(
|
self._queue.put(NotificationEvent(
|
||||||
event_type, severity, data, source='tasks',
|
event_type, severity, data, source='tasks',
|
||||||
@@ -1025,17 +1030,16 @@ class ProxmoxHookWatcher:
|
|||||||
data['duration'] = dur_m.group(1).strip()
|
data['duration'] = dur_m.group(1).strip()
|
||||||
|
|
||||||
# Record this event for cross-source dedup.
|
# Record this event for cross-source dedup.
|
||||||
# TaskWatcher checks this dict before emitting backup/replication
|
# TaskWatcher iterates this dict checking if any key with the same
|
||||||
# events so it yields to the richer webhook data.
|
# event_type prefix was delivered recently (within 120s).
|
||||||
import time
|
import time
|
||||||
if not hasattr(self, '_delivered'):
|
self._delivered[f"{event_type}:{entity_id}"] = time.time()
|
||||||
self._delivered = {}
|
# Cleanup old entries (use del, NOT reassign -- TaskWatcher holds a ref)
|
||||||
dedup_key = f"{event_type}:{entity_id}"
|
|
||||||
self._delivered[dedup_key] = time.time()
|
|
||||||
# Cleanup old entries
|
|
||||||
if len(self._delivered) > 200:
|
if len(self._delivered) > 200:
|
||||||
cutoff = time.time() - 300
|
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 = NotificationEvent(
|
||||||
event_type=event_type,
|
event_type=event_type,
|
||||||
|
|||||||
@@ -653,6 +653,14 @@ class NotificationManager:
|
|||||||
if event.severity == 'CRITICAL' and cooldown_str is None:
|
if event.severity == 'CRITICAL' and cooldown_str is None:
|
||||||
cooldown = 60
|
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
|
# Check against last sent time using stable fingerprint
|
||||||
last_sent = self._cooldowns.get(event.fingerprint, 0)
|
last_sent = self._cooldowns.get(event.fingerprint, 0)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user