Skip to content

fix(storage): scope the artifact purge alias guard to case-alias candidates - #6024

Draft
BigDataDZ wants to merge 1 commit into
apache:mainfrom
BigDataDZ:fix/4038-two-tier-purge-guard
Draft

BigDataDZ wants to merge 1 commit into
apache:mainfrom
BigDataDZ:fix/4038-two-tier-purge-guard

Conversation

@BigDataDZ

Copy link
Copy Markdown
Contributor

Summary

Purge's referential-integrity guard resolved the realpath of every remaining record before unlinking the purge set, so each purge() paid an O(all records) syscall sweep; retiring M sessions cost M × N realpaths and degraded into the minutes-long storm profiled in #4027.

The guard now resolves only the remaining records whose casefolded relative path collides with a purge path:

  • A case-insensitive filesystem (Windows, default macOS) is the one alias class the relative_path UNIQUE index cannot see — two stored paths differing only in case address one physical file. Those guards are flagged in memory (zero syscalls) and still get their resolved identity compared against the purge set, preserving the path is still referenced contract the existing case-alias tests pin.
  • Every other remaining record is pairwise alias-free by construction of the write path, which refuses an aliasing candidate at ingress (resolveArtifactPath). The behavioral delta is narrow: dir-symlink component aliasing between records with unrelated stored paths is now trusted to that write-time authority instead of being re-verified per purge.

A purge now pays O(purge set + flagged) syscalls instead of O(all records), which composes with whatever batching semantics maintainers prefer for the open questions on #4038. Independent of #6022 (the readiness half — no shared files); both together close out the two halves of that issue's profile.

Refs #4038

Verification

  • tsc --noEmit clean in @maka/storage; biome check clean on the touched file.
  • artifact-store.test.ts: 38 tests, 0 failures — including "purge preserves a payload inode still referenced by a non-target canonical record" (hardlink, path-identity based), "purge rejects case aliases that resolve to another live record", and "purge rejects case aliases of the same final symlink without unlinking it" (both exercise the flagged-guard resolution path on this case-insensitive Windows filesystem; symlink-privileged skips are environmental).
  • sqlite-artifact-metadata suite green. The husky pre-commit hook remains bypassed on this machine for the Windows/Node 24 biome.cmd EINVAL spawn failure documented in fix(runtime-host): defer conversation-copy discards to post-ready maintenance #6022.

AI use

Select exactly one:

  • No generative tool made a substantive contribution
  • Generative tooling made a substantive contribution

Tool(s) and scope: ZCode (GLM). Drafted the scoped-guard change and verification; the human contributor reviewed the approach and owns the result. Commits carry Generated-by: ZCode.

…idates

Purge's referential-integrity guard resolved the realpath of every
remaining record before unlinking the purge set, so each purge paid an
O(all records) syscall sweep and session retirement on a large
accumulated store degraded into a minutes-long storm (apache#4038, profile
in apache#4027).

The guard now resolves only the remaining records whose casefolded
relative path collides with a purge path: a case-insensitive
filesystem is the one alias class the write path's UNIQUE
relative_path index cannot see. Every other remaining record is
pairwise alias-free by construction of the write path, which refuses
an aliasing candidate at ingress. A purge now pays O(purge set +
flagged) syscalls instead of O(all records).

Refs apache#4038

Generated-by: ZCode
@github-actions github-actions Bot added the effort/S Under 100 readable lines label Oct 9, 2026

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

effort/S Under 100 readable lines

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant