[Java] Preserve BigQuery failed rows across retries - #39999
Draft
bvolpato wants to merge 3 commits into
Draft
Conversation
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.
Consecutive BigQuery Storage Write API row errors can duplicate a previously rejected record in Beam's failure output and omit the newly rejected record. After a serialization error, both Java writers compact the retry payload and timestamps but retain the original
failsafeTableRowslist. A later error index is then applied to the wrong version of that list.For a write using
withFormatRecordOnFailureFunction:[A, B, C][B, C][C]C is written successfully. B is neither written nor recoverable from the failure output. The Storage Write API contract defines error indexes relative to the current request. This is a controlled reproduction with simulated responses, not a reproduced live BigQuery incident.
Filter failsafe rows alongside payloads and timestamps in both the sharded and unsharded writers. This preserves their positional correspondence through successive retries, including nullable entries used for the protobuf-to-TableRow fallback.
Reproduction and testing
The new
StorageApiWriteRetryTestruns publicBigQueryIOpipelines with the DirectRunner and a fake append service. It uses a failure formatter that returnsoriginal_idrecords distinct from the serialized rows, rejects one row per append, then delegates the successful append toFakeDatasetService. Assertions cover the failed records, successful output, persisted rows, and the three shrinking append sizes.The same regression fails in all three modes against unchanged upstream writer classes and passes with this fix: batch
STORAGE_WRITE_API, streamingSTORAGE_WRITE_APIwith a fixed shard, andSTORAGE_API_AT_LEAST_ONCE.The branch passes the normal Gradle compiler checks and a combined test run with the two existing
BigQueryIOWriteTestcasestestStorageWriteReturnsAppendSerializationErrorandtestStorageWriteWithMultipleAppendsPerStream: 8 passed, 5 inapplicable parameter combinations skipped.spotlessJavaCheck,validateChanges, andgit diff --checkalso pass. The baseline comparison separately compiles the unchanged writer classes with the same regression against released Beam 2.76 dependencies.Downsides
Each serialization-error retry allocates one additional list of references to the surviving failsafe rows. The normal append path is unchanged; the error-path allocation is proportional to the batch being retried and does not copy the row objects.
CHANGES.mdwith the behavior change.