diff options
| author | Markus Heiser <markus.heiser@darmarit.de> | 2025-05-01 11:31:29 +0200 |
|---|---|---|
| committer | Markus Heiser <markus.heiser@darmarIT.de> | 2025-05-03 08:39:12 +0200 |
| commit | 8ef5fbca4e90668c8ae1f9f60f4d5d43816a593c (patch) | |
| tree | fe22bf9435e471cbf0e668687ea79cc106d5380c /searx/cache.py | |
| parent | 7351c38e6c7fb1386efafc1685a634f8a1bd1d84 (diff) | |
[fix] cache.ExpireCache: definition of a context name for the key
The definition of a context name belongs in the abstract base class (was
previously only in the concrete implementation for the SQLite adapter).
Suggested-by: @dalf https://github.com/searxng/searxng/pull/4650#discussion_r2069873853
Signed-off-by: Markus Heiser <markus.heiser@darmarit.de>
Diffstat (limited to 'searx/cache.py')
| -rw-r--r-- | searx/cache.py | 59 |
1 files changed, 37 insertions, 22 deletions
diff --git a/searx/cache.py b/searx/cache.py index dc388207d..ea6c17be9 100644 --- a/searx/cache.py +++ b/searx/cache.py @@ -83,12 +83,12 @@ class ExpireCacheStats: """Dataclass wich provides information on the status of the cache.""" cached_items: dict[str, list[tuple[str, typing.Any, int]]] - """Values in the cache mapped by table name. + """Values in the cache mapped by context name. .. code: python { - "table name": [ + "context name": [ ("foo key": "foo value", <expire>), ("bar key": "bar value", <expire>), # ... @@ -98,22 +98,22 @@ class ExpireCacheStats: """ def report(self): - c_tables = 0 + c_ctx = 0 c_kv = 0 lines = [] - for table_name, kv_list in self.cached_items.items(): - c_tables += 1 + for ctx_name, kv_list in self.cached_items.items(): + c_ctx += 1 if not kv_list: - lines.append(f"[{table_name:20s}] empty") + lines.append(f"[{ctx_name:20s}] empty") continue for key, value, expire in kv_list: valid_until = datetime.datetime.fromtimestamp(expire).strftime("%Y-%m-%d %H:%M:%S") c_kv += 1 - lines.append(f"[{table_name:20s}] {valid_until} {key:12}" f" --> ({type(value).__name__}) {value} ") + lines.append(f"[{ctx_name:20s}] {valid_until} {key:12}" f" --> ({type(value).__name__}) {value} ") - lines.append(f"number of tables: {c_tables}") + lines.append(f"Number of contexts: {c_ctx}") lines.append(f"number of key/value pairs: {c_kv}") return "\n".join(lines) @@ -127,15 +127,27 @@ class ExpireCache(abc.ABC): hash_token = "hash_token" @abc.abstractmethod - def set(self, key: str, value: typing.Any, expire: int | None) -> bool: + def set(self, key: str, value: typing.Any, expire: int | None, ctx: str | None = None) -> bool: """Set *key* to *value*. To set a timeout on key use argument ``expire`` (in sec.). If expire is unset the default is taken from :py:obj:`ExpireCacheCfg.MAXHOLD_TIME`. After the timeout has expired, the key will automatically be deleted. + + The ``ctx`` argument specifies the context of the ``key``. A key is + only unique in its context. + + The concrete implementations of this abstraction determine how the + context is mapped in the connected database. In SQL databases, for + example, the context is a DB table or in a Key/Value DB it could be + a prefix for the key. + + If the context is not specified (the default is ``None``) then a + default context should be used, e.g. a default table for SQL databases + or a default prefix in a Key/Value DB. """ @abc.abstractmethod - def get(self, key: str, default=None) -> typing.Any: + def get(self, key: str, default=None, ctx: str | None = None) -> typing.Any: """Return *value* of *key*. If key is unset, ``None`` is returned.""" @abc.abstractmethod @@ -171,7 +183,7 @@ class ExpireCache(abc.ABC): @staticmethod def normalize_name(name: str) -> str: """Returns a normalized name that can be used as a file name or as a SQL - table name.""" + table name (is used, for example, to normalize the context name).""" _valid = "-_." + string.ascii_letters + string.digits return "".join([c for c in name if c in _valid]) @@ -320,14 +332,15 @@ class ExpireCacheSQLite(sqlitedb.SQLiteAppl, ExpireCache): # implement ABC methods of ExpireCache - def set(self, key: str, value: typing.Any, expire: int | None, table: str | None = None) -> bool: - """Set key/value in ``table``. If expire is unset the default is taken - from :py:obj:`ExpireCacheCfg.MAXHOLD_TIME`. If ``table`` argument is - ``None`` (the default), a table name is generated from the - :py:obj:`ExpireCacheCfg.name`. If DB ``table`` does not exists, it will be - created (on demand) by :py:obj:`self.create_table + def set(self, key: str, value: typing.Any, expire: int | None, ctx: str | None = None) -> bool: + """Set key/value in DB table given by argument ``ctx``. If expire is + unset the default is taken from :py:obj:`ExpireCacheCfg.MAXHOLD_TIME`. + If ``ctx`` argument is ``None`` (the default), a table name is + generated from the :py:obj:`ExpireCacheCfg.name`. If DB table does not + exists, it will be created (on demand) by :py:obj:`self.create_table <ExpireCacheSQLite.create_table>`. """ + table = ctx self.maintenance() value = self.serialize(value=value) @@ -360,12 +373,14 @@ class ExpireCacheSQLite(sqlitedb.SQLiteAppl, ExpireCache): return True - def get(self, key: str, default=None, table: str | None = None) -> typing.Any: - """Get value of ``key`` from ``table``. If ``table`` argument is - ``None`` (the default), a table name is generated from the - :py:obj:`ExpireCacheCfg.name`. If ``key`` not exists (in table), the - ``default`` value is returned. + def get(self, key: str, default=None, ctx: str | None = None) -> typing.Any: + """Get value of ``key`` from table given by argument ``ctx``. If + ``ctx`` argument is ``None`` (the default), a table name is generated + from the :py:obj:`ExpireCacheCfg.name`. If ``key`` not exists (in + table), the ``default`` value is returned. + """ + table = ctx self.maintenance() if not table: |