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:
+5
-4
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user