wwj6591812 opened a new pull request, #9301:
URL: https://github.com/apache/paimon/pull/9301

   ### Purpose
   
   `blob-write-null-on-fetch-failure=true` can safely turn a BLOB fetch/open 
failure into NULL only while no bytes for that BLOB have reached the managed 
BLOB output. An HTTP-backed BLOB write can also fail later, while the response 
body is being consumed. One observed failure was:
   
   ```text
   org.apache.paimon.shade.hc.core5.http.ConnectionClosedException:
   Premature end of Content-Length delimited message body
   (expected: 990434; received: 89075)
   ```
   
   At that point a raw BLOB, ARRAY element, or MAP value may already have 
appended a record header and a partial payload to the shared BLOB file. 
Catching the exception and returning NULL directly would leave unindexed bytes 
behind and could corrupt subsequent offsets, CRCs, and records. 
`PositionOutputStream` also has no portable record-level rollback across local, 
distributed, and object-store implementations.
   
   This PR adds a per-BLOB-element staging boundary so the existing opt-in 
option can safely cover terminal response-body fetch failures.
   
   ### Changes
   
   When `blob-write-null-on-fetch-failure=true`:
   
   - Read each individual BLOB payload into a private staging buffer before 
appending any of its payload bytes to the final managed BLOB output.
   - Keep up to 1 MiB in memory and spill larger payloads to a task-local 
temporary file.
   - Append the staged payload to the final output only after the source body 
completes and its declared length is satisfied.
   - If the source body ultimately fails while being read, close the source, 
discard the stage, and encode that scalar/ARRAY/MAP element as NULL.
   - Keep staging creation/write/read/close/delete failures, source cleanup 
failures, final output failures, footer/CRC failures, and consumer failures 
fatal. These are not remote fetch failures and must not be hidden as NULL.
   - Preserve task cancellation: an interrupted task is never converted to a 
successful NULL row.
   - Discard a failed reusable source so the next descriptor reopens it instead 
of continuing from an unknown offset.
   
   When the option is false, the existing direct-streaming fast path and 
failure behavior are unchanged.
   
   ### Relationship to #9271
   
   This PR and #9271 address different layers and are intentionally independent:
   
   | Case | #9271: HTTP body recovery | This PR: atomic NULL fallback |
   | --- | --- | --- |
   | A truncated body is recoverable | Resume/replay and return the complete 
body | Commit the complete staged body, not NULL |
   | Recovery is exhausted | Propagate the terminal read failure | If the 
existing option is enabled, discard the stage and write NULL |
   | The option is disabled | Recovery is still attempted | Terminal failure 
still fails the write |
   | This PR is used without #9271 | No transport-level recovery | The first 
terminal body-read failure can safely become NULL when opted in |
   
   #9271 recovers transport interruptions: it uses validated `Range + If-Range` 
with a strong ETag, or a complete HTTP 200 replay with SHA-256 prefix 
verification when no strong ETag is available. It deliberately does not change 
NULL semantics.
   
   This PR supplies the output atomicity needed for the separate terminal 
policy. With both changes, Paimon first tries bounded body recovery; only after 
recovery is exhausted does the existing opt-in setting write NULL. The PRs can 
be reviewed and merged in either order.
   
   ### Scope and performance
   
   - The new staging path is enabled only by 
`blob-write-null-on-fetch-failure=true`; other writers keep the existing direct 
path.
   - The change applies to the append-only managed-BLOB writer path. 
Primary-key BLOB externalization currently keeps both NULL-on-fetch options 
disabled and is not expanded by this PR.
   - Each active BLOB writer stages one element at a time. It uses at most 
approximately 1 MiB of heap before spilling, then performs one local write/read 
before the final output write.
   - Normal success, handled fetch failure, abort, and close paths delete spill 
files. A process hard kill can leave an unreferenced temporary file for 
host-level cleanup.
   - There is no public API or managed BLOB on-disk format change. Magic bytes, 
length/index encoding, CRC handling, descriptors, and NULL encoding remain 
unchanged.
   
   ### Tests
   
   Format-layer unit tests cover scalar, ARRAY, and MAP layouts; good/fail/good 
sequencing; known-length EOF and unknown-length read errors; option-disabled 
behavior; reusable-source reopening; exact metrics; cancellation versus socket 
timeout; in-memory and spilled staging; cleanup on success/failure/abort/close; 
and fatal staging/final-output/consumer failures.
   
   ```text
   mvn -pl paimon-format -am \
     -DskipITs -DwildcardSuites=none \
     -Dtest=BlobFormatWriterTest \
     -Dsurefire.failIfNoSpecifiedTests=false test
   
   Tests run: 57, Failures: 0, Errors: 0, Skipped: 0
   BUILD SUCCESS
   ```
   
   Flink integration tests use deterministic truncated HTTP responses and cover 
scalar, ARRAY, and MAP NULL fallback, a following BLOB in the same writer, 
disabled fallback with no committed row/snapshot, and separation from the 404 
option.
   
   ```text
   Tests run: 5, Failures: 0, Errors: 0, Skipped: 0
   BUILD SUCCESS
   ```
   
   A local synthetic merge with #9271 also passed:
   
   - `HttpClientUtilsTest`: 32 tests
   - HTTP recovery plus terminal-NULL Flink integration tests: 7 tests (2 
recovery + 5 fallback)
   - All failures/errors/skips: 0
   
   The combined integration coverage verifies both successful recovery staying 
non-NULL and recovery exhaustion falling back to NULL only when explicitly 
enabled.
   
   ### API and format
   
   No public API or storage-format change.


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