Skip to content

[flink] Avoid having QueryFileMonitor always busy - #9291

Open
thswlsqls wants to merge 2 commits into
apache:masterfrom
thswlsqls:fix/query-file-monitor-availability
Open

[flink] Avoid having QueryFileMonitor always busy#9291
thswlsqls wants to merge 2 commits into
apache:masterfrom
thswlsqls:fix/query-file-monitor-availability

Conversation

@thswlsqls

Copy link
Copy Markdown
Contributor

Purpose

fix #9290

QueryFileMonitor.Reader.pollNext() sleeps on the mailbox thread and returns MORE_AVAILABLE when a scan finds nothing, and it never overrides isAvailable(), so Flink always sees a completed future. The source is measured as 100% busy and shown as a permanent bottleneck in the Web UI, and checkpoint triggering waits for the sleeping mailbox.

Await the discovery interval asynchronously and return NOTHING_AVAILABLE instead, so idle polls are measured as idle. This is the change #6396 made to MonitorSource, applied to the remaining instance of that pattern.

Tests

  • Added QueryFileMonitorTest#testPollWithoutNewFilesReportsNothingAvailable and #testPollWithNewFilesReportsMoreAvailable; no test covered this reader before. The first fails on master with expected: NOTHING_AVAILABLE.
  • mvn -pl paimon-flink/paimon-flink-common -Pflink1 clean install: 2303 tests, 0 failures, 0 errors. Both new tests also pass with -Pflink2.

The reader slept on the mailbox thread and reported MORE_AVAILABLE while
idle, so the source task was always measured as busy. Complete the sleep
asynchronously and report NOTHING_AVAILABLE instead, matching MonitorSource.

Generated-by: Claude Code
assertThat(status).isEqualTo(InputStatus.NOTHING_AVAILABLE);
assertThat(output.getEmittedRecords()).isEmpty();
// the poll must not block the mailbox thread for the discovery interval
assertThat(elapsed).isLessThan(DISCOVERY_INTERVAL_MS / 3);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: this sleep can introduce flakyness under heavy CI contention, we may want to manually control this

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(non blocking)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ArnavBalyan Thanks — you're right, dropped that assertion.

The elapsed-time bound was the only wall-clock dependency in the test: NOTHING_AVAILABLE plus an isAvailable() future that isn't done yet already prove the poll didn't block for the discovery interval, so removing it loses no coverage. QueryFileMonitorTest still passes.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for update @thswlsqls LGTM

The test measured how long pollNext took and asserted it stayed under a
third of the discovery interval. That bound depends on wall-clock timing:
pollNext runs a table scan, so under heavy CI contention it can exceed the
bound even when the reader behaves correctly.

Returning NOTHING_AVAILABLE together with an isAvailable() future that is
not yet done already proves the poll did not block for the discovery
interval, so dropping the timing assertion loses no coverage.

Generated-by: Claude Code

@JingsongLi JingsongLi left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The mailbox-facing availability change is correct, but the delay should not occupy the JVM-wide common pool.

if (isEmpty) {
Thread.sleep(monitorInterval);
availableFuture =
CompletableFuture.runAsync(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] Do not block the shared common pool for the discovery interval

CompletableFuture.runAsync uses ForkJoinPool.commonPool(), and this task occupies one of its workers in Thread.sleep for the full interval. When a TaskManager hosts more idle QueryFileMonitor readers than the common-pool parallelism, the remaining futures stay queued and do not even start their delay: later readers can wake after roughly 2×, 3×, ... the configured discovery interval, while unrelated common-pool work is starved as well. close() also leaves a long sleep running. Please use a scheduled/timer executor that does not block a worker, own/cancel it with the reader lifecycle, and cover multiple concurrent waits with a controllable scheduler.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] QueryFileMonitor source is always measured as busy

3 participants