You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix: gate chunked-receive checkpoint on stream completion
The receive path advanced check_dbversion/check_seq per applied chunk to
the chunk's last row, which can fall mid-db_version. Since the server's
cloudsync_payload_chunks resumes on db_version > since with no seq cursor,
a stop between chunks of a split db_version silently skipped the un-applied
rows on the next /check (data loss).
Mirror the send path: advance the receive cursor only after the whole chunk
stream is applied, to the stream watermark, never per chunk. cloudsync_payload_apply
gains a C-level checkpoint argument (watermark / none / last-applied); the
/check response signals watermark + final chunk, and falls back to legacy
monolithic behavior when absent. The public single-arg SQL function and the
send path are unchanged; re-delivered rows stay idempotent.
Adds do_test_payload_chunks_split_dbversion reproducing a single db_version
split across >=2 v2 chunks with partial apply.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Copy file name to clipboardExpand all lines: API.md
+2Lines changed: 2 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -759,6 +759,8 @@ If a package of new changes is already available for the local site, the server
759
759
This function is designed to be called periodically to keep the local database in sync.
760
760
To force an update and wait for changes (with a timeout), use [`cloudsync_network_sync(wait_ms, max_retries)`].
761
761
762
+
When the server delivers a download as a stream of chunks, the local receive checkpoint is advanced only after the **whole stream** has been applied — never in the middle of a source `db_version`. Mirroring the send path, the server tags the stream with its watermark and marks the final chunk; the checkpoint jumps straight to that watermark on completion. A stop between chunks therefore re-delivers the stream from the unchanged checkpoint on the next call (apply is idempotent, so re-delivered rows are harmless), so no changes can be skipped. A non-chunked (monolithic) download advances the checkpoint to the artifact's last applied position, as before.
763
+
762
764
If the network is misconfigured or the remote server is unreachable, the function raises a SQL error. If the received payload cannot be applied locally (for example because of an unknown schema hash), the error is returned as a `receive.error` field in the JSON response. If the server reports an unresolved failed check job (e.g. an `encode_changes` failure), that failure is forwarded as a `receive.lastFailure` object.
Copy file name to clipboardExpand all lines: CHANGELOG.md
+1Lines changed: 1 addition & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -19,6 +19,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
19
19
20
20
-`cloudsync_payload_apply()` now accepts legacy payloads, monolithic payloads, and v3 fragment payloads without enforcing the local `payload_max_chunk_size`, preserving compatibility between peers with different settings.
21
21
-`cloudsync_network_send_changes()` now streams outgoing changes through `cloudsync_payload_chunks()` instead of first building one monolithic payload. This bounds transport payload size for the built-in network path and lets large rowsets or oversized BLOB/TEXT values flow through the same `/apply` endpoint as regular payloads.
22
+
- The chunked-download receive path advances the local receive checkpoint (`check_dbversion` / `check_seq`) **only after a chunk stream has been fully applied**, jumping straight to the stream watermark — never into the middle of a source `db_version`. This mirrors the send path and ensures a stop between chunks cannot skip the un-applied rows of a `db_version` split across chunks on the next `/check` (the server resumes on `db_version > since`, with no intra-version cursor). `cloudsync_payload_apply()` no longer advances the receive checkpoint per applied chunk; the built-in network `/check` path drives it from the server's watermark and final-chunk signal, and falls back to the previous monolithic behavior when the server sends no watermark. Re-delivered rows remain idempotent.
0 commit comments