Commit Graph

371 Commits

Author SHA1 Message Date
Henry Guo d5df66ac4f fix(scanner): require authoritative usage snapshots (#5333) 2026-07-28 07:29:57 +08:00
houseme 6d3ce90c0f fix(lifecycle): harden manual transition rollout checks (#5344)
Co-authored-by: heihutu <heihutu@gmail.com>
2026-07-27 17:29:06 +00:00
abdullahnah92 c3aac2279f fix(site-replication): keep reverse direction after config broadcast (#5292)
* fix(site-replication): keep reverse direction after config broadcast

`site-repl-*` rules encode the sender's outbound direction: their
destination ARN names the receiver. `apply_bucket_meta_item` wrote an
incoming rule set verbatim over the receiver's, leaving the receiver with
a rule whose ARN is its own deployment ID. `reconcile_site_replication_bucket_targets`
skips the local peer, so no bucket target can back that ARN and every
object was dropped; the follow-up call reconciled targets only, so
nothing rebuilt the lost reverse rule. Replication went one-directional
after any PutBucketReplication broadcast — the console's Save button,
`mc replicate import`, a metadata import, or `/site-replication/repair`.

Only operator-authored rules now travel between sites; each site owns its
`site-repl-*` rules and rebuilds them from the current peer set.

Four defects kept that invisible or unrecoverable:

- `update_all_targets` discarded target-client build errors silently, and
  `replicate_object` logged the resulting missing-target drop at debug
  while every other failure there logs at error. Both now report.
- `site_replication_rule_complete` never checked that a rule's
  destination named a remote site, so two sites holding identical
  configs — the post-clobber state — passed as in sync.
- `update_service_account` cannot rewrite `parent_user`, and IAM records
  encrypted with a previous root secret decode as "no such account".
  Startup now reconciles the account, reseeding from the secret every
  site-replication bucket target already stores, and refuses the
  delete-then-create sequence when the parent cannot back an account.
  Bucket rules are reconciled too, so an already-broken site heals on
  upgrade.
- A joined site never verified it could reach the initiator, whose
  endpoint is derived from the Host header of the admin request that
  created the topology. The join now probes each peer and reports through
  `initial_sync_error_message`.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* fix(site-replication): report unreachable targets and reconcile on a timer

Rule-shape checking cannot see an unreachable peer. A `site-repl-*` rule
can be perfectly formed while the endpoint recorded for its peer is one
this site cannot reach: `update_all_targets` then builds no client and
`replicate_object` drops every object against that ARN, yet the rule set
still reads as correct and the bucket reports in sync.

Each site now reports whether all of its `site-repl-*` rules resolve to a
live target (`SRBucketInfo.replicationTargetsOnline`, read from the
already-resolved client map so the status path stays cheap), and the
status aggregation treats an offline report as a mismatch. The field is
additive and optional: peers that omit it are "unknown", never a fault,
so a mixed-version topology does not flip every bucket to out of sync.

The reconcilers also run on a 10-minute timer instead of at startup only,
so drift is repaired without waiting for a restart. Both are no-ops when
the wiring already matches — the bucket pass compares serialized targets
and the rule set before writing. The tick takes the site-replication
lifecycle lock with a non-blocking try_acquire and skips the round when
an add/remove/endpoint-refresh holds it: those run in phases, and
rebuilding rules between two of them would resurrect what the operation
just tore down.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* refactor(site-replication): invert reconcile dependency to satisfy layers

`startup_services.rs` sits in the infra layer and was calling the
reconcilers in `admin::handlers::site_replication`, which is interface —
a reverse dependency that check_layer_dependencies.sh rejects.

Moving the reconcilers down is not viable in this change: they rest on
the site-replication state core (`SiteReplicationState` alone has 107
in-file uses, `load_site_replication_state` 38, the state lock 33), so
relocating it would move ~2000 lines and ~200 call sites through a
bug-fix PR.

Invert the direction instead. A new infra module owns the contract and
the schedule; the admin layer registers its reconciler from
`register_site_replication_route`, which runs while the admin router is
built — `init_startup_http_servers` awaits that before
`init_startup_runtime_services` reconciles, so the hook is always
installed in time. No logic moves and no baseline entry is added: the
dependency genuinely reverses.

The lifecycle guard now wraps both reconcilers in one round rather than
each separately, closing the window between them.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* fix(site-replication): harden reconcile per review feedback

Addresses the automated review on #5292.

Security: secret recovery from bucket targets accepted any target carrying
the `site-replicator-0` access key. Bucket targets are writable by anyone
holding `admin:SetBucketTarget`, so such a principal could plant a secret
and have reconciliation recreate the broadly privileged replication
account with it. A target must now name a peer in the persisted state and
point at that peer's recorded endpoint, disagreeing targets abort the
recovery, and only missing/unreadable-account errors may trigger it at
all — a transient store failure no longer rewrites a live account.

Durability: the repair no longer deletes before creating. A readable
account is rebound in place through a new `parent_user` field on
`UpdateServiceAccountOpts`, gated to `site-replicator-0` under
`allow_site_replicator_account` exactly as the account itself is. The
parent also lives in the session-token claims, and
`prepare_service_account_auth` denies the account when the two disagree,
so both move together.

Availability: the reconcile scheduler no longer requires an inline IAM
bootstrap. Deferred IAM recovers in the background with no callback into
the scheduler, which left a recovered node with self-pointing rules until
the next restart. It now starts unconditionally and returns early while
IAM or the object store are unavailable. Its first pass runs inside the
task, so walking every bucket no longer delays startup.

Correctness: an endpoint refresh commits bucket targets and peer state in
separate steps without holding the lifecycle lock, so a tick landing
between them rewrote targets from the stale endpoint; the reconciler now
also skips while any pending marker is set. Rule repair preserves an
operator-authored `role` and clears only sender-owned site-replication
ARNs, matching the merge path.

Hot path: the per-object missing-target message returns to debug. The
condition is reported once per bucket per reconcile pass instead.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Co-authored-by: houseme <housemecn@gmail.com>
2026-07-27 22:39:23 +08:00
houseme 300beff970 fix: classify manual transition tier failures (#5335)
Co-authored-by: heihutu <heihutu@gmail.com>
2026-07-27 12:49:08 +00:00
houseme ab5aa54035 fix(ecstore): replay manual transition task journal (#5329)
Recover accepted manual-transition tasks from the durable task journal when worker-result markers are missing after a restart.

Co-authored-by: heihutu <heihutu@gmail.com>
2026-07-27 17:36:40 +08:00
houseme e076e8cc6e feat(scripts): add runbook entrypoints for #1508 #1510 (#5326)
* feat(ecstore): attribute manual transition worker failures

Add manual transition worker failure reason tracking and persistence recovery compatibility for checksum validation.

Co-Authored-By: heihutu <heihutu@gmail.com>

* chore(ilm): add manual transition diagnostics scripts

Co-Authored-By: heihutu <heihutu@gmail.com>

* style(ecstore): format manual transition attribution

Co-Authored-By: heihutu <heihutu@gmail.com>

* fix(ecstore): avoid copying failure reasons via clone

Co-Authored-By: heihutu <heihutu@gmail.com>

* fix(manual-transition): improve matrix verification scripts

- Add strict mixed rollout phase ratio validation.
- Add strict read/write ratio validation for soak mix.
- Inline generated admin-check command blocks into mixed-rollout run script.

Co-Authored-By: heihutu <heihutu@gmail.com>

* feat(scripts): add runbook entrypoints for #1508 #1510

---------

Co-authored-by: heihutu <heihutu@gmail.com>
2026-07-27 06:47:28 +00:00
houseme 9d84056d7b feat(ecstore): attribute manual transition worker failures (#5324)
* feat(ecstore): attribute manual transition worker failures

Add manual transition worker failure reason tracking and persistence recovery compatibility for checksum validation.

Co-Authored-By: heihutu <heihutu@gmail.com>

* chore(ilm): add manual transition diagnostics scripts

Co-Authored-By: heihutu <heihutu@gmail.com>

* style(ecstore): format manual transition attribution

Co-Authored-By: heihutu <heihutu@gmail.com>

* fix(ecstore): avoid copying failure reasons via clone

Co-Authored-By: heihutu <heihutu@gmail.com>

---------

Co-authored-by: heihutu <heihutu@gmail.com>
2026-07-27 06:06:12 +00:00
houseme e0e2eb30a9 test(ilm): cover pending worker budget status (#5317)
Co-authored-by: heihutu <heihutu@gmail.com>
2026-07-26 17:38:28 +00:00
houseme fec09968b9 fix(ilm): preserve manual transition duration budget (#5315)
Co-authored-by: heihutu <heihutu@gmail.com>
2026-07-26 17:32:33 +00:00
houseme cc3c39da5c test(ilm): cover queue pressure job readback (#5313)
Co-authored-by: heihutu <heihutu@gmail.com>
2026-07-26 17:16:53 +00:00
houseme e79337bb5c test(ilm): cover queue-full terminal job records (#5310)
Co-authored-by: heihutu <heihutu@gmail.com>
2026-07-26 17:11:47 +00:00
Zhengchao An 63e57378d6 fix(ecstore): never cache fabricated bucket metadata as authoritative (#5307)
BucketMetadataSys::get_config lazily fabricated a default BucketMetadata
(object-lock off) for any bucket whose .metadata.bin was ConfigNotFound and
cached it in the map that the map-only, fail-closed metadata_sys::get()
serves. The object-lock batch-delete gate (object_lock_delete_check_required,
backlog#929 / #4297) treats that map as authoritative, so a metadata miss
became a cached "no lock" answer: a versioning peek could poison the cache
and let delete_objects skip the per-object retention/legal-hold stat. The
same fabrication raced make_bucket (lost update overwriting freshly
persisted lock-enabled metadata) and let the 15-minute refresh loop replace
good cached metadata on a transient quorum dip.

Production changes:
- get_config caches only metadata actually read from disk; misses are
  recorded in a bounded negative cache (30s TTL, 10k entries, invalidated by
  set()) so repeated lookups for metadata-less names cost no extra
  namespace-lock + erasure-set fanout (reachable pre-auth via CORS
  preflight and per-key in DeleteObjects).
- concurrent_load never lets a fabricated default REPLACE an existing map
  entry; startup insert-if-vacant behavior for legacy buckets is preserved.
- delete_objects and new_ns_lock resolve dist-erasure, versioning, and the
  object-lock gate from the set's own instance context (backlog#1052)
  instead of the ambient facade, so a second in-process instance (or, in
  tests, another test's transient DistErasure window) cannot reroute
  locking onto an empty dist locker list or answer with the wrong
  instance's bucket state.

Test-isolation changes (the bug that surfaced all of the above: the
delete_objects lock-gating test failed deterministically when sharing a
process with the lifecycle env tests):
- The MinIO-migration test builds on an isolated InstanceContext instead of
  registering soon-deleted disks in the shared bootstrap registry.
- The cached lifecycle env re-registers its disks on every use, surviving
  other serial tests' reset_local_disk_test_state.
- Hermetic SetDisks helpers gain isolated-context variants pinned to plain
  erasure; tier-free non-serial test modules use them, guard-based
  SetupTypeGuard tests stay on the bootstrap context.
- Three deterministic pin tests (nextest-safe) cover the caching contract,
  the delete gate resolution source, and the ns-lock resolution source.

Verification:
- cargo test -p rustfs-ecstore --lib -- --exact <4-test combo from the
  report> (previously failing, now green)
- cargo test -p rustfs-ecstore --lib: 3169 passed / 0 failed across
  repeated runs; cargo fmt --check and cargo clippy --lib --tests clean
- Adversarial validation (high-risk tier, all seven roles) run per
  AGENTS.md; all findings fixed or rebutted with evidence
2026-07-27 00:53:48 +08:00
houseme 0ea7f17fd7 test(ilm): cover transition budget partial records (#5305)
Co-authored-by: heihutu <heihutu@gmail.com>
2026-07-27 00:15:58 +08:00
houseme fc6dfa891a test(ilm): cover heartbeat backpressure status (#5303)
Co-authored-by: heihutu <heihutu@gmail.com>
2026-07-26 14:41:18 +00:00
houseme 994678cfcf test(ilm): cover unknown checkpoint counters (#5299)
Co-authored-by: heihutu <heihutu@gmail.com>
2026-07-26 14:33:21 +00:00
houseme 0a25d25e68 test(ilm): cover cancelled continuation resume (#5294)
Co-authored-by: heihutu <heihutu@gmail.com>
2026-07-26 13:40:36 +00:00
houseme 009dd93788 test(ilm): cover restart unknown readback (#5298)
Co-authored-by: heihutu <heihutu@gmail.com>
2026-07-26 13:15:25 +00:00
houseme 7cacd1f558 feat(ilm): persist manual transition task journals (#5296)
* feat(ilm): persist manual transition task journal

Co-Authored-By: heihutu <heihutu@gmail.com>

* fix(ilm): reconcile manual task journals on recovery

Co-Authored-By: heihutu <heihutu@gmail.com>

---------

Co-authored-by: heihutu <heihutu@gmail.com>
2026-07-26 12:38:41 +00:00
houseme 14c249c266 test(ilm): cover durable checkpoint persistence (#5288)
* test(ilm): cover durable checkpoint persistence

Co-Authored-By: heihutu <heihutu@gmail.com>

* style: format checkpoint persistence imports

Co-Authored-By: heihutu <heihutu@gmail.com>

---------

Co-authored-by: heihutu <heihutu@gmail.com>
2026-07-26 11:32:23 +00:00
houseme 5acc52b7f9 test(ilm): cover admission scope parallelism (#5293)
* test(ilm): cover cross-bucket admission scope

Co-Authored-By: heihutu <heihutu@gmail.com>

* fix(ilm): remove duplicate transition progress import

Co-Authored-By: heihutu <heihutu@gmail.com>

---------

Co-authored-by: heihutu <heihutu@gmail.com>
2026-07-26 11:30:08 +00:00
houseme 26663e0d5d test(ilm): cover durable progress checkpoint renewal (#5287)
Add regression coverage for durable manual transition progress checkpoints so page progress persists the report, queue snapshot, and renewed scope admission lease together.

Co-authored-by: heihutu <heihutu@gmail.com>
2026-07-26 10:34:08 +00:00
houseme caeaa4bf34 test(ilm): cover durable transition progress recovery (#5286)
Co-authored-by: heihutu <heihutu@gmail.com>
2026-07-26 10:06:24 +00:00
houseme a609b92b3c fix(ilm): retry transient scope admission races (#5280)
Co-authored-by: heihutu <heihutu@gmail.com>
2026-07-26 17:13:53 +08:00
houseme 058f81c61f fix(ilm): deduplicate manual transition worker results (#5278)
* fix(ilm): fail closed on unsafe manual job recovery

Mark expired manual transition jobs Unknown when recovery cannot prove queued worker outcomes are durable. Enforce ETag-guarded admission release with exact delete preconditions so stale releasers cannot remove a replacement admission, while still allowing drained cancelled jobs to terminate.

Co-Authored-By: heihutu <heihutu@gmail.com>

* style(ilm): format manual recovery imports

Apply rustfmt import ordering after merging main into the manual recovery branch.

Co-Authored-By: heihutu <heihutu@gmail.com>

* fix(ilm): deduplicate manual transition worker results

Persist per-task manual transition worker result markers before applying job counters so duplicate worker completion reports are no-ops. Reconcile persisted markers during drained-queue lease renewal and recovery to restore marker-before-record crash windows. Fail closed when persisted worker result markers are corrupt.

Co-Authored-By: heihutu <heihutu@gmail.com>

---------

Co-authored-by: heihutu <heihutu@gmail.com>
2026-07-26 08:28:33 +00:00
houseme b4e3c7117e fix(ilm): fail closed on unsafe manual recovery (#5276)
fix(ilm): fail closed on unsafe manual job recovery

Mark expired manual transition jobs Unknown when recovery cannot prove queued worker outcomes are durable. Enforce ETag-guarded admission release with exact delete preconditions so stale releasers cannot remove a replacement admission, while still allowing drained cancelled jobs to terminate.

Co-authored-by: heihutu <heihutu@gmail.com>
2026-07-26 07:36:58 +00:00
houseme 23f4683f20 test(ilm): cover queue terminal partial reports (#5277)
Cover manual transition terminal job records for queue closed and queue send timeout outcomes so backpressure summaries remain partial with the expected counters and queue snapshots.

Co-authored-by: heihutu <heihutu@gmail.com>
2026-07-26 07:21:37 +00:00
houseme 12b7f22fca test(ilm): cover stale transition admission reclaim (#5273)
Co-authored-by: heihutu <heihutu@gmail.com>
2026-07-26 06:55:36 +00:00
houseme a047bbfcfb test(ilm): cover manual transition worker failure summary (#5272)
Co-authored-by: heihutu <heihutu@gmail.com>
2026-07-26 06:45:06 +00:00
houseme 21c85481b8 test(ilm): cover unknown manual transition worker loss (#5269)
test(ilm): cover unknown state after lost worker result

Co-authored-by: heihutu <heihutu@gmail.com>
2026-07-26 13:41:26 +08:00
houseme 1397a4e7ca feat(ilm): expose lifecycle expiry scanner counters (#5262)
Co-authored-by: heihutu <heihutu@gmail.com>
2026-07-26 12:11:03 +08:00
houseme 78dd2d40d3 test(ilm): cover deterministic manual transition cancel (#5263)
Add a focused ecstore regression that exercises active manual transition cancellation through the existing cancel_check hook after scan progress has been made. The test verifies the cancelled report, dry-run counters, and opaque resume cursor without relying on wall-clock timing.

Co-authored-by: heihutu <heihutu@gmail.com>
2026-07-26 04:03:19 +00:00
houseme 342f9f94bc test(ilm): cover manual transition queue pressure status (#5265)
Co-authored-by: heihutu <heihutu@gmail.com>
2026-07-26 04:02:44 +00:00
houseme 92f72c3912 fix(ilm): normalize cancelled manual job reports (#5255)
Ensure cancelled durable manual transition jobs expose a cancelled report both when worker results drain after a cancel request and when legacy persisted records are decoded.

Co-authored-by: heihutu <heihutu@gmail.com>
2026-07-26 03:18:53 +00:00
houseme 6fa2d06731 fix(ilm): honor explicit object lock metadata (#5253)
Co-authored-by: heihutu <heihutu@gmail.com>
2026-07-26 02:57:37 +00:00
harry han 03af8e472b fix(lifecycle): stop tier free-version recovery walk-timeout loop (#5194)
The background tier free-version recovery walk pinned a hardcoded 60s
total wall-clock timeout that overrides every operator knob, so any
bucket whose healthy full walk exceeds 60s fails forever; the failed
run's duration was also subtracted from the next 60s tick, restarting
the walk immediately and pinning CPU and disk I/O.

- Drop the total wall-clock budget on the recovery walk
  (walkdir_timeout: Duration::ZERO) and inherit the operator-tunable
  drive stall budget (RUSTFS_DRIVE_WALKDIR_STALL_TIMEOUT_SECS) for
  per-call progress, so hung disks still fail fast.
- Back off failed runs from completion time: 60s doubling to a 600s
  cap, reset on success; never subtract the failed run's duration.
- Add RUSTFS_TIER_FREE_VERSION_RECOVERY_ENABLED (default true) to opt
  out of the recovery worker on deployments with no remote tiers;
  invalid values warn and fail open.

Fixes #5130

Co-authored-by: claude <claude@ehdtn.com>
2026-07-26 02:54:33 +00:00
houseme 6d8e196f36 feat(ilm): trace lifecycle expiry execution (#5250)
Co-authored-by: heihutu <heihutu@gmail.com>
2026-07-26 01:58:48 +00:00
houseme 77b5e1b64c fix(ilm): report manual transition tier failures (#5238)
Co-authored-by: heihutu <heihutu@gmail.com>
2026-07-25 18:02:37 +00:00
houseme 23a5db4012 fix(ilm): preserve lifecycle version groups (#5239)
* fix(ilm): evaluate complete version groups

Co-Authored-By: heihutu <heihutu@gmail.com>

* feat(ilm): log replication expiry blocks

Co-Authored-By: heihutu <heihutu@gmail.com>

* fix(ilm): diagnose incomplete noncurrent chains

Co-Authored-By: heihutu <heihutu@gmail.com>

* test(ilm): cover purge-pending version groups

Add regression coverage for lifecycle-only version listing so purge-pending versions stay present for ILM evaluation while the public ListObjectVersions projection remains filtered.

Refs rustfs/backlog#1500

Co-Authored-By: heihutu <heihutu@gmail.com>

* feat(ilm): log lifecycle evaluation failures

Emit structured lifecycle_evaluation_failed events when version group loading or evaluation fails during immediate and existing-object expiry scans.

Refs rustfs/backlog#1503

Co-Authored-By: heihutu <heihutu@gmail.com>

* test(ilm): cover incomplete noncurrent chains

Pin the fail-closed behavior for noncurrent expiration when successor_mod_time is missing and reuse a stable structured event name for that skip path.

Refs rustfs/backlog#1502

Co-Authored-By: heihutu <heihutu@gmail.com>

* test(ilm): cover one-day noncurrent expiry boundary

Add a runtime regression test proving NoncurrentVersionExpiration Days=1 stays inactive before expected_expiry_time and deletes exactly at the computed due boundary.

Refs rustfs/backlog#1504

Co-Authored-By: heihutu <heihutu@gmail.com>

* fix(ilm): keep transition checks after incomplete expiry

Co-Authored-By: heihutu <heihutu@gmail.com>

---------

Co-authored-by: heihutu <heihutu@gmail.com>
2026-07-25 17:42:02 +00:00
houseme 1e95e6d311 fix(ilm): harden durable transition admission (#5235)
Co-authored-by: heihutu <heihutu@gmail.com>
2026-07-25 15:46:55 +00:00
houseme 6974963e20 feat(ilm): add durable manual transition job store (#5229)
* feat(ilm): add manual transition job route contract

Refs #1479

Co-Authored-By: heihutu <heihutu@gmail.com>

* feat(ilm): add durable manual transition job store

Co-Authored-By: heihutu <heihutu@gmail.com>

* fix(ilm): harden durable transition job cancellation

Co-Authored-By: heihutu <heihutu@gmail.com>

---------

Co-authored-by: heihutu <heihutu@gmail.com>
2026-07-25 14:54:14 +00:00
houseme 2ee111ad8b feat(ilm): add durable manual transition jobs (#5223)
Refs #1479

Co-authored-by: heihutu <heihutu@gmail.com>
2026-07-25 09:12:44 +00:00
cxymds 7320d7fab2 fix(replication): make resync starts atomic (#5215) 2026-07-25 08:58:06 +08:00
cxymds 45b675c641 fix(replication): report authoritative backlog metrics (#5209) 2026-07-25 01:32:50 +08:00
cxymds d7f30fe0a2 fix(replication): persist sanitized resync errors (#5200) 2026-07-24 22:15:51 +08:00
cxymds fa235e9018 fix(s3): list multipart uploads by bucket prefix (#5195)
* fix(s3): list multipart uploads by bucket prefix

* fix(s3): preserve exact-key crash reclamation
2026-07-24 21:28:06 +08:00
houseme 7876319811 test(ilm): cover manual transition queue pressure (#5189)
Co-authored-by: heihutu <heihutu@gmail.com>
2026-07-24 11:10:04 +00:00
houseme 8ac618e6c2 feat(ilm): count already transitioned manual runs (#5177)
Co-authored-by: heihutu <heihutu@gmail.com>
2026-07-24 17:52:56 +08:00
houseme 3132637294 feat(ilm): bound manual transition duration (#5174)
* feat(ilm): bound manual transition duration

Add maxDurationSeconds handling for manual transition runs so operators can bound long scoped scans without changing the existing enqueue_only job contract.

Co-Authored-By: heihutu <heihutu@gmail.com>

* docs(ilm): document manual transition run limits

Document the enqueue_only manual transition contract, secret-handling guidance, and best-effort duration budget while pinning the new duration flag in the e2e response model.

Co-Authored-By: heihutu <heihutu@gmail.com>

---------

Co-authored-by: heihutu <heihutu@gmail.com>
2026-07-24 07:54:52 +00:00
houseme 6765aca3f9 feat(ilm): add manual transition run endpoint (#5171)
* feat(ilm): report manual transition backfill outcomes

Add scoped lifecycle transition backfill reporting for backlog #1478 and expose enqueue outcomes needed by #1479 without changing the existing scanner/compensation bool API.

Co-Authored-By: heihutu <heihutu@gmail.com>

* feat(admin): add manual transition run endpoint

Add a bounded POST /rustfs/admin/v3/ilm/transition/run API for backlog #1477 and cover the route, policy, query parsing, and partial status contract needed by #1481. Console operations from #1480 are intentionally left for a later client integration.

Co-Authored-By: heihutu <heihutu@gmail.com>

* feat(ilm): allow manual transition resume markers

Accept additive marker and versionMarker parameters on the bounded manual transition run API so clients can continue from a partial report without changing the existing default scan behavior.

Co-Authored-By: heihutu <heihutu@gmail.com>

* fix(ilm): harden manual transition partial reports

Preserve the null-version cursor contract, stop manual scans on enqueue pressure without skipping the failed object, and keep raw resume markers out of admin JSON responses.

Co-Authored-By: heihutu <heihutu@gmail.com>

* test(ilm): add manual transition e2e coverage

Co-Authored-By: heihutu <heihutu@gmail.com>

* perf(ilm): keep transition enqueue hot path direct

Co-Authored-By: heihutu <heihutu@gmail.com>

---------

Co-authored-by: heihutu <heihutu@gmail.com>
2026-07-24 15:13:22 +08:00
houseme e1e6a8b020 fix(tier): gate exact remote version consumption (#5126)
* fix(tier): gate exact remote version consumption

Reject non-empty remote tier versions before transitioned GET and remote delete backend I/O when the tier backend does not support exact version operations.

Co-Authored-By: heihutu <heihutu@gmail.com>

* test(tier): split mock remote version validation fault

Separate one-shot mock remote version validation failures from persistent unsupported-backend behavior so cleanup durability tests can still verify exact-version recovery while #1358 fail-closed gate tests keep asserting no backend I/O.

Co-Authored-By: heihutu <heihutu@gmail.com>

---------

Co-authored-by: heihutu <heihutu@gmail.com>
2026-07-22 11:52:56 +00:00