Skip to content

feat: content-versioned preview ids for local scene development - #1529

Draft
dalkia wants to merge 1 commit into
mainfrom
feat/lsd-content-versioned-preview-ids
Draft

feat: content-versioned preview ids for local scene development#1529
dalkia wants to merge 1 commit into
mainfrom
feat/lsd-content-versioned-preview-ids

Conversation

@dalkia

@dalkia dalkia commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

What does this PR change?

In preview (dcl start / Creator Hub), a file's content id is derived from its absolute path only (b64-<base64(path-machineId)>). The id never changes when the file changes, so an explorer cannot tell from the content map whether anything is stale — its only correct option is to drop its caches wholesale on every scene reload and re-download/re-process the entire scene, even for a one-file edit.

This PR embeds the file's mtime into the preview id:

b64-<base64(path \u0000 truncatedMtimeMs -machineId)>
  • Every URL and client cache key derived from the id becomes self-invalidating: an edited file gets a new id (cache miss → fresh bytes), unchanged files keep their warm caches.
  • The separator is a NUL byte, which cannot occur in file paths or hostnames, so decoding is unambiguous (paths with spaces, hyphens or digits are safe) — and clients can detect a version-capable server by its presence.
  • The project directory's own id (the scene/entity id) stays path-only, so scene identity remains stable across edits and reloads.
  • The decoder accepts both plain and versioned ids, so nothing that still mints plain ids breaks.

Why

Explorer-side scene reload currently spends most of its time re-downloading and re-parsing unchanged assets because of the forced cache drain. With versioned ids the explorer can skip the drain entirely and only re-fetch what actually changed (unity-explorer counterpart: decentraland/unity-explorer#9819). Old explorers are unaffected: they treat ids as opaque strings and keep draining as before.

Notes / follow-ups

  • A .gltf/.glb with external textures keeps its own id when only a texture changes; a client that caches the composed model must still handle that dependency (or a follow-up could fold dependency mtimes into the model's id). GLBs with embedded textures — the common export — are fully covered.
  • Wearable preview projects keep plain ids for the wearable id derivation (b64HashingFunction(workingDirectory)), which is unaffected.

Test it

npm run start # in any scene project
curl -s -X POST http://127.0.0.1:8000/content/entities/active -d '{"pointers":["0,0"]}' -H 'Content-Type: application/json'
# content[].hash changes when you touch a file; entity id does not

🤖 Generated with Claude Code

In preview, content ids are derived from the file's absolute path only, so
a client cannot tell from the id whether a file changed — explorers must
drop their caches wholesale on every scene reload to pick up edits.

Embed the file's mtime in the id (NUL-separated so it decodes unambiguously:
paths cannot contain NUL bytes), making every URL and client cache key
derived from it self-invalidating: an edited file gets a new id, unchanged
files keep warm caches. The project directory's own id (the scene/entity id)
stays path-only so scene identity is stable across edits, and the decoder
accepts both plain and versioned ids.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
dalkia added a commit to decentraland/unity-explorer that referenced this pull request Aug 6, 2026
…oned ids

New sdk-commands embed each file's mtime in its preview content id
(NUL-separated from the path), so an edited file gets a new id and every
cache key derived from it self-invalidates: the wholesale UnloadCache +
UnloadUnusedAssets on reload becomes unnecessary and caches stay warm.

Detect the capability from the definition the reload already holds: a NUL
byte in a decoded content id is unforgeable by accident (file paths and
hostnames cannot contain one), and any doubt — legacy path-only ids,
non-b64 ids, malformed base64 — falls back to the full drain, preserving
today's behavior against older toolchains byte-for-byte.

Toolchain counterpart: decentraland/js-sdk-toolchain#1529

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Test this pull request

  • The @dcl/sdk package can be tested in scenes by running

    npm install "https://sdk-team-cdn.decentraland.org/@dcl/js-sdk-toolchain/branch/feat/lsd-content-versioned-preview-ids/dcl-sdk-7.25.1-31122727261.commit-7d9a14b.tgz"
  • The @dcl/js-runtime package can be tested in scenes by running

    npm install "https://sdk-team-cdn.decentraland.org/@dcl/js-sdk-toolchain/branch/feat/lsd-content-versioned-preview-ids/@dcl/js-runtime/dcl-js-runtime-7.25.1-31122727261.commit-7d9a14b.tgz"
  • To test with npx init

    export SDK_COMMANDS="https://sdk-team-cdn.decentraland.org/@dcl/js-sdk-toolchain/branch/feat/lsd-content-versioned-preview-ids/dcl-sdk-commands-7.25.1-31122727261.commit-7d9a14b.tgz"
    npx $SDK_COMMANDS init
  • The /changerealm command to test test in-world

    /changerealm https://sdk-team-cdn.decentraland.org/ipfs/feat/lsd-content-versioned-preview-ids-e2e
    
  • You can preview this build entering:
    https://playground.decentraland.org/?sdk-branch=feat/lsd-content-versioned-preview-ids

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant