Skip to content

feat(undo): restore versioned PUT and DELETE operations#300

Merged
cxymds merged 1 commit into
mainfrom
cxymds/issue-1369-undo
Jul 23, 2026
Merged

feat(undo): restore versioned PUT and DELETE operations#300
cxymds merged 1 commit into
mainfrom
cxymds/issue-1369-undo

Conversation

@cxymds

@cxymds cxymds commented Jul 23, 2026

Copy link
Copy Markdown
Member

Related issue

Closes rustfs/backlog#1369.

Server-side atomic destination preconditions remain tracked by rustfs/backlog#1438.

Background and impact

RustFS supports object version history, exact delete-marker deletion, and copying a historical source version, but rc did not provide a safe workflow for recovering from an accidental versioned PUT or DELETE. Operators had to compose low-level requests manually and could easily delete the wrong marker, overwrite a concurrent update, or lose per-object failure context.

Root cause

The core object-store abstraction exposed version listing and version-aware deletion but did not expose an exact historical source version for CopyObject. There was also no deterministic undo planner or command-level current-version validation.

Solution

  • Add CopyObjectOptions and a backward-compatible exact-source-version copy abstraction.
  • Encode CopySource keys and version IDs correctly in the S3 adapter and preserve returned source/destination version metadata.
  • Preserve nanosecond precision when combining data versions and delete markers.
  • Add a pure planner for reversible latest operations and explicit historical versions.
  • Add rc undo with single-object and recursive prefix modes, dry run, explicit version selection, and bounded concurrency.
  • Require bucket versioning to be enabled; refuse suspended, unversioned, missing, or ambiguous histories.
  • Build the complete plan before mutation, revalidate the current version immediately before each action, and verify the resulting current version afterward.
  • Preserve object history: delete undo removes only the exact current marker; overwrite undo creates a new version by self-copying the selected historical version.
  • Emit per-object v3 plan/results, stable partial-failure exit codes, and blocked version IDs for Object Lock, retention, and legal-hold failures.

Concurrency boundary

The current S3/RustFS contract has no destination-current compare-and-swap for CopyObject or version-specific DeleteObject. The preflight and postcondition checks detect observed concurrent changes and report a conflict, but the mutation itself is not atomic and a conflict detected afterward cannot be rolled back. This PR therefore does not claim transactional or exactly-once semantics. The server prerequisite is rustfs/backlog#1438.

Validation

  • cargo fmt --all --check
  • CARGO_BUILD_JOBS=2 cargo clippy --workspace --all-targets -- -D warnings
  • CARGO_BUILD_JOBS=2 cargo test --workspace
  • git diff --check

Tests cover delete-marker restoration, overwrite restoration, explicit versions, dry run, recursive planning, bounded execution, missing and ambiguous history, suspended and unversioned buckets, stale plans before mutation, concurrent changes after mutation, plan-level retry, partial failure, access denial, legal hold, stable exit codes, pagination markers, nanosecond version ordering, CopySource encoding, and missing historical source versions.

@cxymds
cxymds requested a review from overtrue July 23, 2026 03:12
@cxymds
cxymds merged commit cbeb54f into main Jul 23, 2026
17 checks passed
@cxymds
cxymds deleted the cxymds/issue-1369-undo branch July 23, 2026 03:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant