Files
Claude 5d034b0d09 Delta-upload client: FastCDC in WASM + overlapped worker pipeline
Phase 2 — the client side of "upload only what changed", closing the
delta-sync plan.

WASM (wasm/oxicloud-hash): DeltaChunker adds incremental FastCDC with
the server's exact crate and parameters (64K/256K/1M) next to the BLAKE3
hasher. The incremental split is provably identical to a single pass:
every chunk except the last ends on a content/max-size condition whose
decision window was fully buffered, so only the tail is provisional and
re-examined as slices arrive. A mirror test — the client twin of the
server's stream≡slice test — chunks 4 MiB of xorshift noise with
adversarial slice sizes (7 B … 8 MiB) and requires boundary-for-boundary
equality with one FastCDC pass. Vendored artifacts rebuilt (55 KB wasm).

Worker (static/js/workers/deltaWorker.js): the full protocol off the
main thread with OVERLAPPED stages — 8 MiB file slices feed the chunker
while earlier batches (256 hashes) negotiate and their missing chunks
upload through a 2-deep PUT pool (≤8 MiB framed bodies, bytes re-sliced
from the File at send time, never hoarded). Commit handles 409
still_missing by uploading exactly the named hashes and retrying.

Orchestrator (features/files/deltaUpload.js): threshold (8 MiB),
worker lifecycle + size-scaled timeout, progress relay to the upload
bell, conclusive-outcome mapping (201/200, 507 quota, 409 name
conflict) and silent fallback to the byte upload for everything else.
Wired into uploadFiles and uploadFolderEntries, which now surface one
batch summary of the bytes dedup saved. This subsumes the whole-file
instant-upload module — a fully-known file negotiates to nothing
missing and the commit short-circuits on possession — so
instantUpload.js and hashWorker.js are removed (the /api/dedup/check
and /api/files/by-hash endpoints remain for API clients).

Verified end-to-end against PostgreSQL 16 — the cross-boundary proof
the whole design hangs on, in both directions: a 24 MB file byte-
uploaded (server-side CDC) then edited and delta-negotiated with
WASM-computed chunks reported missing 1/74 (boundaries bit-identical),
synced with 344 KB on the wire vs 24 MB (98.6% saved) and downloaded
byte-identical; inversely, a file created via delta then byte-uploaded
as identical content produced a server-side manifest DEDUP HIT with the
same content_hash. Insertion at the head of the file (the adversarial
CDC case) still negotiated missing 1/74. Chunk+hash throughput ≈275 MB/s
in V8 with SIMD128.

https://claude.ai/code/session_01WdNenpnujNR2sc32XVvwfS
2026-06-11 15:44:44 +00:00

35 lines
1.3 KiB
TOML
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
[package]
name = "oxicloud-hash-wasm"
version = "0.1.0"
edition = "2021"
description = "BLAKE3 hashing for the OxiCloud web frontend — compiled from the exact same crate the server uses, so client-side hashes match server-side content addressing bit for bit."
publish = false
# Standalone workspace root: this crate is built only by
# scripts/build-wasm.sh (wasm32 target) and must not join the server
# workspace — `cargo test --workspace` / clippy on the host have nothing
# useful to do with a wasm cdylib.
[workspace]
[lib]
crate-type = ["cdylib"]
[dependencies]
# Same major as the server's Cargo.toml. `wasm32_simd` enables the WASM
# SIMD128 kernels (~3-4× over the portable implementation); every
# evergreen browser since 2023 supports it, and the frontend falls back
# to a plain byte upload when instantiation fails.
blake3 = { version = "1.8.4", default-features = false, features = ["wasm32_simd"] }
# Same crate AND parameters as the server's CDC dedup engine — chunk
# boundaries computed in the browser must equal the server's bit for bit,
# or cross-version dedup between byte uploads and delta uploads collapses.
fastcdc = "4.0.0"
wasm-bindgen = "0.2"
[profile.release]
# Hashing throughput is the whole point of this module.
opt-level = 3
lto = "fat"
codegen-units = 1
strip = true