[FLINK-40657][connector-base] Release per-fetcher state in FutureCompletingBlockingQueue - #29218
Open
SAlexandru wants to merge 1 commit into
Open
SAlexandru wants to merge 1 commit into
SAlexandru wants to merge 1 commit into
Conversation
…letingBlockingQueue Fetcher indexes are never recycled, so the array of ConditionAndFlag grew without bound. Key the state by producer index instead and release it from the SplitFetcher shutdown hook. Generated-by: Claude Code (Claude Opus 5)
Collaborator
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What is the purpose of the change
FutureCompletingBlockingQueueretained a condition and wakeup flag for eachproducer ID that created queue state.
SplitFetcherManagerassigns monotonicallyincreasing IDs that are never reused, so this state could grow indefinitely as
fetchers were created and shut down.
This change releases per-producer state when its fetcher terminates, bounding
retained state by active or in-flight producers. It preserves sticky wakeups,
prevents release from stranding a producer inside
put(), and leaves thenon-full
put()path unchanged.Brief change log
ConditionAndFlagarray with a lock-guarded map.releaseProducer()to remove state after a producer permanently finishes.releaseProducer()from the existingSplitFetcherManagershutdownhook.
wakeUpPuttingThread()creating state so wakeup requests remain sticky.parked or has been signalled but has not yet reacquired the queue lock.
SplitFetcher.runningTaskwhen task execution fails.tests.
Why
SplitFetcher.runningTaskmust be cleared on failurereleaseProducer()requires the shutdown hook to be the producer's finalinteraction with the queue.
Previously,
SplitFetcher.runOnce()clearedrunningTaskonly whentask.run()returned normally. If aFetchTaskfailed while retaining a batch,the following shutdown ordering was possible:
This requires the failure to occur after
FetchTaskhas obtained or retained abatch. A
splitReader.fetch()failure that occurs before returning a batch leaveslastRecordsnull and cannot recreate queue state through this path.runOnce()now clearsrunningTaskin afinallyblock while holding thefetcher lock. Successful result processing remains atomic with that clear. A
separate completion flag distinguishes a normal
falsereturn from a thrownexception.
This makes both possible shutdown orderings safe:
shutdown()acquires the fetcher lock beforerunOnce()performs itscleanup, it may wake the still-published task.
runOnce()then clears the task,and the shutdown hook releases any queue state afterward.
runOnce()acquires the fetcher lock first, it clears the failed task.shutdown()subsequently observes no running task and performs no latewakeup.
In both cases,
releaseProducer()remains the final interaction with the queuefor that producer ID.
This exceptional path is not the normal split-churn leak reported in
FLINK-40657. It was identified
while ensuring that the new terminal-release invariant also holds during failed
task shutdown.
Failure propagation remains unchanged:
Exceptioninstances are wrapped in aRuntimeException, andErrorinstances propagate unchanged. The successfulpath performs the same single lock reacquisition as before.
Verifying this change
Tests cover:
IDs.
runningTaskafter bothExceptionandErrorfailures.Does this pull request potentially affect one of the following parts:
@Public(Evolving): yes; implementation changes only, with no API signaturechanges
is accessed only when a queue is full or explicitly woken, and the non-full
put()path remains unchangedDocumentation
Was generative AI tooling used to co-author this PR?
Generated-by: OpenAI Codex (GPT-5)
(also used Claude Code Opus 5 for review, to try it out)