storage/sqlite: store the JSON-serialised key in the database
- ID
9e42abf- date
2026-11-06 22:06:41+00:00- author
Alex Chan <alexc@tailscale.com>- parent
9393430- message
storage/sqlite: store the JSON-serialised key in the database We use slightly more storage, but it'll be much easier to debug a misbehaving database or cache if this is there. We only select the value column when looking up values, so this won't affect lookup speed.- changed files
1 file, 19 additions, 7 deletions
Changed files
src/funkycache/storage.py (6427 → 6794)
diff --git a/src/funkycache/storage.py b/src/funkycache/storage.py
index 7495dce..a9f009c 100644
--- a/src/funkycache/storage.py
+++ b/src/funkycache/storage.py
@@ -147,7 +147,15 @@ class SQLiteCacheStorage[V](TypedCacheStorage[V]):
self.con.execute("PRAGMA synchronous = NORMAL;")
cursor = self.con.cursor()
- cursor.execute("CREATE TABLE IF NOT EXISTS funkycache(key PRIMARY KEY, value)")
+
+ # Each row in the table contains three columns:
+ # - enc_key is the JSON-serialised, hashed key
+ # - raw_key is the JSON-serialised key (for debugging)
+ # - value is the JSON-serialised value
+ cursor.execute(
+ "CREATE TABLE IF NOT EXISTS funkycache(enc_key PRIMARY KEY, raw_key, value)"
+ )
+
self.con.commit()
super().__init__(data_type=data_type)
@@ -174,12 +182,12 @@ class SQLiteCacheStorage[V](TypedCacheStorage[V]):
"""
self.close()
- def _encode_key(self, key: Mapping[str, Any]) -> str:
+ def _encode_key(self, key: Mapping[str, Any]) -> tuple[str, str]:
"""
Encode a mapping as a string key.
"""
json_key = json.dumps(key, sort_keys=True, default=str)
- return _hash(json_key)
+ return json_key, _hash(json_key)
def _set_str(self, key: Mapping[str, Any], value: str) -> None:
"""
@@ -188,10 +196,12 @@ class SQLiteCacheStorage[V](TypedCacheStorage[V]):
Throws an exception if you overwrite an existing key with
a different value.
"""
- enc_key = self._encode_key(key)
+ json_key, enc_key = self._encode_key(key)
try:
- self.con.execute("INSERT INTO funkycache VALUES (?,?)", (enc_key, value))
+ self.con.execute(
+ "INSERT INTO funkycache VALUES (?,?,?)", (enc_key, json_key, value)
+ )
self.con.commit()
except sqlite3.IntegrityError as err:
if err.sqlite_errorname == "SQLITE_CONSTRAINT_PRIMARYKEY":
@@ -208,9 +218,11 @@ class SQLiteCacheStorage[V](TypedCacheStorage[V]):
Throws a KeyError if you look up a key which isn't in the cache.
"""
- enc_key = self._encode_key(key)
+ _, enc_key = self._encode_key(key)
- res = self.con.execute("SELECT value FROM funkycache WHERE key=?", (enc_key,))
+ res = self.con.execute(
+ "SELECT value FROM funkycache WHERE enc_key=?", (enc_key,)
+ )
try:
(value,) = res.fetchone()