fix(ilm): preserve duplicate metadata and reject unapplied purges

Merge lock and tag revisions for duplicate versions before all-pool
lifecycle evaluation using the existing metadata reconciliation rules.

Distinguish ordinary lifecycle refusal from object absence and clear
rejected batch replication state so a late policy withdrawal cannot
schedule a purge. Preserve restored-copy cleanup and real absence.

Cover single and batch protections, legitimate metadata removals, and
actual replication queue and HTTP target behavior.

Signed-off-by: Feng Ruohang <rh@vonng.com>
This commit is contained in:
Feng Ruohang
2026-11-03 22:38:21 +08:00
parent 3a1e132f16
commit ba0b59d0b2
6 changed files with 416 additions and 29 deletions
+9
View File
@@ -2045,6 +2045,9 @@ func (er erasureObjects) DeleteObject(ctx context.Context, bucket, object string
// expiration attempted on a bucket with no lifecycle
// rules shall be rejected.
if lc == nil && opts.Expiration.Expire {
if !opts.Transition.ExpireRestored {
return objInfo, errLifecycleNotApplicable
}
if opts.VersionID != "" {
return objInfo, VersionNotFound{
Bucket: bucket,
@@ -2089,6 +2092,9 @@ func (er erasureObjects) DeleteObject(ctx context.Context, bucket, object string
isErr = true
}
if isErr {
if !opts.Transition.ExpireRestored {
return goi, errLifecycleNotApplicable
}
if goi.VersionID != "" {
return goi, VersionNotFound{
Bucket: bucket,
@@ -2162,6 +2168,9 @@ func (er erasureObjects) DeleteObject(ctx context.Context, bucket, object string
isErr = true
}
if isErr {
if !opts.Transition.ExpireRestored {
return goi, errLifecycleNotApplicable
}
if goi.VersionID != "" {
return goi, VersionNotFound{
Bucket: bucket,