Skip to content

feat(container-loader): add reference-only state capture - #28006

Merged
Alex Villarreal (alexvy86) merged 6 commits into
microsoft:mainfrom
alexvy86:alexvy86-reference-only-state-capture
Aug 21, 2026
Merged

Alex Villarreal (alexvy86) merged 6 commits into
microsoft:mainfrom
alexvy86:alexvy86-reference-only-state-capture

Conversation

@alexvy86

@alexvy86 Alex Villarreal (alexvy86) commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

Description

This PR adds a reference-only mode for captureFullContainerState that results in blobs being omitted in the returned pending container state. The new blobCaptureMode option defaults to "inline" to preserve today's self-contained/offline behavior; "reference" retains snapshot blob IDs while omitting structural and attachment payloads so later online loads fetch them from live storage.

The intended scenario is capturing a baseline state that is later used together with a separate (non-Fluid) representation of changes to be applied to the container, so the edits are applied on top of the container state at the moment of the initial capture/read, not on top of the latest container state. The state is returned by an HTTP API call and is submitted back on another HTTP request, where the caller doesn't interact with the state blob, so keeping it size down is preferred to save bandwidth and is possible because the load during the write request happens online and blobs can be rehydrated at that point.

Of note, getPendingLocalState is intentionally not suitable for this even when it doesn't include blobs by default because it serializes an ongoing ID-compressor session and pending runtime state; forking that artifact can duplicate session ownership, and we don't want to limit the use of the baseline state blob to a single write request after it is read. captureFullContainerState emits pendingRuntimeState: undefined, so each load creates a fresh runtime and ID-compressor session.

Reference-only state is online-only. loadExistingContainer and the online form of loadFrozenContainerFromPendingState fall through to live readBlob when the payload cache is empty. The fully offline frozen-load form rejects reference-only state with a clear UsageError.

Validation includes:

  • Existing default inline capture and fully offline frozen-load coverage.
  • Structural and attachment payload omission plus state-size reduction.
  • Live attachment reads from omitted payloads.
  • Two independent containers loaded from one baseline, each submitting a distinct edit, with both edits present in a subsequent load.
  • 300 passing container-loader tests.
  • 108 passing local-server tests (4 pending).

This is a request-for-feedback prototype, not a proposal to make getPendingLocalState forkable.

Reviewer Guidance

The review process is outlined in the pull request guidelines.

Please focus on:

  • Is blobCaptureMode: "inline" | "reference" the right API shape and terminology?
  • Should reference-only artifacts carry an explicit serialized marker, rather than being identified by an empty snapshotBlobs map for fully offline rejection?
  • Is making the existing capture API mode-dependent preferable to introducing a separate reference-only capture API?
  • Are the online-only storage dependency and offline failure semantics sufficiently explicit?

This adds a non-breaking property to an existing @legacy @alpha interface, so API Council review is required.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 8c3852c2-aee1-4175-acc6-99d66725460b
@github-actions github-actions Bot added area: tools area: loader Loader related issues area: repo Repo related work area: website area: tests Tests to add, test infrastructure improvements, etc public api change Changes to a public API changeset-present base: main PRs targeted against main branch labels Aug 18, 2026
@github-actions

github-actions Bot commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

Hi! Thank you for opening this PR. Want me to review it?

Based on the diff (270 lines, 6 files), I've queued these reviewers:

  • Correctness — logic errors, race conditions, lifecycle issues
  • Security — vulnerabilities, secret exposure, injection
  • API Compatibility — breaking changes, release tags, type design
  • Performance — algorithmic regressions, memory leaks
  • Testing — coverage gaps, hollow tests

How this works

  • Adjust the reviewer set by ticking/unticking boxes above. Reviewer toggles alone don't trigger anything.

  • Tick Start review below to dispatch the review fleet.

  • After review finishes, tick Start review again to request another run — it auto-resets after each dispatch.

  • This comment updates as new commits land; your reviewer selections are preserved.

  • Start review

@alexvy86
Alex Villarreal (alexvy86) marked this pull request as ready for review August 19, 2026 23:06
@alexvy86
Alex Villarreal (alexvy86) requested a review from a team as a code owner August 19, 2026 23:06
Copilot AI lite review requested due to automatic review settings August 19, 2026 23:06

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR prototypes a new reference-only blob capture mode for captureFullContainerState, enabling reusable baselines that can be loaded online multiple times while fetching omitted blob payloads from live storage.

Changes:

  • Added blobCaptureMode?: "inline" | "reference" to captureFullContainerState, defaulting to "inline".
  • Updated frozen/offline load semantics to clearly reject reference-only pending state when no driver wiring is provided.
  • Added local-server test coverage demonstrating two independent online loads from a shared reference-only baseline and verifying attachment fetch + merged edits.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
packages/test/local-server-tests/src/test/captureFullContainerState.spec.ts Adds coverage for reference-only baseline capture and multiple independent online loads seeded from one baseline.
packages/loader/container-loader/src/frozenServices.ts Updates offline blob-read failure message to reference the new inline/reference capture mode semantics.
packages/loader/container-loader/src/createAndLoadContainerUtils.ts Implements the new blobCaptureMode option, adjusts offline URL validation rules, and adds offline rejection for reference-only state.
packages/loader/container-loader/api-report/container-loader.legacy.alpha.api.md Updates the legacy alpha API report to include the new blobCaptureMode property.
.changeset/strict-buckets-sing.md Documents the new feature and provides sample usage for reference-only baselines.
Suppressed comments (1)

packages/loader/container-loader/src/createAndLoadContainerUtils.ts:639

  • snapshotBlobs / attachmentBlobContents are initialized as {} without a type annotation, which widens them to {} (no index signature). That loses type-safety vs IPendingContainerState and can lead to type errors/regressions when these maps are later treated as string-indexed dictionaries.
		let gcData: IGcSnapshotData | undefined;
		let snapshotBlobs = {};
		let attachmentBlobContents = {};

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread packages/loader/container-loader/src/createAndLoadContainerUtils.ts Outdated
Comment thread packages/test/local-server-tests/src/test/captureFullContainerState.spec.ts Outdated
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 8c3852c2-aee1-4175-acc6-99d66725460b
Comment thread packages/loader/container-loader/src/createAndLoadContainerUtils.ts Outdated
Co-authored-by: Abram Sanderson <Abram.sanderson@gmail.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 8c3852c2-aee1-4175-acc6-99d66725460b
@alexvy86

Copy link
Copy Markdown
Contributor Author

/azp run Build - client packages

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 1 pipeline(s).

Comment thread .changeset/strict-buckets-sing.md Outdated
Comment thread .changeset/strict-buckets-sing.md Outdated
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 8c3852c2-aee1-4175-acc6-99d66725460b
@github-actions

Copy link
Copy Markdown
Contributor

🔗 No broken links found! ✅

Your attention to detail is admirable.

linkcheck output

$ start-server-and-test "npm run serve -- --host 127.0.0.1 --no-open" http://127.0.0.1:3000 check-links
1: starting server using command "npm run serve -- --host 127.0.0.1 --no-open"
and when url "[ 'http://127.0.0.1:3000' ]" is responding with HTTP status code 200
running tests using command "npm run check-links"


> fluid-framework-website@0.0.0 serve
> docusaurus serve --host 127.0.0.1 --no-open

[SUCCESS] Serving "build" directory at: http://127.0.0.1:3000/

> fluid-framework-website@0.0.0 check-links
> linkcheck http://127.0.0.1:3000 --skip-file skipped-urls.txt

Crawling...

Stats:
  338440 links
    2041 destination URLs
    2297 URLs ignored
       0 warnings
       0 errors


@jzaffiro jzaffiro left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved for docs

@github-actions

Copy link
Copy Markdown
Contributor

Bundle size comparison

Base commit: 42f17839eb4b69ccb7d45489fea1244750640023
Head commit: fd3591e504b2251fc3ff38d8725c567bd590405f

Notable changes

No bundles changed by ≥ 500 bytes parsed.

Per-bundle deltas

@fluid-example/bundle-size-tests

  • fluidFrameworkAllAlpha.js: parsed 782366 → 782422 (+56), gzip 215005 → 215070 (+65)
  • azureClient.js: parsed 632351 → 632346 (-5), gzip 169406 → 169505 (+99)
  • odspClient.js: parsed 609607 → 609704 (+97), gzip 163773 → 163897 (+124)
  • aqueduct.js: parsed 536725 → 536736 (+11), gzip 144124 → 144165 (+41)
  • fluidFramework.js: parsed 401229 → 401262 (+33), gzip 114017 → 114062 (+45)
  • sharedTree.js: parsed 390608 → 390634 (+26), gzip 111442 → 111477 (+35)
  • containerRuntime.js: parsed 313633 → 313615 (-18), gzip 86017 → 86013 (-4)
  • sharedString.js: parsed 175134 → 175141 (+7), gzip 49635 → 49639 (+4)
  • experimentalSharedTree.js: parsed 161726 → 161726 (0), gzip 46665 → 46665 (0)
  • matrix.js: parsed 159511 → 159520 (+9), gzip 45849 → 45854 (+5)
  • loader.js: parsed 146720 → 146736 (+16), gzip 39875 → 39888 (+13)
  • odspDriver.js: parsed 115403 → 115458 (+55), gzip 35585 → 35663 (+78)
  • directory.js: parsed 65559 → 65566 (+7), gzip 18444 → 18451 (+7)
  • 578.js: parsed 58686 → 58686 (0), gzip 17657 → 17657 (0)
  • odspPrefetchSnapshot.js: parsed 45838 → 45819 (-19), gzip 15321 → 15331 (+10)
  • map.js: parsed 45710 → 45717 (+7), gzip 14077 → 14085 (+8)
  • 252.js: parsed 44362 → 44362 (0), gzip 13735 → 13735 (0)
  • summarizerDelayLoadedModule.js: parsed 31287 → 31287 (0), gzip 7929 → 7929 (0)
  • socketModule.js: parsed 26992 → 26962 (-30), gzip 8019 → 8053 (+34)
  • createNewModule.js: parsed 8523 → 8517 (-6), gzip 3550 → 3561 (+11)
  • summaryModule.js: parsed 3888 → 3888 (0), gzip 1874 → 1874 (0)
  • connectionState.js: parsed 909 → 909 (0), gzip 500 → 500 (0)
  • sharedTreeAttributes.js: parsed 845 → 852 (+7), gzip 493 → 503 (+10)
  • debugAssert.js: parsed 429 → 429 (0), gzip 299 → 299 (0)
  • FluidFramework-HashFallback.js: parsed 419 → 419 (0), gzip 313 → 313 (0)

@alexvy86
Alex Villarreal (alexvy86) merged commit 4374770 into microsoft:main Aug 21, 2026
39 checks passed
@alexvy86
Alex Villarreal (alexvy86) deleted the alexvy86-reference-only-state-capture branch August 21, 2026 20:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: loader Loader related issues area: repo Repo related work area: tests Tests to add, test infrastructure improvements, etc area: tools area: website base: main PRs targeted against main branch changeset-present public api change Changes to a public API

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants