fix: _save no longer resolves the store's realpath twice per call

_save() already resolves target = realpath(self.file) for the write path;
_sweep_stale_tmp then independently recomputed the same realpath to derive its
match basename. _sweep_stale_tmp now takes that resolved basename as a
parameter instead of re-resolving it, cutting one syscall per save. the sweep
itself still runs on every save (unchanged) - gating it to first-save-per-
instance would change when a crash-orphaned tmp from before this process
started actually gets swept, so that part is left alone.

Signed-off-by: disqualifier <dev@disqualifier.me>
This commit is contained in:
2026-07-06 00:18:16 -04:00
parent ddf76d8241
commit 98f7190f18
+5 -4
View File
@@ -121,7 +121,7 @@ class AioKV:
target = await asyncio.to_thread(os.path.realpath, self.file)
directory = os.path.dirname(target) or "."
await asyncio.to_thread(os.makedirs, directory, exist_ok=True)
await self._sweep_stale_tmp(directory)
await self._sweep_stale_tmp(directory, os.path.basename(target))
payload = await asyncio.to_thread(json.dumps, cache, allow_nan=False)
tmp = f"{target}.{os.getpid()}.tmp"
@@ -137,14 +137,15 @@ class AioKV:
log.exception("aiokv: failed to clean up temp file %s", tmp)
raise
async def _sweep_stale_tmp(self, directory: str) -> None:
async def _sweep_stale_tmp(self, directory: str, base: str) -> None:
"""remove orphaned .<pid>.tmp files left by a hard crash of a different, dead process
matches only the exact shape _save() creates (<realpath basename>.<pid>.tmp), via a
re.escape'd regex over a directory listing rather than a raw glob - a glob pattern
both crosses unrelated dots (matching non-aiokv neighbors like foo.backup.999.tmp) and
mistreats glob metacharacters in the store's own filename (e.g. state[prod].json)"""
base = os.path.basename(await asyncio.to_thread(os.path.realpath, self.file))
mistreats glob metacharacters in the store's own filename (e.g. state[prod].json).
`base` is the realpath'd basename _save() already resolved - passed in rather than
re-resolved here so a save does one realpath call, not two."""
candidate = re.compile(rf"^{re.escape(base)}\.(\d+)\.tmp$")
names = await asyncio.to_thread(os.listdir, directory)
for name in names: