feat(container-loader): support offline loads in loadFrozenContainerFromPendingState#27347
feat(container-loader): support offline loads in loadFrozenContainerFromPendingState#27347anthony-murphy wants to merge 6 commits into
Conversation
|
Hi! Thank you for opening this PR. Want me to review it? Based on the diff (831 lines, 16 files), I've queued these reviewers:
How this works
|
9e0e5c2 to
2a9813f
Compare
2a9813f to
9213320
Compare
…romPendingState Add an offline form that synthesizes IResolvedUrl/IUrlResolver/IDocumentServiceFactory from the URL captured in pendingLocalState. Online callers (all three driver props supplied) behave as before. Mixing the two forms is rejected with UsageError. IContainer.getAbsoluteUrl throws on offline-loaded containers since the resolver's external URL format is unknown. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
9213320 to
66f1d3d
Compare
- Document the offline-form URL shape requirement on ILoadFrozenContainerFromPendingStateProps: pendingLocalState.url must satisfy tryParseCompatibleResolvedUrl's contract (protocol://<string>/.../..?<querystring>), and non-standard resolved-URL shapes surface as UsageError at load time. Addresses the open deep-review comment on the offline JSDoc. - Add a missing local-server-tests case: capture-and-relay round-trip through a writable-offline frozen load (readOnly: false + no driver wiring), locking in the documented contract that local DDS submissions accrue in the runtime's pending-state manager and round-trip through getPendingLocalState() even when the driver wiring is fully synthesized. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ps interfaces - Add @internal validateAllOrNone<T>(obj, keys) to @fluidframework/core-utils, returning all | none | mixed for runtime validation of the compile-time AllOrNone<T> modifier. - Decompose ICreateAndLoadContainerProps into reusable building blocks: * IContainerHostProps (code loader + optional policy/observability) * IContainerDriverServices (urlResolver + documentServiceFactory) * IContainerLoadDriverProps (driver services + request) ICreateAndLoadContainerProps now composes IContainerHostProps and IContainerDriverServices; structural shape is unchanged. - Replace the Omit<ILoadExistingContainerProps, ...> in ILoadFrozenContainerFromPendingStateProps with composition: IContainerHostProps & { pendingLocalState; readOnly? } & AllOrNone<IContainerLoadDriverProps> - Wire the entry-point runtime check to validateAllOrNone instead of the hand-rolled all-defined/any-defined checks. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…eAndLoadContainerProps - Synthesized IResolvedUrl on offline loads now uses the trailing path segment of tryParseCompatibleResolvedUrl's two-segment 'tenantId/docId' id, matching the single-doc-id-segment shape that production resolvers emit (see localResolver.ts:58, odspDriverUrlResolver.ts:167, etc.). Downstream consumers keyed on IContainer.resolvedUrl.id for telemetry or cache keys now see the same shape on offline-loaded and online-loaded containers. - Add a spec assertion in loadFrozenContainerFromPendingState.spec.ts that pins frozenContainer.resolvedUrl.id to the expected single-segment value for the offline path, so the contract can't regress. - Mark ICreateAndLoadContainerProps as @deprecated, pointing callers at the composable building blocks IContainerHostProps and IContainerDriverServices. Migrate the three extending props types (ILoadExistingContainerProps, ICreateDetachedContainerProps, IRehydrateDetachedContainerProps) to extend the building blocks directly. The member set is unchanged so the interfaces remain structurally identical. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…rl hardening Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
🔗 No broken links found! ✅ Your attention to detail is admirable. linkcheck output |
Deep ReviewReviewed commit Readiness: 8/10 — ALMOST READY The prior cross-package changeset gap for Path to Ready
Context for Reviewers
For human reviewer
Review history (6 prior reviews)
|
| throw new UsageError( | ||
| "Attempted to read an attachment blob from a frozen-loaded container without a live storage service. " + | ||
| "Fully-offline frozen loads must use pending state produced by `captureFullContainerState`, which inlines all referenced attachment blobs.", | ||
| ); |
There was a problem hiding this comment.
Deep Review: This is an observable change to the @legacy @alpha surface that isn't called out in any changeset.
Pre-PR, frozenDocumentStorageServiceHandler threw new Error("Operations are not supported on the FrozenDocumentStorageService."). Post-PR the generic handler throws new UsageError(...) (different class), and readBlob is rebound to a new frozenReadBlobOfflineHandler that throws a dedicated UsageError whose message names captureFullContainerState explicitly.
The three changesets in this PR cover URL parsing (harden-try-parse-resolved-url.md), the ICreateAndLoadContainerProps deprecation (quiet-shrews-marry.md), and the AllOrNone / validateAllOrNone primitive (sweet-spiders-grow.md) — none mention this Error → UsageError class change or the new readBlob-specific message.
Suggested fix: append a sentence to quiet-shrews-marry.md (or land a fourth changeset) noting that FrozenDocumentStorageService operations now throw UsageError instead of Error, and that readBlob on a no-inner-storage frozen container throws a dedicated UsageError whose message names captureFullContainerState.
Description
Adds an "offline" form of
loadFrozenContainerFromPendingStatethat loads a frozen container entirely from the URL captured inpendingLocalState— noIRequest,IUrlResolver, orIDocumentServiceFactoryis supplied by the caller.ILoadFrozenContainerFromPendingStatePropsbecomes a discriminated union of two shapes, selected by the presence of the driver-wiring fields:request,urlResolver, anddocumentServiceFactory. The supplied factory is wrapped in a frozen factory and the resolver re-resolves the request just as today.IResolvedUrlfrompendingLocalState.url, anIUrlResolverwhoseresolve()returns that synthesized URL, and a no-inner frozenIDocumentServiceFactory. The existing pipeline (loadExistingContainer->Loader.resolve->Container.load) is reused unchanged — the identity guard inLoader.resolveCoreis trivially satisfied because the same URL string is on both sides of the compare.Mixing the two forms (some fields supplied, others omitted) is rejected at runtime with
UsageError.IContainer.getAbsoluteUrlthrows on an offline-loaded container, since the resolver's external (request-form) URL cannot be reconstructed from the captured resolved URL alone. Fabricating a string in the wrong format would mislead any caller that passed it back into a real resolver.No changes to
ContainerorLoaderwere required; all new behavior is composed at the entry-point layer increateAndLoadContainerUtils.ts.Reviewer Guidance
The review process is outlined on this wiki page.
interface->typechange onILoadFrozenContainerFromPendingStatePropsis required because TS does not allow widening an inherited required field (request/urlResolver/documentServiceFactory) to optional viaextends. The API is@legacy @alphaand was introduced one PR ago, so consumer impact is essentially zero.request.urlcarries a resolved-form URL where an external-form URL is normally expected. Nothing downstream inspects it before the synthesized resolver swallows it. Worth a sanity check that no future load-pipeline change starts depending onrequest.urlhaving external-form structure.loadFrozenContainerFromPendingState.spec.tscover: offline happy path,getAbsoluteUrlthrows, mixed-driver-wiring is rejected.