Repository navigation
60-net: Q2 fast movement channel + Q6 local asset cache - #435
Merged
Merged
Conversation
…nel for pose streams
- fastChannel.js (leaf): a negotiated {ordered:false, maxRetransmits:0} data channel on each
PeerJS connection's own RTCPeerConnection (id 7, no extra signaling), opened only when the
other side advertises `fc: 1` in the modules handshake + a `fastchan` hello down the same conn
- every pose message (camera, vrhands, move) carries `ps`, one monotonic counter per sender;
receivers drop a pose older than the newest applied for that (sender, key) — on both channels
and inside batch envelopes, so a late streamed move never overwrites the committed one
- trailing keyframe: a stream's last pose is re-sent reliably (same ps) once the key goes
quiet for 250 ms, to the peers that got it unreliably
- streams marked fast: avatar camera (not when its extras change), VR hands (not on a rep
switch), gizmo drag, physics bodies, VR held objects (not the release), play-mode grabs,
possess rides; everything else stays on the reliable conn
- graceful fallback: older peers / closed channel / >12 KB messages go reliable; kill switch
safeStorage fastChannel=off; `fastchan` on the cloudHooks ALWAYS_ALLOWED floor
- debug hook __stores.fastChannel (links, stale filter, keyframes, pose tap for the loss e2e)
- unit: tests/unit/fastChannel.test.js (18)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…r a cap - assetCacheCore.js (zero-import leaf): url keys (+ a version tag for build-bundled files), derived keys (source hash + kind + settings, field order irrelevant), the index shape and its normalizer, usage (a shared blob counted once), the LRU eviction plan, orphans - assetCache.js: one blob per SHA-256 in OPFS (tp-asset-cache/blobs) + index.json; the same model on CacheStorage where OPFS cannot write; a plain fetch where neither exists. Reconciles orphan blobs / missing blobs on open; index flushed on a 400 ms debounce and on pagehide - kinds wired: pack files (packCache.js is now a url-keyed view over the cache, same API; 39 P5's CacheStorage copies are migrated once and that cache deleted), bundled skies (hdriRuntime, keyed by the build version), CC0 downloads (cc0Fetch.fetchBytes), converted textures (the import optimizer's output keyed by source hash + options + version), pack anim refs - navigator.storage.persist() asked once, from a toast with the reason, the first time something is cached (assetCache:persistAsked); never on boot, never again - never the app shell: only content urls reach it - unit: tests/unit/assetCacheCore.test.js (13); place-drag-cache reads the store through packCache.cachedPackBuffer instead of CacheStorage Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…uites - Settings ▸ Storage (StorageSettings.svelte, Workspace group): what the cache holds by kind, Clear, the size limit (256 MB / 512 MB / 1 GB / 2 GB, LRU), the persistence state with "Ask the browser", and the Storage breakdown button - Storage breakdown: a "Cached downloads" category (skies, converted textures, downloaded files), one row per kind, reclaimed through the cache's own delete - e2e: asset-cache-opfs (second load served from OPFS with no request, persist asked once, no shell in the index, Settings Clear, the 39 P5 migration), fast-channel-loss (p95 pose gap at 0/5/10 % loss before/after through a WebRTC loss shim), fast-channel-fallback Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…of queueing it stale Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…h pages paused, edits read from .text, a cadence check per phase Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…al pose land (10 % back-off outlasts a fixed 1.5 s) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…r message swapped same-ms releases), ordered-channel control check Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Collaborator
Author
|
In main via 60-int: released in v1.44.0 (#476). |
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.
Lane 60-net — roadmap 60 Q2 (fast movement channel) + Q6 (local asset cache). Base v1.41.0.
Q2 — fast movement channel (
src/lib/fastChannel.js){ordered: false, maxRetransmits: 0}, for latest-pose streams only:camera,vrhands, streamedmove(drag, held objects, physics bodies, possess). Edits, committed moves and requests stay on the reliable conn.pssequence numbers per sender; a receive-side stale filter drops older poses, on both channels.fc: 1(an older build), a channel that isn't open yet, or a message over 12 KB all go reliable, byte-identical to before.fc: 1onmodules, afastchanhello (on the ALWAYS_ALLOWED floor), andps.peers.send(data, {fast: true})andbroadcast(payload, opts)gain an optional second argument.Q6 — local asset cache (
src/lib/assetCache.js+assetCacheCore.js)packCachekeeps its API; its old Cache Storage copy is migrated once, then deleted), skies, CC0 downloads, converted textures and animation refs.navigator.storage.persist()is asked once, through a toast that gives the reason.Proof
fastChannel,assetCacheCore); check-ratchet 298 against a baseline of 299;npm run buildpasses.fast-channel-losspasses. It runs two real peers through a WebRTC loss shim: reliable = retransmit after 200 ms with head-of-line blocking, fast = dropped. 20 Hz, 400 poses per phase, with rendering paused so the measurement times the wire.Edits arrive complete and in order on both channels, the final pose lands exactly, and the ordered-channel control applies 400/400.
fast-channel-fallbackpasses: a peer without the channel gets every pose over the reliable conn.asset-cache-opfspasses:persist()is asked once;cc0-asset-browserandpossessfail identically on base 1.41.0 (A/B), so they are not this branch.Owed on device
🤖 Generated with Claude Code