Repository navigation
Conversation
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Adhd9T7LkLhPWyrUensoju
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Adhd9T7LkLhPWyrUensoju
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Adhd9T7LkLhPWyrUensoju
|
@sandros94 is attempting to deploy a commit to the unjs Team on Vercel. A member of the Team first needs to authorize it. |
Member
|
Thanks for PR @sandros94 since it is a big change, can you somehow share your full claude chat session with me? |
Author
Yes, absolutely. How would you like I send it to you? Discord? |
Author
|
I'm a bit second guessing myself on this topic, as ETags aren't durable and on process being restarted they fallback to the derivedETag. Which brings back the metadata topic again 🥲 |
This branch has not been deployed
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.
Closes #20, and the two things the thread found alongside it: a stale
If-Matchpassing, and an unconditionalPUTlanding between a compare and its swap. Ofc I asked help from claude, especially with reviewing some ideas, benchmarking, docs and repo patterns, but everything is under my intent and knowledge. So feel free to mix, rewrite, ask or deny anything as usual @pi0What changed
All three were the same write path, so there is now one:
src/commit.ts, shared bymountx/s3andmountx/webdav..mountx-multipart/tmp-<hex>, is checked there (length cap,Content-MD5), and becomes the object withlink()for a create or an atomicrename()for a replace. A reader mid-PUTsees the whole previous object; a failed upload leaves it untouched and no debris. Capability-gated:memoryandnode-fsget this shape,unstoragewrites in place as beforePUTrace is gonestatidentity. Anything the table doesn't know (restart, eviction, an outside writer) answers the old derived-1tag, so the worst case is one spurious412, never a false200. Multipart objects answer S3'smd5(part md5s)-N; parts answer their MD5;Content-MD5is verified onPutObject/UploadPart;CompleteMultipartUploadtakes the same conditionals asPutObjectstatidentity can't repeat inside one millisecond eitherrclone checkactually verifies hashes now instead of reporting them as unchecked.Three things worth saying explicitly
.mountx-multipartshould be renamed. As it now covers something broader than simple multi-part uploads, even just a simple.mountx-lockis clear enoguh IMO, but decision is yoursunstorage stays in place, and that is unstorage's limitation, not mountx's. It has no
linkand itsrenameis a copy followed by a delete, so there is nothing to commit atomically with. The stale-If-Matchfix and the whole-write lock hold there too; what stays is that a reader can see a partial resource mid-write and a digest mismatch cannot restore the previous one. It's written down as such in the docs and insrc/commit.ts.The clock for the multigrain stamp is
Date.now()plus a per-node nudge, discarding an earlier approach I did withperformance.now(). The goal was a trusted wall clock that is runtime-agnostic, on older runtimes too:performance.now()reads a monotonic clock that excludes suspended time and drifts from the wall clock after a suspend or an NTP step. The nudge (previous stamp + 1 µs when the clock hasn't moved past it) encodes ordering, intentionally not elapsed time; nothing consumes the distance between two stamps as of writing this PR, and the module doc says so.Measured
Stale
If-Matchaccepted, through the session, same-size bodies, 200 rounds:Cost of the hash, 256 MiB
PUTthrough the session on my dev machine: node-fs 747 → 667 MiB/s (S3) and 748 → 683 (WebDAV), the MD5 overlaps the threadpool write; memory 1205 → 590 on both, itswrite()is synchronous so copy and hash add up. A body paced like a socket (100 or 400 MiB/s) shows no loss on either driver.HEADis unchanged on node-fs and faster on memory. Not on the docs pages but claude suggested correctly to place them in.agents/architecture.mdwith their provenance.Verified
pnpm testgreen, plus the rclone oracle for both transports with rclone onPATHtest/integrations/celld.test.ts) on node-fsCommits
Five, meant to be read in order: the driver timestamps, the commit module with the S3 adoption, the WebDAV adoption, a small fix for
201/204under a race (decided at the commit rather than before the lock), and the prose.Follow-ups, deliberately out
x-amz-checksum-*headers and trailers (crc32/crc32c/sha1/sha256), noted in the roadmap; the plumbing is theremountx.*compare-and-commit extension for drivers whose store has a native CAS — the path to cross-process CAS, which this PR keeps out of scope (one gateway process per bucket)