Skip to content

[FLINK-40170][table-planner] Infer update-producing changelog mode for early-fire interval join - #3

Draft
weiqingy wants to merge 33 commits into
FLINK-36953-pr2-targetfrom
FLINK-36953-pr3-changelog
Draft

[FLINK-40170][table-planner] Infer update-producing changelog mode for early-fire interval join#3
weiqingy wants to merge 33 commits into
FLINK-36953-pr2-targetfrom
FLINK-36953-pr3-changelog

Conversation

@weiqingy

@weiqingy weiqingy commented Jul 18, 2026

Copy link
Copy Markdown
Owner

Part of the FLIP-497 stack under umbrella FLINK-36953. Stacked on PR-2. Landing order: PR-1a → PR-1b → PR-2 → PR-3 (this) → PR-4 → PR-5 → PR-6 → PR-7.

What is the purpose of the change

When EARLY_FIRE is set on an outer interval join, the join emits a speculative null-padded row and later corrects it — an updating result. This PR makes the planner infer that update-producing changelog mode and reject an insert-only downstream with a tailored error. Inner joins and negative-window joins remain append-only.

Brief change log

  • Split an interval-join arm in FlinkChangelogModeInferenceProgram (SatisfyModifyKindSetTraitVisitor): early-fire + outer join + non-negative window ⇒ INSERT,UPDATE; otherwise INSERT_ONLY.
  • Add a tailored TableException when such an updating early-fire interval join feeds an insert-only sink.
  • StreamPhysicalIntervalJoin forwards the trait.

Verifying this change

This change added tests and can be verified as follows:

  • Added IntervalJoinTest plan/changelog cases: early-fire outer join is update-producing; insert-only-downstream throws the tailored error; negative-window + early-fire and inner + early-fire stay INSERT_ONLY.

Does this pull request potentially affect one of the following parts:

  • Dependencies (does it add or upgrade a dependency): no
  • The public API, i.e., is any changed class annotated with @Public(Evolving): no
  • The serializers: no
  • The runtime per-record code paths (performance sensitive): no
  • Anything that affects deployment or recovery: no
  • The S3 file system connector: no

Documentation

  • Does this pull request introduce a new feature? no (planner inference for the FLIP-497 hint)
  • If yes, how is the feature documented? not applicable

Was generative AI tooling used to co-author this PR?
  • Yes (please specify the tool below)

Generated-by: Claude Code (Anthropic)

@weiqingy
weiqingy force-pushed the FLINK-36953-pr3-changelog branch from f6163da to 16ae7d2 Compare July 18, 2026 22:12
@weiqingy
weiqingy force-pushed the FLINK-36953-pr2-target branch from 0b76a4b to dc1e210 Compare July 18, 2026 22:12
@weiqingy weiqingy changed the title [FLINK-36953][table-planner] Infer update-producing changelog mode for early-fire interval join [FLINK-40170][table-planner] Infer update-producing changelog mode for early-fire interval join Jul 18, 2026
@weiqingy
weiqingy force-pushed the FLINK-36953-pr3-changelog branch from 16ae7d2 to 17d607b Compare July 21, 2026 02:17
@weiqingy
weiqingy force-pushed the FLINK-36953-pr2-target branch 2 times, most recently from 2d8840b to 8000ad1 Compare July 21, 2026 04:43
@weiqingy
weiqingy force-pushed the FLINK-36953-pr3-changelog branch from 17d607b to 9dbe90d Compare July 21, 2026 04:43
@weiqingy
weiqingy force-pushed the FLINK-36953-pr2-target branch 2 times, most recently from 0ef163a to 3b14d56 Compare August 2, 2026 22:18
@weiqingy
weiqingy force-pushed the FLINK-36953-pr3-changelog branch from 9dbe90d to 8f7448f Compare August 2, 2026 22:42
auroflow and others added 20 commits August 3, 2026 10:53
…ration reference

ConfigurationOptionLocator discovers ConfigOptions from a hard-coded list of
packages and reads each with Files.newDirectoryStream, which does not recurse
into sub-packages. Options outside that list are dropped from the generated
configuration reference without any error, and ConfigOptionsDocsCompletenessITCase
cannot detect it because it derives its expectations from the same list.

All seven state.backend.rocksdb.manual-compaction.* options were affected: they
carry @Documentation.Section(EXPERT_ROCKSDB) but live in
org.apache.flink.state.rocksdb.sstmerge, a sub-package of a searched package, so
the feature shipped in 1.20 had no documented configuration.

Add a location for the sub-package and regenerate the affected tables.
RocksDBManualCompactionOptions needs a stability annotation because becoming
discoverable also subjects it to ConfigOptionsDocGenerator#verifyClassAnnotation;
@PublicEvolving matches RocksDBOptions and RocksDBConfigurableOptions in the same
module. Two option descriptions were missing a space between concatenated
sentences, which is now user-visible, so fix those too.

Add ConfigurationOptionLocatorTest to prevent recurrence: it scans the source
tree and fails when a @Documentation.Section option sits in a package the
locator does not search. Repo-wide it needs no exclusions.

Generated-by: Claude Code (claude-opus-5)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…th a leading None (apache#28819)

_infer_type inferred a list's element type from obj[0] rather than the
first non-None element the loop scans for, so a leading None collapsed
the array element type to NULL. Infer from the scanned element v
instead, matching the dict branch above.
`BinaryVariantUtil` decoded string values and object field names with `new String(byte[], int, int)`, which uses the JVM default charset, while `BinaryVariantInternalBuilder` writes both as UTF-8. The two only agree on Java 18+, where JEP 400 made UTF-8 the default charset. On Java 11 and 17 a non-UTF-8 platform charset corrupts any non-ASCII text.

Corrupted field names are the worse half of this. `getField(name)` silently returns null, and `getFieldNames()` and `toJson()` return mangled keys.

Both call sites now pass `StandardCharsets.UTF_8` explicitly, matching Spark's `VariantUtil`.
gaborgsomogyi and others added 13 commits August 5, 2026 17:11
…utable via MDC propagation and thread names

Source split-fetcher threads previously carried no job identity, so on a shared TaskManager their logs and thread dumps could not be traced back to the job that owned them. This adds the job id into each fetcher pool thread's MDC and appends a truncated job-name/job-id suffix to the fetcher thread name, making both logs and thread dumps attributable per job.
ThreadMXBean.dumpAllThreads(true, true) enters a single JVM-wide
safepoint to collect monitor/synchronizer state; on busy JVMs the pause
can exceed heartbeat.timeout and cause unnecessary TaskManager failover.

- Introduce ThreadDumpMode {LITE, FULL}: LITE = dumpAllThreads(false,
  false), FULL preserves today's (true, true) behavior. Exposed via an
  optional query parameter `?mode=lite|full` on the JM/TM thread-dump
  endpoints.
- Add config cluster.thread-dump.default-mode (default FULL to preserve
  upgrade behavior; LITE recommended for large clusters).
- Add a Lite/Full toggle to both Web UI thread-dump pages; selecting a
  mode does not auto-fetch, the download link tracks the selection.
The decrement in acquire() was generalized from a constant 1 to
numberOfEvents as part of FLIP-535, but the gate was left closing only at
capacityLeft <= 0, so a cycle can admit more events than capacityPerCycle.
The gate is now closed unless the capacity left covers the whole request.
…ilteringHandler

onRecoveredStateBuffer() takes over the buffer before anything can fail, so the
compensating loop in the catch block must skip the buffer it failed on.
Generated-by: Claude Code (claude-opus-4-8)
…n Batch Mode (apache#28500)

Co-authored-by: Yuepeng Pan <hipanyuepeng@gmail.com>
…fire interval join

With the EARLY_FIRE hint, an outer interval join speculatively emits a padded
unmatched row after the delay and corrects it when a match later arrives, so it
no longer produces insert-only changes. Teach FlinkChangelogModeInferenceProgram
to reflect this.

Split StreamPhysicalIntervalJoin into its own ModifyKindSet arm: its children
still consume insert-only, but the node provides INSERT and, when the hint makes
it update-producing, UPDATE. A new produceEarlyFireUpdates accessor gates that on
the hint being set, the join being outer, and a non-negative window span, so the
hint stays inert for inner joins and negative-window joins (which only ever emit
inserts). The interval join keeps its place in the UpdateKind and DeleteKind arms.

When such a join feeds an insert-only downstream, planning fails with a tailored
error that names the hint, rather than the generic "doesn't support consuming
update changes" message. Runtime behavior is unchanged; the operator still
ignores the hint.

The compiled-plan round-trip test's sink now declares sink-insert-only=false:
its early-fire outer join produces updates under the new inference, so the
previously insert-only sink no longer accepts the pipeline.
@weiqingy
weiqingy force-pushed the FLINK-36953-pr3-changelog branch from 8f7448f to 4f6ef24 Compare August 8, 2026 04:27
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.