[836] Introduce xtable-spark-runtime for in-job metadata sync#837
Closed
vinishjail97 wants to merge 1 commit into
Closed
[836] Introduce xtable-spark-runtime for in-job metadata sync#837vinishjail97 wants to merge 1 commit into
vinishjail97 wants to merge 1 commit into
Conversation
Add a new xtable-spark-runtime module and RFC-3. A driver-side QueryExecutionListener runs an incremental ConversionController.sync after a successful write to a configured source table, activated via spark.xtable.* config only (path- and name-based table selection). The listener is stateless and synchronous: the sync watermark already lives in the target's TableSyncMetadata, and callbacks are delivered on Spark's single-threaded LiveListenerBus, so single-flight falls out for free and the sync runs inline on the callback. Per-table failures are caught (as Throwable) so a listener never destabilizes the bus. - XTableSparkConfig: parse spark.xtable.* into TableSyncSpec - XTableSyncService: build ConversionConfig(INCREMENTAL) + run sync - PlanTargetResolver: best-effort write-path extraction from the plan - XTableSyncListener: trigger sync on a recognized write matching a configured table - Unit tests + ITXTableSyncListener (embedded local[*], Hudi -> Delta/Iceberg) Spark/Hadoop are provided; thin shaded bundle, streaming listener, and CALL xtable.sync(...) are follow-ups. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Contributor
Author
|
Splitting the PR into packaging and listener for easier validation. |
This was referenced Jul 7, 2026
Contributor
Author
|
Split into two stacked PRs for easier review, per feedback:
Closing this combined PR in favor of those. |
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 pull request
Implements the first slice of #836 (RFC-3): a new
xtable-spark-runtimemodule that runs incremental XTable metadata sync inside an existing Spark job, activated by config only — no separateRunSyncprocess, no user code change.A driver-side
QueryExecutionListenerrunsConversionController.sync(...)after a successful write to a configured source table:Design details are in
rfc/rfc-3/rfc-3.md.Brief change log
xtable-spark-runtime_${scala.binary.version}(Spark/Hadoopprovided), registered in the parentpom.xml.XTableSparkConfig— parsespark.xtable.*intoTableSyncSpec(path- and name-based table selection).XTableSyncService— buildConversionConfig(INCREMENTAL)and runConversionController.sync(...).PlanTargetResolver— best-effort extraction of the written path from the analyzed plan (isolated Spark-internal dependence).XTableSyncListener— stateless, synchronous: on a recognized write matching a configured table, run the sync inline on the callback. Single-flight falls out for free (single-threadedLiveListenerBus); per-table failures are caught asThrowableso a listener never destabilizes the bus.Design notes
TableSyncMetadata, andINCREMENTALauto-falls back to a full snapshot when unsafe, so there is nothing to track client-side.QueryExecutionListenercallbacks are delivered asynchronously by Spark offSparkListenerSQLExecutionEnd, so a listener can't blockwrite(); running inline is the simplest correct choice and completes before JVM exit via the bus drain onSparkContext.stop(). Async / "when to trigger" is intentionally left to the user's DAG as an opt-in follow-up.Non-goals (follow-ups)
org.apache.xtable.shaded.*).StreamingQueryListenervariant,CALL xtable.sync(...)procedure, async execution opt-in.Verify this pull request
This change added tests and can be verified as follows:
TestXTableSparkConfig,TestPlanTargetResolver,TestXTableSyncListener(path matching).ITXTableSyncListener— embeddedlocal[*]; a real Hudi datasource write triggers the listener and syncs to Delta + Iceberg in the same JVM, asserting theidsets match across all three formats.Closes #836 (first slice).
🤖 Generated with Claude Code