fix(ilm): recheck read expiry for the resolved version

Recheck only local ordinary-delete candidates that need an all-pool lifecycle decision. Match UUID/null identity to the version actually read and queue its global metadata and event; retain a successful read on recheck failure, absence, or refusal.

Keep GET reader cleanup, authorization, proxy reads, single-pool reads, restored-copy cleanup, and expiry response headers on their existing paths. Cover signed GET/HEAD, queue contents, metadata faults, missing matches, no-scan boundaries, and reader-lock release.

Signed-off-by: Feng Ruohang <rh@vonng.com>
This commit is contained in:
Feng Ruohang
2026-11-03 21:07:55 +08:00
parent 3a1e132f16
commit 65c59dd860
3 changed files with 421 additions and 2 deletions
+4 -2
View File
@@ -492,9 +492,10 @@ func (api objectAPIHandlers) getObjectHandler(ctx context.Context, objectAPI Obj
return
}
event := evalActionFromLifecycle(ctx, *lc, rcfg, replcfg, objInfo)
expiryInfo, event := recheckReadExpiry(ctx, objectAPI, objInfo, event)
if event.Action.Delete() {
// apply whatever the expiry rule is.
applyExpiryRule(event, lcEventSrc_s3GetObject, objInfo)
applyExpiryRule(event, lcEventSrc_s3GetObject, expiryInfo)
if !event.Action.DeleteRestored() {
// If the ILM action is not on restored object return error.
writeErrorResponse(ctx, w, errorCodes.ToAPIErr(ErrNoSuchKey), r.URL)
@@ -972,9 +973,10 @@ func (api objectAPIHandlers) headObjectHandler(ctx context.Context, objectAPI Ob
return
}
event := evalActionFromLifecycle(ctx, *lc, rcfg, replcfg, objInfo)
expiryInfo, event := recheckReadExpiry(ctx, objectAPI, objInfo, event)
if event.Action.Delete() {
// apply whatever the expiry rule is.
applyExpiryRule(event, lcEventSrc_s3HeadObject, objInfo)
applyExpiryRule(event, lcEventSrc_s3HeadObject, expiryInfo)
if !event.Action.DeleteRestored() {
// If the ILM action is not on restored object return error.
writeErrorResponseHeadersOnly(w, errorCodes.ToAPIErr(ErrNoSuchKey))