Skip to main content

manager: only close SQLite caches we're actually using

ID
522bdc4
date
2026-11-06 14:00:54+00:00
author
Alex Chan <alex@alexwlchan.net>
parent
22f5874
message
manager: only close SQLite caches we're actually using

If an SQLite cache is invalidated, it's closed when we register the new
cache. The at-exit hook was holding a reference to the old cache, which
we can't even close because it's already been deleted.

Move the atexit hook so we close all outstanding SQLite caches at
program exit.
changed files
1 file, 14 additions, 2 deletions

Changed files

src/funkycache/manager.py (10346 → 10676)

diff --git a/src/funkycache/manager.py b/src/funkycache/manager.py
index acf015c..7621e02 100644
--- a/src/funkycache/manager.py
+++ b/src/funkycache/manager.py
@@ -11,7 +11,7 @@ from functools import wraps
 import inspect
 import json
 from pathlib import Path
-from typing import Any, Literal, overload, ParamSpec, Protocol, TypeVar
+from typing import Any, cast, Literal, overload, ParamSpec, Protocol, TypeVar
 import warnings
 
 import xxhash
@@ -104,6 +104,8 @@ class FunkyCache:
         self._root = Path(root)
         self._known_caches = {}
 
+        atexit.register(self._close)
+
     @overload
     def register[**P, R](self, func: F) -> F: ...
 
@@ -214,11 +216,21 @@ class FunkyCache:
                 for f in self._root.glob(f"{identifier}.*.db"):
                     if f != db_path:
                         f.unlink()
-                atexit.register(lambda: storage.close())
                 return storage
             case _:  # pragma: no cover
                 raise TypeError(f"unrecognised storage: {self._storage!r}")
 
+    def _close(self) -> None:  # pragma: no cover
+        """
+        Close any open files or underlying caches.
+        """
+        match self._storage:
+            case "sqlite":
+                for kc in self._known_caches.values():
+                    cast(SQLiteCacheStorage, kc.storage).close()
+            case _:
+                pass
+
     def notify_path_change(self, changed_paths: Path | list[Path]) -> None:
         """
         Invalidate cache that depend on this path and/or paths.