Skip to content

Introduce xtable-spark-runtime: thin, relocated Spark bundle for in-job metadata sync #836

Description

@vinishjail97

Motivation

XTable's modules are published to Maven, so a user can depend on
xtable-core and assemble their own runtime today. But there is no
maintained, thin, drop-in artifact — everyone re-solves the same
shading/classpath problem, or uses xtable-utilities, an unshaded ~1GB fat
jar that isn't practical to add to a Spark job and requires running a
separate sync process with multiple config files.

XTable conversion is metadata-only and lightweight, so the common case —
"I already write this table with Spark, keep it in sync in other formats" —
should be a one-dependency, config-only addition to an existing pipeline.

Proposal

A new module xtable-spark-runtime producing a thin, relocated bundle that:

  • is added via --jars / --packages,
  • is activated through config only (no user code change),
  • runs incremental ConversionController.sync(...) on the driver after each
    successful write to a source table.

Usage

spark-submit --packages org.apache.xtable:xtable-spark-runtime_2.12:<ver> \
  --conf spark.sql.queryExecutionListeners=org.apache.xtable.spark.XTableSyncListener \
  --conf spark.xtable.tables=/warehouse/db/orders \
  --conf spark.xtable.orders.sourceFormat=HUDI \
  --conf spark.xtable.orders.targets=ICEBERG,DELTA

Packaging (Hudi/Iceberg model)

  • Spark / Hadoop → provided (on the cluster, not bundled).
  • Curated dependency allowlist (no bundling of the full transitive closure).
  • Relocate guava / jackson / protobuf / avro / commons under
    org.apache.xtable.shaded.* to avoid classpath clashes with the cluster.
  • Target size: tens of MB.

Design

  • XTableSyncListener implements QueryExecutionListener (batch) and a
    StreamingQueryListener variant.
  • On write-success: resolve target table(s) from spark.xtable.*, submit an
    incremental sync to a debounced, single-flight-per-table driver executor.
  • Sync is idempotent + incremental, so a missed trigger self-heals on the
    next commit.

Scope / non-goals

  • No data rewriting — metadata translation only.
  • Does not replace the standalone CLI (RunSync); complements it.

Open questions

  • Table selection: config-declared (proposed) vs. plan-inspection auto-detect.
  • Batch jobs: async (needs shutdown-hook drain) vs. blocking.
  • Also ship a CALL xtable.sync(...) SQL procedure in the same jar?

Tasks

  • Scaffold xtable-spark-runtime module (pom: provided engines, allowlist, relocations).
  • Implement XTableSyncListener + spark.xtable.* config parsing.
  • Debounced driver executor + shutdown drain.
  • ITXTableSyncListener (embedded local[*], Hudi→Delta/Iceberg).
  • spark-shell smoke test + README section.
  • (optional) CALL xtable.sync(...) procedure.

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions