mirror of
https://github.com/rustfs/rustfs.git
synced 2026-08-05 12:57:42 +00:00
726f3dc185
An object transitioned to an unversioned remote tier legally records an empty remote version_id (per CLAUDE.md: a tier version of `None`/`""` means the tier bucket is unversioned, so remote GET/DELETE must omit the versionId). Two recovery paths wrongly treated that empty sentinel as an incomplete/unrecoverable record while the persist/encode and worker paths accept it, producing permanent leaks in the crash-recovery window. - tier_delete_journal::into_jentry rejected entries with an empty version_id as "incomplete", so unversioned-tier WAL entries could never be decoded during recovery: the remote object was orphaned and the journal file leaked forever. Drop the version_id emptiness check; keep the obj_name/tier_name checks. Truncated payloads are still rejected at JSON deserialization (all fields are required, non-Option, no default, with deny_unknown_fields). - tier_free_version_recovery::is_recoverable_tier_free_version required a non-empty version_id, silently filtering out free versions of unversioned-tier objects so a first enqueue failure leaked the remote object and local free version permanently. Drop the version_id check; keep free_version + name + tier checks. Both downstream paths already issue a versionless remote delete for an empty version_id, so no further changes are needed. Adds regression tests covering the empty-version_id case and the preserved guards. Co-authored-by: heihutu <heihutu@gmail.com>