timothyw553 opened a new pull request, #17599:
URL: https://github.com/apache/iceberg/pull/17599

   ## Problem
   
   An Iceberg Spark streaming checkpoint stores a snapshot ID and a position 
inside that snapshot. If table metadata is replaced with an independent 
snapshot history, the old snapshot ID is no longer on the current lineage and 
the stream cannot restart.
   
   For example:
   
   ```text
   Old history:          O1 -> O2 -> O3 -> O4
                              ^
                              checkpoint
   
   Replacement history: N1 -> K -> A1 -> A2
   ```
   
   Restarting against the replacement history fails because `O2` cannot be 
resolved.
   
   ## What this draft proves
   
   This is a test-only proof of concept, not a production recovery command or 
service.
   
   The tests construct a separate, read-only recovery table:
   
   ```text
   O1 -> O2 -> O3 -> O4 -> K* -> A1
                              ^
                          REPLACE
   ```
   
   The recovery table keeps the old snapshots and manifest lists unchanged. 
`K*` keeps the final replacement snapshot ID and v3 manifests, but points to 
`O4` and uses the `REPLACE` operation. Spark therefore finishes the partially 
consumed old snapshot, reads later old appends, skips `K*`, and reaches the 
real post-replacement snapshot `A1`.
   
   After Spark commits `A1`, the same checkpoint restarts against the original 
live table. Because `A1` exists in both histories, streaming continues from the 
live descendants without replaying earlier rows.
   
   The tests cover both an in-process catalog and an HTTP REST catalog with 
catalog caching enabled. They also verify that:
   
   - a normal restart first fails with the missing-snapshot error;
   - old manifest lists remain byte-for-byte unchanged;
   - v3 row IDs remain unique and contiguous;
   - the bridge emits no rows;
   - a live source write can commit while recovery is active;
   - the handoff reads every row exactly once across another restart.
   
   The REST fixture serves metadata that is already registered in the test 
catalog. It does not test production REST registration, authentication, or 
credential vending.
   
   ## Current assumptions
   
   The fixture is intentionally limited to an append-only, unpartitioned table 
without delete files. A production implementation must fail safely unless the 
old terminal snapshot and final replacement snapshot describe the same physical 
table state. It must also handle metadata retention, schema and partition 
evolution, delete files, encryption, authentication, and temporary 
recovery-table lifecycle.
   
   The test demonstrates a handoff between two table identifiers with the same 
source provider, schema, and source position. It does not establish a general 
Spark compatibility contract for arbitrary source changes.
   
   ## Tests
   
   ```text
   ./gradlew --offline -DsparkVersions=4.0 \
     :iceberg-spark:iceberg-spark-4.0_2.13:spotlessJavaCheck \
     :iceberg-spark:iceberg-spark-4.0_2.13:test \
     --tests org.apache.iceberg.spark.source.TestStreamingSnapshotRecovery \
     --no-daemon
   ```
   
   Result: 2 tests passed and formatting passed.
   
   ## AI assistance
   
   AI assistance was used to scaffold and pressure-test this prototype. I 
reviewed the complete diff, corrected the snapshot-summary and row-ID 
validation, and ran the focused tests and formatting check. The production 
limitations and source-handoff compatibility noted above remain open design 
questions.
   


-- 
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]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to