Refactor MQTT (#24010)

* refactor mqtt so that Frigate owns the transport lifecycle instead of delegating it to paho

* release the shutdown barrier on worker crash and replay retained publishes the broker never acked

* collapse in-flight retained values by topic and release the shutdown barrier from a finally

* replay the outage buffer before the publish queue so newer values are not reverted
This commit is contained in:
Josh Hawkins
2026-09-12 07:30:04 -06:00
committed by Nicolas Mowen
parent f4cf1e1539
commit ad04101c76
10 changed files with 1774 additions and 347 deletions
+14 -9
View File
@@ -63,14 +63,8 @@ class WebPushClient(Communicator):
self.last_notification_time: float = 0
self.user_cameras: dict[str, set[str]] = {}
self.notification_queue: queue.Queue[PushNotification] = queue.Queue()
self.notification_thread = threading.Thread(
target=self._process_notifications, daemon=True
)
self.notification_thread.start()
self.suspension_thread = threading.Thread(
target=self._process_suspensions, daemon=True
)
self.suspension_thread.start()
self.notification_thread: threading.Thread | None = None
self.suspension_thread: threading.Thread | None = None
if not self.config.notifications.email:
logger.warning("Email must be provided for push notifications to be sent.")
@@ -99,6 +93,16 @@ class WebPushClient(Communicator):
"""Wrapper for allowing dispatcher to subscribe."""
pass
def start(self) -> None:
self.notification_thread = threading.Thread(
target=self._process_notifications, daemon=True
)
self.notification_thread.start()
self.suspension_thread = threading.Thread(
target=self._process_suspensions, daemon=True
)
self.suspension_thread.start()
def check_registrations(self) -> None:
# check for valid claim or create new one
now = datetime.datetime.now().timestamp()
@@ -608,4 +612,5 @@ class WebPushClient(Communicator):
def stop(self) -> None:
logger.info("Closing notification queue")
self.notification_thread.join()
if self.notification_thread is not None:
self.notification_thread.join()