[fix][offload] Fix final ledger not being offloaded for terminated topics#25955
[fix][offload] Fix final ledger not being offloaded for terminated topics#25955void-ptr974 wants to merge 1 commit into
Conversation
| } | ||
|
|
||
| long current = ledgers.lastKey(); | ||
| boolean includeLastLedger = STATE_UPDATER.get(this) == State.Terminated |
There was a problem hiding this comment.
I think this needs one more guard for the in-progress termination window. asyncTerminate() sets state = State.Terminated before the BookKeeper close callback refreshes the final LedgerInfo. If asyncOffloadPrefix() runs in that window, includeLastLedger becomes true, but the current ledger still has the active-ledger placeholder metadata (entries/size are still 0 and timestamp is not refreshed). The loop can then find no ledgers to offload and return lastConfirmedEntry.getNext(), which reports the prefix as fully offloaded even though the final ledger was never offloaded.
Could we gate includeLastLedger on the final LedgerInfo actually being closed/refreshed, or introduce a separate terminating state so manual offload does not treat an in-flight termination as completed? A regression test can block the BK close with PulsarMockBookKeeper.promiseAfter(0), call asyncTerminate(), call offloadPrefix() before releasing the close, and assert it does not report lastConfirmedEntry.getNext() without offloading the final ledger.
There was a problem hiding this comment.
Recommended fix: Gate includeLastLedger on the final ledger actually being closed (metadata refreshed). The simplest reliable signal is whether the last ledger's LedgerInfo has been populated:
LedgerInfo lastLedgerInfo = ledgers.get(current);
boolean lastLedgerClosed = lastLedgerInfo != null && lastLedgerInfo.getEntries() > 0;
boolean includeLastLedger = STATE_UPDATER.get(this) == State.Terminated
&& requestOffloadTo.compareTo(lastConfirmedEntry) >= 0
&& lastLedgerClosed;
Motivation
Terminated topics can leave their final ledger in BookKeeper even when tiered-storage offload is enabled and the ledger is eligible for offload.
Termination closes the current ledger outside the normal ledger rollover path. That means the final ledger is complete, but it is not handled like other closed ledgers for offload purposes. Its closed-ledger metadata is not refreshed during termination, automatic offload is not triggered from that path, and manual
offloadPrefix()still excludes the last ledger as if it were active.As a result, terminated topic data can be only partially offloaded, with the final ledger continuing to consume BookKeeper storage.
Fixes #25956
Modifications
Verifying this change
Ran:
Result:
BUILD SUCCESSFUL.