rangareddy commented on code in PR #922:
URL: https://github.com/apache/incubator-xtable/pull/922#discussion_r3986538089


##########
website/docs/how-to-spark-runtime.md:
##########
@@ -28,22 +32,101 @@ Every engine dependency is `provided`, so the jar is about 
4 MB and reuses the H
 Delta libraries your cluster already has. See the 
[Downloads](/releases/downloads) page for the
 full list of releases.
 
-## Adding the sync to a Spark job
+## Prerequisites
+
+XTable converts the metadata of a table that already exists, so you need a 
source table before you
+can sync anything. If you don't have one, follow
+[Creating your first interoperable table](/docs/how-to) to create the Hudi 
table `people` under
+`file:///tmp/hudi-dataset`. Every example on this page syncs that table.
+
+You also need a Spark 3.4.x or 3.5.x installation with `$SPARK_HOME` set. See

Review Comment:
   You were right, and it was worse than the classpath. I set up Spark 3.4.2 
(matching
   `spark.version` at the tag) and JDK 11, and ran the page end to end against 
the released jar.
   
   Added a **Getting the engine libraries** section that resolves the 
`provided` engines from the
   published POM, the recipe `demo/spark-runtime/README.md` already uses:
   
   ```
   mvn -q -f xtable-spark-runtime_2.12-0.4.0-incubating.pom 
dependency:build-classpath \
     -DincludeScope=provided -Dmdep.outputFile=engine-classpath-raw.txt
   ```
   
   filtered to 21 engine jars (`hudi-spark3.4-bundle 0.14.0`, 
`hudi-java-client`,
   `hudi-client-common`, `hudi-timeline-service`, 
`iceberg-core/-api/-common/-bundled-guava 1.9.2`,
   `delta-core 2.4.0`, `delta-storage`, `delta-kernel-api/-defaults 4.0.0`, 
`avro 1.12.0`, the seven
   `parquet-* 1.15.2`, `jol-core 0.16`), then passed to every `spark-submit` on 
the page through
   `spark.driver.extraClassPath` and `spark.executor.extraClassPath`, as
   `ITXTableSparkRuntimeBundle` does. A note records why it has to be a flat 
classpath rather than
   `--packages` or `--jars`.
   
   Running it that way, the documented submit now works:
   
   ```
   INFO XTableSparkSync: Starting XTable sync for people 
(file:///tmp/hudi-dataset/people)
   INFO XTableSparkSync: Completed XTable sync for people
   EXIT=0
   ```
   
   and Hudi, Delta and Iceberg all read back the same six rows.
   
   One more thing the run exposed, which the classpath alone does not fix: the 
Quickstart's shell now
   uses `hudi-spark3.4-bundle_2.12:1.2.0`, which writes Hudi table version 9. 
`0.4.0-incubating` is
   built against Hudi `0.14.0`, so the sync fails before reading anything:
   
   ```
   java.lang.IllegalArgumentException
     at 
org.apache.hudi.common.util.ValidationUtils.checkArgument(ValidationUtils.java:33)
     at 
org.apache.hudi.common.table.timeline.versioning.TimelineLayoutVersion.<init>(TimelineLayoutVersion.java:40)
     at 
org.apache.xtable.hudi.HudiConversionSourceProvider.getConversionSourceInstance(HudiConversionSourceProvider.java:41)
   ```
   
   Creating the table with `0.14.0` instead makes it pass. Added a caution to 
Prerequisites. The
   underlying cause is #904 bumping the Quickstart to match `main` 
(`hudi.version` `1.2.0`) while the
   site documents the released `0.4.0-incubating` (`0.14.0`); I can file that 
separately.



##########
website/docs/how-to-spark-runtime.md:
##########
@@ -28,22 +32,101 @@ Every engine dependency is `provided`, so the jar is about 
4 MB and reuses the H
 Delta libraries your cluster already has. See the 
[Downloads](/releases/downloads) page for the
 full list of releases.
 
-## Adding the sync to a Spark job
+## Prerequisites
+
+XTable converts the metadata of a table that already exists, so you need a 
source table before you
+can sync anything. If you don't have one, follow
+[Creating your first interoperable table](/docs/how-to) to create the Hudi 
table `people` under
+`file:///tmp/hudi-dataset`. Every example on this page syncs that table.
+
+You also need a Spark 3.4.x or 3.5.x installation with `$SPARK_HOME` set. See
+[Spark version support](#spark-version-support) for what each line provides.
 
-This is what the jar is for. Your job already writes a table in one format, 
and you want that same
-table to be interoperable with the others as soon as the write finishes.
+## Running a sync as its own job
+
+The jar ships a `spark-submit` entry point, 
`org.apache.xtable.spark.XTableSparkSync`. Pass the jar
+as the application jar rather than with `--jars`. It runs in one of two modes.
 
-Add the jar to the `spark-submit` you already use, alongside your application 
jar:
+### Syncing a single table
+
+Describe the table with command line options. This is the shortest path from a 
source table to an
+interoperable one:
 
 ```shell md title="shell"
 $SPARK_HOME/bin/spark-submit \
-  --jars xtable-spark-runtime_2.12-0.4.0-incubating.jar \
-  --class com.example.OrdersJob \
-  orders-job.jar
+  --class org.apache.xtable.spark.XTableSparkSync \
+  --master 'local[*]' \
+  xtable-spark-runtime_2.12-0.4.0-incubating.jar \
+  --basepath file:///tmp/hudi-dataset/people \
+  --sourceformat HUDI \
+  --targets ICEBERG,DELTA

Review Comment:
   Confirmed and fixed, and I measured it both ways rather than reasoning about 
it.
   `HudiSourceConfig.parsePartitionFieldSpecs` returns 
`Collections.emptyList()` for a null or empty
   spec, and on the Quickstart's `people` table that shows up as:
   
   | | Iceberg `default-spec-id` | Delta `partitionColumns` |
   | --- | --- | --- |
   | without the flag | `0` (fields `[]`) | `[]` |
   | with `city:VALUE` | `1` (identity transform on `city`) | `['city']` |
   
   So the targets really were being created unpartitioned. The single-table 
command now passes
   `--partitionspec city:VALUE`, both `TableSyncSpec` examples pass 
`.partitionSpec("city:VALUE")`,
   and the `--datasetconfig` entry carries `partitionSpec: city:VALUE`. I also 
changed the
   option-table example from `level:VALUE` to `city:VALUE` so the page is 
consistent throughout.



##########
website/docs/how-to-spark-runtime.md:
##########
@@ -28,22 +32,101 @@ Every engine dependency is `provided`, so the jar is about 
4 MB and reuses the H
 Delta libraries your cluster already has. See the 
[Downloads](/releases/downloads) page for the
 full list of releases.
 
-## Adding the sync to a Spark job
+## Prerequisites
+
+XTable converts the metadata of a table that already exists, so you need a 
source table before you
+can sync anything. If you don't have one, follow
+[Creating your first interoperable table](/docs/how-to) to create the Hudi 
table `people` under
+`file:///tmp/hudi-dataset`. Every example on this page syncs that table.
+
+You also need a Spark 3.4.x or 3.5.x installation with `$SPARK_HOME` set. See
+[Spark version support](#spark-version-support) for what each line provides.
 
-This is what the jar is for. Your job already writes a table in one format, 
and you want that same
-table to be interoperable with the others as soon as the write finishes.
+## Running a sync as its own job
+
+The jar ships a `spark-submit` entry point, 
`org.apache.xtable.spark.XTableSparkSync`. Pass the jar
+as the application jar rather than with `--jars`. It runs in one of two modes.
 
-Add the jar to the `spark-submit` you already use, alongside your application 
jar:
+### Syncing a single table
+
+Describe the table with command line options. This is the shortest path from a 
source table to an
+interoperable one:
 
 ```shell md title="shell"
 $SPARK_HOME/bin/spark-submit \
-  --jars xtable-spark-runtime_2.12-0.4.0-incubating.jar \
-  --class com.example.OrdersJob \
-  orders-job.jar
+  --class org.apache.xtable.spark.XTableSparkSync \
+  --master 'local[*]' \
+  xtable-spark-runtime_2.12-0.4.0-incubating.jar \
+  --basepath file:///tmp/hudi-dataset/people \
+  --sourceformat HUDI \
+  --targets ICEBERG,DELTA
 ```
 
-Then call `XTableSyncService` after your write. You describe the table with a 
`TableSyncSpec` and
-hand it the session's Hadoop configuration:
+After this finishes, `/tmp/hudi-dataset/people` carries Iceberg and Delta 
metadata next to the Hudi
+data files, and all three formats read the same rows.
+
+### Syncing several tables from a config file
+
+To sync more than one table in a single submit, list them in a YAML file and 
pass
+`--datasetconfig`. It takes the same config that `RunSync` uses, so an 
existing file works
+unchanged:
+
+```yaml md title="my_config.yaml"
+sourceFormat: HUDI
+targetFormats:
+  - DELTA
+  - ICEBERG
+datasets:
+  -
+    tableBasePath: file:///tmp/hudi-dataset/people
+    tableName: people
+  -
+    tableBasePath: file:///tmp/hudi-dataset/orders

Review Comment:
   Confirmed by running it. With `people` (which the prerequisite creates) plus 
`orders` (which it
   does not):
   
   ```
   INFO  XTableSparkSync: Completed XTable sync for people
   ERROR XTableSparkSync: XTable sync failed for orders 
(file:///tmp/hudi-dataset/orders)
   Exception in thread "main" java.lang.IllegalStateException: 1 of 2 table 
sync(s) failed
   EXIT=1
   ```
   
   so the example as written could not succeed. The runnable config now lists 
only `people` and exits
   0. The multi-table shape is still shown, but as a separate snippet clearly 
labelled as a second
   `datasets` entry rather than as part of the file you run, and the text now 
states the behaviour:
   
   > Add one entry per table. Every entry has to point at a table that already 
exists:
   > `XTableSparkSync` logs each table that fails, carries on with the rest, 
then exits nonzero, so
   > one missing path fails the whole submit.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to