`clear(namespace=...)` over-deletes on `SimpleMemoryCache`: prefix match has no boundary, silently clearing sibling namespaces (inconsistent with the Valkey backend)
- 主要语言
- Python
- 星标
- 1.4k
- 派生
- 181
- PR 合并指标
- 30 天内没有已合并 PR
描述
**Summary**
On `SimpleMemoryCache`, `clear(namespace="foo")` also deletes keys stored under any namespace that *starts with* `"foo"` (e.g. `"foobar"`), silently discarding unrelated cached data. The Valkey backend does not have this problem, so the same `clear(namespace=...)` call behaves differently depending on the backend.
**Reproduction** (in-memory, no external server needed; HEAD `ae5948b`):
```python
import asyncio
from aiocache import SimpleMemoryCache
async def main():
c = SimpleMemoryCache()
await c.set("k", 1, namespace="foo") # stored under key "fook"
await c.set("k", 2, namespace="foobar") # stored under key "foobark"
await c.clear(namespace="foo") # intended: clear only namespace "foo"
print(await c.get("k", namespace="foo")) # None (expected)
print(await c.get("k", namespace="foobar")) # None <-- BUG: expected 2, data silently lost
asyncio.run(main())
```
**Root cause**
`SimpleMemoryBackend._clear` matches by bare prefix, and memory keys are built with no delimiter (`f"{ns}{k}"`):
```python
# aiocache/backends/memory.py
async def _clear(self, namespace=None, _conn=None):
if namespace:
for key in list(self._cache):
if key.startswith(namespace): # no boundary: "foo" also matches "foobar..."
self.__delete(key)
```
The Valkey backend avoids this by isolating namespaces with a `:` delimiter in both key construction and clear (`f"{ns}:{k}"` and a `"{ns}:*"` scan), so `clear(namespace="foo")` is boundary-safe on Valkey but over-deletes on the memory backend (and memcached, which shares the bare-prefix default key builder).
**Why it matters**
Two concerns: (1) **silent data loss** — clearing one namespace can wipe another whose name shares a prefix, with no error; and (2) **backend inconsistency** — the backends are documented as interchangeable, but `clear(namespace=...)` is not consistent across them.
**On intent** — I recognize this may be the intended "prefix" behavior for the memory/memcached backends: `test_clear_namespace` currently asserts `clear("nm")` deletes `"nma"` and `"nmb"`, which codifies bare-prefix matching. That is exactly why I am raising this as an issue rather than opening a PR — the resolution is a design choice for you. (Distinct from #479, which was `clear()` ignoring the instance namespace entirely and was fixed in #562; and from #910, a feature request.)
**Possible resolutions (your call)**
1. **Align the memory (and memcached) backends with Valkey** — use a `:` delimiter in the default key builder and a boundary-aware clear, so `clear(namespace=...)` is consistent across all backends. This changes the memory key format (low risk: memory is ephemeral) and would update `test_clear_namespace`. Happy to send this PR.
2. **Keep the prefix model but document it** — explicitly warn that on prefix-scanning backends, namespaces must not share a prefix, to prevent silent data loss. Also happy to PR the docs.
---
[](https://coretexa.dev)
*Originated and independently verified by Coretexa — an AI-assisted pipeline that reproduces each finding on HEAD and has it adversarially checked by a separate verifier than found it before submission. Here: reproduced on HEAD `ae5948b`, the delimiter fix confirmed to resolve it, and the existing test reviewed.*
**Environment:** aiocache @ HEAD `ae5948b`, Python 3.11.
贡献指南
评估
这个 Issue 还没有评估数据。