[fix][ml] Track all pending read callbacks for timeouts#26081
[fix][ml] Track all pending read callbacks for timeouts#26081Technoboy- wants to merge 2 commits into
Conversation
|
I think the current priority-queue approach can still retain too much state after reads complete. The wrapper is added before A bucketed timeout structure may be a better fit here: group reads by timeout bucket, and keep an inner map from // bucketId -> (readOpCount -> callback wrapper)
private final ConcurrentLongHashMap<ConcurrentLongHashMap<ReadEntryCallbackWrapper>> readTimeoutBuckets =
ConcurrentLongHashMap.<ConcurrentLongHashMap<ReadEntryCallbackWrapper>>newBuilder().build();
static final class ReadEntryCallbackWrapper implements ReadEntryCallback, ReadEntriesCallback {
volatile ConcurrentLongHashMap<ReadEntryCallbackWrapper> timeoutBucket;
} |
Motivation
When managed ledger read-entry timeout is enabled,
ManagedLedgerImplonly keeps the most recentReadEntryCallbackWrapperinlastReadCallback. If multiple reads are pending and an older read hangs, a newer read can overwrite that callback, so the older operation is no longer checked bycheckReadTimeout().That can leave a cursor read pending indefinitely and block follow-up cursor operations such as reset/mark-delete progress.
Modifications
lastReadCallbackwith a pending-read callback map keyed by read operation id.Verifying this change
./gradlew :managed-ledger:test --tests org.apache.bookkeeper.mledger.impl.ManagedLedgerTest.testManagedLedgerWithReadEntryTimeOut --tests org.apache.bookkeeper.mledger.impl.ManagedLedgerTest.testManagedLedgerWithConcurrentReadEntryTimeOut