SSDP cache draft

Wed, 04 Jun 2025 08:45:21 -0500

author
Tuomo Valkonen <tuomov@iki.fi>
date
Wed, 04 Jun 2025 08:45:21 -0500
changeset 152
52362f545be1
parent 151
41adab2ef3f1
child 153
4efb3abc77f3

SSDP cache

borgend/backup.py file | annotate | diff | comparison | revisions
borgend/repository.py file | annotate | diff | comparison | revisions
config.example.yaml file | annotate | diff | comparison | revisions
--- a/borgend/backup.py	Mon Jun 02 23:02:42 2025 -0500
+++ b/borgend/backup.py	Wed Jun 04 08:45:21 2025 -0500
@@ -18,7 +18,6 @@
 from .instance import BorgInstance
 from .scheduler import TerminableThread
 from .exprotect import protect_noreturn
-from .ssdp_discover import discover_repository_provider
 
 _logger=logging.getLogger(__name__)
 
@@ -485,25 +484,12 @@
                 +self.repository.borg_parameters
                 +self.borg_parameters)
 
-        if self.repository.location is None:
-            assert(self.repository.ssdp_uuid is not None)
-            assert(self.repository.ssdp_path is not None)
-            ssdp_uuid = self.repository.ssdp_uuid
-            ssdp_path = self.repository.ssdp_path
-            self.logger.debug('Starting SSDP discovery of service {}'.format(ssdp_uuid))
-            self.__update_status(State.DISCOVERY)
-            #self._cond.release()
-            location = discover_repository_provider(ssdp_uuid)
-            #self._cond.acquire()
-            #self.__update_status(State.IDLE) # TODO: probably should update to old status
-            if location is None:
-                self.current_operation.add_error(Errors.OFFLINE)
-                self.logger.warn("Failed to discover repository provider {}".format(ssdp_uuid))
-            else:
-                self.logger.debug("Found repository provider {} at {}".format(ssdp_uuid, location))
-                self.__launch_with_location(op, params, "{}/{}".format(location, ssdp_path))
+        location = self.repository.discover(lambda: self.__update_status(State.DISCOVERY))
+        if location is None:
+            op.add_error(Errors.OFFLINE)
+            self.__mark_finished(op)
         else:
-            self.__launch_with_location(op, params, self.repository.location)
+            self.__launch_with_location(op, params, location)
 
     def __launch_with_location(self, op, params, location):
         if op.type==Operation.CREATE:
@@ -571,9 +557,10 @@
 
     def __mark_current_finished(self):
         current=self.current_operation
+        assert(current)
+        self.__mark_finished(current)
 
-        assert(current)
-
+    def __mark_finished(self, current):
         current.finish_time=MonotonicTime.now()
 
         self.previous_operation_of_type[current.type]=current
--- a/borgend/repository.py	Mon Jun 02 23:02:42 2025 -0500
+++ b/borgend/repository.py	Wed Jun 04 08:45:21 2025 -0500
@@ -21,6 +21,8 @@
 from . import config
 from .scheduler import QueueThread, QueuedEvent
 from .exprotect import protect_noreturn
+from .ssdp_discover import discover_repository_provider
+from .dreamtime import MonotonicTime
 
 logger=logging.getLogger(__name__)
 
@@ -113,6 +115,10 @@
                                            'SSDP service UUID', loc,
                                            is_optional = True)
 
+        self.ssdp_validity=config.check_nonneg_int(cfg, 'ssdp_validity',
+                                                   'SSDP service validity (seconds)', loc,
+                                                   300)
+
         self.ssdp_path=config.check_string(cfg, 'ssdp_path',
                                            'Path within SSDP service', loc,
                                            is_optional = self.ssdp_uuid is None)
@@ -138,6 +144,8 @@
     def __init__(self, identifier, cfg):
         self.identifier=identifier
         self.__decode_config(cfg)
+        self.last_discovered = 0
+        self.ssdp_cache = None
         super().__init__(name = 'RepositoryThread %s' % self.repository_name)
         repositories[self.repository_name]=self
 
@@ -161,6 +169,29 @@
     def is_ssdp(self):
         return self.location is None and self.ssdp_uuid is not None
 
+    def discover(self, update_status):
+        if self.location is not None:
+            return self.location
+        else:
+            assert(self.ssdp_uuid is not None)
+            assert(self.ssdp_path is not None)
+            if (self.ssdp_cache is not None and
+              MonotonicTime.after_other(self.last_discovered, self.ssdp_validity) >= MonotonicTime.now()):
+                return "{}/{}".format(self.ssdp_cache, self.ssdp_path)
+            else:
+                update_status()
+                self.logger.debug('Starting SSDP discovery of service {}'.format(self.ssdp_uuid))
+                #self._cond.release()
+                location = discover_repository_provider(self.ssdp_uuid)
+                if location is None:
+                    self.logger.warn("Failed to discover repository provider {}".format(self.ssdp_uuid))
+                    return None
+                else:
+                    self.last_discovered = MonotonicTime.now()
+                    self.ssdp_cache = location
+                    self.logger.debug("Found repository provider {} at {}".format(self.ssdp_uuid, location))
+                    return "{}/{}".format(location, self.ssdp_path)
+
     def launch_borg_instance(self, inst):
         try:
             self.logger.debug('launch_borg_instance: entering _cond')
--- a/config.example.yaml	Mon Jun 02 23:02:42 2025 -0500
+++ b/config.example.yaml	Wed Jun 04 08:45:21 2025 -0500
@@ -44,6 +44,7 @@
   - name: homeserver
     ssdp_uuid: borg@home.c5fad77dbff6157eba56597e9c404631
     ssdp_path: /mnt/backup/borg
+    ssdp_validity: 300
     keychain_account: borg-backup@mylaptop
 
 # Backups: configure here which files should be backed up, how frequently, and to

mercurial