diff --git a/src/c3nav/mapdata/models/update.py b/src/c3nav/mapdata/models/update.py index 58b4c990..877ef51c 100644 --- a/src/c3nav/mapdata/models/update.py +++ b/src/c3nav/mapdata/models/update.py @@ -75,6 +75,22 @@ class MapUpdate(models.Model): cache.set('mapdata:last_processed_update', last_processed_update, None) return last_processed_update + @classmethod + def last_processed_geometry_update(cls, force=False): + if not force: + last_processed_geometry_update = cache.get('mapdata:last_processed_geometry_update', None) + if last_processed_geometry_update is not None: + return last_processed_geometry_update + try: + with cls.lock(): + last_processed_geometry_update = cls.objects.filter(processed=True, + geometries_changed=True).latest().to_tuple + cache.set('mapdata:last_processed_geometry_update', last_processed_geometry_update, None) + except cls.DoesNotExist: + last_processed_geometry_update = (0, 0) + cache.set('mapdata:last_processed_geometry_update', last_processed_geometry_update, None) + return last_processed_geometry_update + @property def to_tuple(self): return self.pk, int(make_naive(self.datetime).timestamp()) @@ -91,6 +107,10 @@ class MapUpdate(models.Model): def current_processed_cache_key(cls, request=None): return cls.build_cache_key(*cls.last_processed_update()) + @classmethod + def current_processed_geometry_cache_key(cls, request=None): + return cls.build_cache_key(*cls.last_processed_geometry_update()) + @staticmethod def build_cache_key(pk, timestamp): return int_to_base36(pk)+'_'+int_to_base36(timestamp) @@ -178,7 +198,9 @@ class MapUpdate(models.Model): update_cache_key = MapUpdate.build_cache_key(*new_updates[-1].to_tuple) (settings.CACHE_ROOT / update_cache_key).mkdir() - if any(update.geometries_changed for update in new_updates): + last_geometry_update = ([None] + [update.geometries_changed for update in new_updates])[-1] + + if last_geometry_update is not None: from c3nav.mapdata.utils.cache.changes import changed_geometries changed_geometries.reset() @@ -209,6 +231,10 @@ class MapUpdate(models.Model): from c3nav.mapdata.render.renderdata import LevelRenderData LevelRenderData.rebuild(update_cache_key) + + transaction.on_commit( + lambda: cache.set('mapdata:last_processed_geometries_update', last_geometry_update.to_tuple, None) + ) else: logger.info('No geometries affected.') diff --git a/src/c3nav/mapdata/render/renderdata.py b/src/c3nav/mapdata/render/renderdata.py index 3d2116e6..5bccaa73 100644 --- a/src/c3nav/mapdata/render/renderdata.py +++ b/src/c3nav/mapdata/render/renderdata.py @@ -55,7 +55,7 @@ class LevelRenderData: darken_area: MultiPolygon | None = None @staticmethod - def rebuild(update_cache_key): + def rebuild(update_cache_key, geometry_update_cache_key): # Levels are automatically sorted by base_altitude, ascending levels = tuple(Level.objects.prefetch_related('altitudeareas', 'buildings', 'doors', 'spaces', 'spaces__holes', 'spaces__areas', 'spaces__columns', @@ -352,9 +352,9 @@ class LevelRenderData: package.add_level(render_level.pk, theme, map_history, access_restriction_affected) - render_data.save(update_cache_key, render_level.pk, theme) + render_data.save(geometry_update_cache_key, render_level.pk, theme) - package.save_all(update_cache_key) + package.save_all(geometry_update_cache_key) cached = LocalContext() @@ -370,7 +370,7 @@ class LevelRenderData: def get(cls, level, theme): # get the current render data from local variable if no new processed mapupdate exists. # this is much faster than any other possible cache - cache_key = MapUpdate.current_processed_cache_key() + cache_key = MapUpdate.current_processed_geometry_cache_key() level_pk = level.pk if isinstance(level, Level) else level theme_pk = theme.pk if isinstance(theme, Theme) else theme key = f'{level_pk}_{theme_pk}' diff --git a/src/c3nav/mapdata/utils/cache/package.py b/src/c3nav/mapdata/utils/cache/package.py index 62ee4c87..9e028df3 100644 --- a/src/c3nav/mapdata/utils/cache/package.py +++ b/src/c3nav/mapdata/utils/cache/package.py @@ -138,7 +138,7 @@ class CachePackage: @classmethod def open_cached(cls) -> Self: from c3nav.mapdata.models import MapUpdate - cache_key = MapUpdate.current_processed_cache_key() + cache_key = MapUpdate.current_processed_geometry_cache_key() if getattr(cls.cached, 'key', None) != cache_key: cls.cached.key = cache_key cls.cached.data = None