Skip to content

feat(storage): add list_filenames, delete, delete_many primitives#553

Merged
michael-richey merged 5 commits into
mainfrom
prune/pr1-storage-primitives
May 11, 2026
Merged

feat(storage): add list_filenames, delete, delete_many primitives#553
michael-richey merged 5 commits into
mainfrom
prune/pr1-storage-primitives

Conversation

@michael-richey
Copy link
Copy Markdown
Collaborator

Summary

First of three stacked PRs adding a top-level prune command that deletes orphaned per-resource state files when source resources are removed upstream.

This PR adds the storage-layer primitives that the upcoming State.compute_stale_files / delete_stale_files helpers (PR 2) and prune command (PR 3) will build on. Internal API only — no user-visible behavior change.

What changed

  • BaseStorage gains three methods:
    • list_filenames(origin, resource_type) -> Set[str] — full filenames under <base>/<resource_type>.*.json, opaque strings (no parsing).
    • delete(origin, filename) -> None — single-file delete, no-op if absent.
    • delete_many(origin, filenames) -> Dict[str, str] — batch wrapper returning {filename: "ok" | error}. Concrete default loops delete(); backends like S3 may override with DeleteObjects later.
  • Concrete defaults raise NotImplementedError on BaseStorage rather than @abstractmethod, so out-of-tree backends fail loudly rather than silently returning empty results.
  • All four in-tree backends implement the methods:
    • LocalFile: os.listdir + os.remove (idempotent on FileNotFoundError).
    • AWSS3Bucket: paginated list_objects_v2; delete_object (idempotent at the AWS layer).
    • GCSBucket: list_blobs(prefix=...); blob.delete() wrapped in try/except NotFound.
    • AzureBlobContainer: list_blobs(name_starts_with=...); delete_blob wrapped in try/except ResourceNotFoundError.

Test plan

  • 35 new unit tests across all four backends + base-class default behavior (tests/unit/test_storage_list_filenames.py, tests/unit/test_storage_delete.py).
  • Full unit suite (tox -e py3 -- tests/unit/) passes — 447 tests, no regressions.
  • `tox -e ruff,black` clean.

Stacked PR context

This is PR 1 of 3. Subsequent PRs:

  • PR 2 — `State.compute_stale_files` / `delete_stale_files` helpers.
  • PR 3 — top-level `prune` command (the user-visible change).

🤖 Generated with Claude Code

Internal storage API additions enabling per-resource file enumeration
and deletion across all four backends (LocalFile, S3, GCS, Azure).
Required for the upcoming `prune` command which removes orphaned
state files when source resources are deleted upstream.

- BaseStorage gains concrete defaults that raise NotImplementedError
  for list_filenames/delete (out-of-tree backends fail loudly rather
  than silently no-op'ing). delete_many has a working default that
  loops delete(), so backends only need to override the single-key
  delete to get batch deletion for free.
- LocalFile: os.listdir + filename prefix filter; os.remove with
  FileNotFoundError handling.
- AWSS3Bucket: paginated list_objects_v2; idempotent delete_object.
- GCSBucket: list_blobs(prefix=...); blob.delete() wrapped in
  try/except NotFound.
- AzureBlobContainer: list_blobs(name_starts_with=...); delete_blob
  wrapped in try/except ResourceNotFoundError.

35 new unit tests across all backends; existing 412 tests unaffected.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@michael-richey michael-richey marked this pull request as ready for review May 11, 2026 14:30
@michael-richey michael-richey requested a review from a team as a code owner May 11, 2026 14:30
riyazsh
riyazsh previously approved these changes May 11, 2026
heyronhay
heyronhay previously approved these changes May 11, 2026
@michael-richey michael-richey dismissed stale reviews from heyronhay and riyazsh via 4757cf5 May 11, 2026 17:40
@michael-richey michael-richey merged commit 45ef33f into main May 11, 2026
11 of 13 checks passed
@michael-richey michael-richey deleted the prune/pr1-storage-primitives branch May 11, 2026 19:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants