@fluidframework/container-loader 2.0.0-rc.2.0.2 → 2.0.0-rc.3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +33 -0
- package/api-report/container-loader.api.md +13 -13
- package/dist/attachment.d.ts +6 -9
- package/dist/attachment.d.ts.map +1 -1
- package/dist/attachment.js +5 -5
- package/dist/attachment.js.map +1 -1
- package/dist/audience.d.ts +1 -1
- package/dist/audience.d.ts.map +1 -1
- package/dist/audience.js +4 -4
- package/dist/audience.js.map +1 -1
- package/dist/catchUpMonitor.d.ts +1 -1
- package/dist/catchUpMonitor.d.ts.map +1 -1
- package/dist/catchUpMonitor.js +2 -2
- package/dist/catchUpMonitor.js.map +1 -1
- package/dist/connectionManager.d.ts +4 -4
- package/dist/connectionManager.d.ts.map +1 -1
- package/dist/connectionManager.js +48 -43
- package/dist/connectionManager.js.map +1 -1
- package/dist/connectionStateHandler.d.ts +3 -3
- package/dist/connectionStateHandler.d.ts.map +1 -1
- package/dist/connectionStateHandler.js +27 -27
- package/dist/connectionStateHandler.js.map +1 -1
- package/dist/container.d.ts +9 -46
- package/dist/container.d.ts.map +1 -1
- package/dist/container.js +105 -116
- package/dist/container.js.map +1 -1
- package/dist/containerContext.d.ts +19 -7
- package/dist/containerContext.d.ts.map +1 -1
- package/dist/containerContext.js +7 -2
- package/dist/containerContext.js.map +1 -1
- package/dist/containerStorageAdapter.d.ts +3 -3
- package/dist/containerStorageAdapter.d.ts.map +1 -1
- package/dist/containerStorageAdapter.js +6 -6
- package/dist/containerStorageAdapter.js.map +1 -1
- package/dist/contracts.d.ts +4 -3
- package/dist/contracts.d.ts.map +1 -1
- package/dist/contracts.js +2 -2
- package/dist/contracts.js.map +1 -1
- package/dist/debugLogger.d.ts +2 -1
- package/dist/debugLogger.d.ts.map +1 -1
- package/dist/debugLogger.js +4 -4
- package/dist/debugLogger.js.map +1 -1
- package/dist/deltaManager.d.ts +11 -7
- package/dist/deltaManager.d.ts.map +1 -1
- package/dist/deltaManager.js +53 -50
- package/dist/deltaManager.js.map +1 -1
- package/dist/deltaQueue.d.ts +1 -1
- package/dist/deltaQueue.d.ts.map +1 -1
- package/dist/deltaQueue.js +5 -5
- package/dist/deltaQueue.js.map +1 -1
- package/dist/error.d.ts +3 -2
- package/dist/error.d.ts.map +1 -1
- package/dist/error.js +5 -5
- package/dist/error.js.map +1 -1
- package/dist/legacy.d.ts +29 -0
- package/dist/loader.d.ts +4 -4
- package/dist/loader.d.ts.map +1 -1
- package/dist/loader.js +23 -23
- package/dist/loader.js.map +1 -1
- package/dist/location-redirection-utilities/resolveWithLocationRedirection.d.ts +2 -2
- package/dist/location-redirection-utilities/resolveWithLocationRedirection.d.ts.map +1 -1
- package/dist/location-redirection-utilities/resolveWithLocationRedirection.js +2 -2
- package/dist/location-redirection-utilities/resolveWithLocationRedirection.js.map +1 -1
- package/dist/noopHeuristic.d.ts +1 -1
- package/dist/noopHeuristic.d.ts.map +1 -1
- package/dist/noopHeuristic.js +6 -6
- package/dist/noopHeuristic.js.map +1 -1
- package/dist/packageVersion.d.ts +1 -1
- package/dist/packageVersion.js +1 -1
- package/dist/packageVersion.js.map +1 -1
- package/dist/protocol.d.ts +1 -1
- package/dist/protocol.d.ts.map +1 -1
- package/dist/protocol.js +2 -2
- package/dist/protocol.js.map +1 -1
- package/dist/protocolTreeDocumentStorageService.d.ts +4 -4
- package/dist/protocolTreeDocumentStorageService.d.ts.map +1 -1
- package/dist/protocolTreeDocumentStorageService.js.map +1 -1
- package/dist/public.d.ts +14 -0
- package/dist/quorum.d.ts +1 -1
- package/dist/quorum.d.ts.map +1 -1
- package/dist/quorum.js +4 -0
- package/dist/quorum.js.map +1 -1
- package/dist/retriableDocumentStorageService.d.ts +2 -2
- package/dist/retriableDocumentStorageService.d.ts.map +1 -1
- package/dist/retriableDocumentStorageService.js +7 -7
- package/dist/retriableDocumentStorageService.js.map +1 -1
- package/dist/serializedStateManager.d.ts +86 -16
- package/dist/serializedStateManager.d.ts.map +1 -1
- package/dist/serializedStateManager.js +182 -82
- package/dist/serializedStateManager.js.map +1 -1
- package/dist/utils.d.ts +24 -9
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +82 -25
- package/dist/utils.js.map +1 -1
- package/internal.d.ts +11 -0
- package/legacy.d.ts +11 -0
- package/lib/attachment.d.ts +6 -9
- package/lib/attachment.d.ts.map +1 -1
- package/lib/attachment.js +1 -1
- package/lib/attachment.js.map +1 -1
- package/lib/audience.d.ts +1 -1
- package/lib/audience.d.ts.map +1 -1
- package/lib/audience.js +1 -1
- package/lib/audience.js.map +1 -1
- package/lib/catchUpMonitor.d.ts +1 -1
- package/lib/catchUpMonitor.d.ts.map +1 -1
- package/lib/catchUpMonitor.js +1 -1
- package/lib/catchUpMonitor.js.map +1 -1
- package/lib/connectionManager.d.ts +4 -4
- package/lib/connectionManager.d.ts.map +1 -1
- package/lib/connectionManager.js +11 -6
- package/lib/connectionManager.js.map +1 -1
- package/lib/connectionStateHandler.d.ts +3 -3
- package/lib/connectionStateHandler.d.ts.map +1 -1
- package/lib/connectionStateHandler.js +2 -2
- package/lib/connectionStateHandler.js.map +1 -1
- package/lib/container.d.ts +9 -46
- package/lib/container.d.ts.map +1 -1
- package/lib/container.js +37 -48
- package/lib/container.js.map +1 -1
- package/lib/containerContext.d.ts +19 -7
- package/lib/containerContext.d.ts.map +1 -1
- package/lib/containerContext.js +7 -2
- package/lib/containerContext.js.map +1 -1
- package/lib/containerStorageAdapter.d.ts +3 -3
- package/lib/containerStorageAdapter.d.ts.map +1 -1
- package/lib/containerStorageAdapter.js +2 -2
- package/lib/containerStorageAdapter.js.map +1 -1
- package/lib/contracts.d.ts +4 -3
- package/lib/contracts.d.ts.map +1 -1
- package/lib/contracts.js +1 -1
- package/lib/contracts.js.map +1 -1
- package/lib/debugLogger.d.ts +2 -1
- package/lib/debugLogger.d.ts.map +1 -1
- package/lib/debugLogger.js +1 -1
- package/lib/debugLogger.js.map +1 -1
- package/lib/deltaManager.d.ts +11 -7
- package/lib/deltaManager.d.ts.map +1 -1
- package/lib/deltaManager.js +13 -10
- package/lib/deltaManager.js.map +1 -1
- package/lib/deltaQueue.d.ts +1 -1
- package/lib/deltaQueue.d.ts.map +1 -1
- package/lib/deltaQueue.js +2 -2
- package/lib/deltaQueue.js.map +1 -1
- package/lib/error.d.ts +3 -2
- package/lib/error.d.ts.map +1 -1
- package/lib/error.js +2 -2
- package/lib/error.js.map +1 -1
- package/lib/legacy.d.ts +29 -0
- package/lib/loader.d.ts +4 -4
- package/lib/loader.d.ts.map +1 -1
- package/lib/loader.js +4 -4
- package/lib/loader.js.map +1 -1
- package/lib/location-redirection-utilities/resolveWithLocationRedirection.d.ts +2 -2
- package/lib/location-redirection-utilities/resolveWithLocationRedirection.d.ts.map +1 -1
- package/lib/location-redirection-utilities/resolveWithLocationRedirection.js +2 -2
- package/lib/location-redirection-utilities/resolveWithLocationRedirection.js.map +1 -1
- package/lib/noopHeuristic.d.ts +1 -1
- package/lib/noopHeuristic.d.ts.map +1 -1
- package/lib/noopHeuristic.js +2 -2
- package/lib/noopHeuristic.js.map +1 -1
- package/lib/packageVersion.d.ts +1 -1
- package/lib/packageVersion.js +1 -1
- package/lib/packageVersion.js.map +1 -1
- package/lib/protocol.d.ts +1 -1
- package/lib/protocol.d.ts.map +1 -1
- package/lib/protocol.js +1 -1
- package/lib/protocol.js.map +1 -1
- package/lib/protocolTreeDocumentStorageService.d.ts +4 -4
- package/lib/protocolTreeDocumentStorageService.d.ts.map +1 -1
- package/lib/protocolTreeDocumentStorageService.js.map +1 -1
- package/lib/public.d.ts +14 -0
- package/lib/quorum.d.ts +1 -1
- package/lib/quorum.d.ts.map +1 -1
- package/lib/quorum.js +4 -0
- package/lib/quorum.js.map +1 -1
- package/lib/retriableDocumentStorageService.d.ts +2 -2
- package/lib/retriableDocumentStorageService.d.ts.map +1 -1
- package/lib/retriableDocumentStorageService.js +3 -3
- package/lib/retriableDocumentStorageService.js.map +1 -1
- package/lib/serializedStateManager.d.ts +86 -16
- package/lib/serializedStateManager.d.ts.map +1 -1
- package/lib/serializedStateManager.js +174 -77
- package/lib/serializedStateManager.js.map +1 -1
- package/lib/utils.d.ts +24 -9
- package/lib/utils.d.ts.map +1 -1
- package/lib/utils.js +69 -15
- package/lib/utils.js.map +1 -1
- package/package.json +37 -58
- package/src/attachment.ts +10 -8
- package/src/audience.ts +3 -2
- package/src/catchUpMonitor.ts +2 -2
- package/src/connectionManager.ts +27 -20
- package/src/connectionStateHandler.ts +7 -7
- package/src/container.ts +90 -143
- package/src/containerContext.ts +22 -12
- package/src/containerStorageAdapter.ts +7 -6
- package/src/contracts.ts +4 -5
- package/src/debugLogger.ts +3 -4
- package/src/deltaManager.ts +40 -30
- package/src/deltaQueue.ts +2 -2
- package/src/error.ts +5 -4
- package/src/loader.ts +25 -23
- package/src/location-redirection-utilities/resolveWithLocationRedirection.ts +4 -4
- package/src/noopHeuristic.ts +3 -3
- package/src/packageVersion.ts +1 -1
- package/src/protocol.ts +2 -2
- package/src/protocolTreeDocumentStorageService.ts +4 -1
- package/src/quorum.ts +2 -1
- package/src/retriableDocumentStorageService.ts +6 -5
- package/src/serializedStateManager.ts +299 -111
- package/src/utils.ts +103 -24
- package/api-extractor-cjs.json +0 -8
- package/dist/container-loader-alpha.d.ts +0 -275
- package/dist/container-loader-beta.d.ts +0 -101
- package/dist/container-loader-public.d.ts +0 -101
- package/dist/container-loader-untrimmed.d.ts +0 -331
- package/lib/container-loader-alpha.d.ts +0 -275
- package/lib/container-loader-beta.d.ts +0 -101
- package/lib/container-loader-public.d.ts +0 -101
- package/lib/container-loader-untrimmed.d.ts +0 -331
- package/lib/test/attachment.spec.js +0 -380
- package/lib/test/attachment.spec.js.map +0 -1
- package/lib/test/catchUpMonitor.spec.js +0 -88
- package/lib/test/catchUpMonitor.spec.js.map +0 -1
- package/lib/test/connectionManager.spec.js +0 -201
- package/lib/test/connectionManager.spec.js.map +0 -1
- package/lib/test/connectionStateHandler.spec.js +0 -555
- package/lib/test/connectionStateHandler.spec.js.map +0 -1
- package/lib/test/container.spec.js +0 -64
- package/lib/test/container.spec.js.map +0 -1
- package/lib/test/deltaManager.spec.js +0 -405
- package/lib/test/deltaManager.spec.js.map +0 -1
- package/lib/test/loader.spec.js +0 -212
- package/lib/test/loader.spec.js.map +0 -1
- package/lib/test/locationRedirectionTests.spec.js +0 -44
- package/lib/test/locationRedirectionTests.spec.js.map +0 -1
- package/lib/test/serializedStateManager.spec.js +0 -148
- package/lib/test/serializedStateManager.spec.js.map +0 -1
- package/lib/test/snapshotConversionTest.spec.js +0 -79
- package/lib/test/snapshotConversionTest.spec.js.map +0 -1
- package/lib/test/types/validateContainerLoaderPrevious.generated.js +0 -38
- package/lib/test/types/validateContainerLoaderPrevious.generated.js.map +0 -1
- package/lib/test/utils.spec.js +0 -31
- package/lib/test/utils.spec.js.map +0 -1
- /package/{dist → lib}/tsdoc-metadata.json +0 -0
|
@@ -2,43 +2,113 @@
|
|
|
2
2
|
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
|
+
import { IGetPendingLocalStateProps, IRuntime } from "@fluidframework/container-definitions/internal";
|
|
6
|
+
import { IDocumentStorageService, IResolvedUrl, ISnapshot } from "@fluidframework/driver-definitions/internal";
|
|
5
7
|
import { ISequencedDocumentMessage, ISnapshotTree, IVersion } from "@fluidframework/protocol-definitions";
|
|
6
|
-
import { IGetPendingLocalStateProps, IRuntime } from "@fluidframework/container-definitions";
|
|
7
8
|
import { ITelemetryLoggerExt } from "@fluidframework/telemetry-utils";
|
|
8
|
-
import {
|
|
9
|
+
import { MonitoringContext } from "@fluidframework/telemetry-utils/internal";
|
|
9
10
|
import { ISerializableBlobContents } from "./containerStorageAdapter.js";
|
|
10
|
-
|
|
11
|
+
export interface SnapshotWithBlobs {
|
|
12
|
+
/**
|
|
13
|
+
* Snapshot from which container initially loaded.
|
|
14
|
+
*/
|
|
15
|
+
baseSnapshot: ISnapshotTree;
|
|
16
|
+
/**
|
|
17
|
+
* Serializable blobs from the base snapshot. Used to load offline since
|
|
18
|
+
* storage is not available.
|
|
19
|
+
*/
|
|
20
|
+
snapshotBlobs: ISerializableBlobContents;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* State saved by a container at close time, to be used to load a new instance
|
|
24
|
+
* of the container to the same state
|
|
25
|
+
* @internal
|
|
26
|
+
*/
|
|
27
|
+
export interface IPendingContainerState extends SnapshotWithBlobs {
|
|
28
|
+
attached: true;
|
|
29
|
+
pendingRuntimeState: unknown;
|
|
30
|
+
/**
|
|
31
|
+
* All ops since base snapshot sequence number up to the latest op
|
|
32
|
+
* seen when the container was closed. Used to apply stashed (saved pending)
|
|
33
|
+
* ops at the same sequence number at which they were made.
|
|
34
|
+
*/
|
|
35
|
+
savedOps: ISequencedDocumentMessage[];
|
|
36
|
+
url: string;
|
|
37
|
+
clientId?: string;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* State saved by a container in detached state, to be used to load a new instance
|
|
41
|
+
* of the container to the same state (rehydrate)
|
|
42
|
+
* @internal
|
|
43
|
+
*/
|
|
44
|
+
export interface IPendingDetachedContainerState extends SnapshotWithBlobs {
|
|
45
|
+
attached: false;
|
|
46
|
+
hasAttachmentBlobs: boolean;
|
|
47
|
+
pendingRuntimeState?: unknown;
|
|
48
|
+
}
|
|
49
|
+
export interface ISnapshotInfo extends SnapshotWithBlobs {
|
|
50
|
+
snapshotSequenceNumber: number;
|
|
51
|
+
}
|
|
11
52
|
export declare class SerializedStateManager {
|
|
12
53
|
private readonly pendingLocalState;
|
|
13
54
|
private readonly storageAdapter;
|
|
14
55
|
private readonly _offlineLoadEnabled;
|
|
56
|
+
private readonly newSnapshotFetched?;
|
|
15
57
|
private readonly processedOps;
|
|
16
58
|
private snapshot;
|
|
17
59
|
private readonly mc;
|
|
18
|
-
|
|
60
|
+
private latestSnapshot;
|
|
61
|
+
private refreshSnapshot;
|
|
62
|
+
constructor(pendingLocalState: IPendingContainerState | undefined, subLogger: ITelemetryLoggerExt, storageAdapter: Pick<IDocumentStorageService, "readBlob" | "getSnapshotTree" | "getSnapshot" | "getVersions">, _offlineLoadEnabled: boolean, newSnapshotFetched?: (() => void) | undefined);
|
|
19
63
|
get offlineLoadEnabled(): boolean;
|
|
20
64
|
addProcessedOp(message: ISequencedDocumentMessage): void;
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
snapshotTree: ISnapshotTree | undefined;
|
|
65
|
+
fetchSnapshot(specifiedVersion: string | undefined, supportGetSnapshotApi: boolean): Promise<{
|
|
66
|
+
baseSnapshot: ISnapshotTree;
|
|
24
67
|
version: IVersion | undefined;
|
|
25
68
|
}>;
|
|
26
|
-
private fetchSnapshotCore;
|
|
27
69
|
/**
|
|
28
|
-
*
|
|
29
|
-
* @param specifiedVersion - The specific version of the snapshot to retrieve
|
|
30
|
-
* @returns The snapshot requested, or the latest snapshot if no version was specified, plus version ID
|
|
70
|
+
* Updates class snapshot and processedOps if we have a new snapshot and it's among processedOps range.
|
|
31
71
|
*/
|
|
32
|
-
private
|
|
72
|
+
private updateSnapshotAndProcessedOpsMaybe;
|
|
33
73
|
/**
|
|
34
74
|
* This method is only meant to be used by Container.attach() to set the initial
|
|
35
75
|
* base snapshot when attaching.
|
|
36
76
|
* @param snapshot - snapshot and blobs collected while attaching
|
|
37
77
|
*/
|
|
38
|
-
|
|
39
|
-
tree: ISnapshotTree;
|
|
40
|
-
blobs: ISerializableBlobContents;
|
|
41
|
-
} | undefined): void;
|
|
78
|
+
setInitialSnapshot(snapshot: SnapshotWithBlobs | undefined): void;
|
|
42
79
|
getPendingLocalStateCore(props: IGetPendingLocalStateProps, clientId: string | undefined, runtime: Pick<IRuntime, "getPendingLocalState">, resolvedUrl: IResolvedUrl): Promise<string>;
|
|
43
80
|
}
|
|
81
|
+
/**
|
|
82
|
+
* Retrieves the most recent snapshot and returns its info.
|
|
83
|
+
*
|
|
84
|
+
* @param mc - The monitoring context.
|
|
85
|
+
* @param storageAdapter - The storage adapter providing methods to retrieve the snapshot.
|
|
86
|
+
* @param supportGetSnapshotApi - a boolean indicating whether to use the fetchISnapshot or fetchISnapshotTree.
|
|
87
|
+
* @returns a SnapshotInfo object containing the snapshot tree, snapshot blobs and its sequence number.
|
|
88
|
+
*/
|
|
89
|
+
export declare function getLatestSnapshotInfo(mc: MonitoringContext, storageAdapter: Pick<IDocumentStorageService, "getSnapshot" | "getSnapshotTree" | "getVersions" | "readBlob">, supportGetSnapshotApi: boolean): Promise<ISnapshotInfo | undefined>;
|
|
90
|
+
/**
|
|
91
|
+
* Fetches an ISnapshot from a storage adapter based on the specified version.
|
|
92
|
+
*
|
|
93
|
+
* @param mc - The monitoring context.
|
|
94
|
+
* @param storageAdapter - The storage adapter providing a getSnapshot method to retrieve the ISnapshot and version.
|
|
95
|
+
* @param specifiedVersion - An optional version string specifying the version of the snapshot tree to fetch.
|
|
96
|
+
* @returns - The fetched snapshot tree and its version.
|
|
97
|
+
*/
|
|
98
|
+
export declare function fetchISnapshot(mc: MonitoringContext, storageAdapter: Pick<IDocumentStorageService, "getSnapshot">, specifiedVersion: string | undefined): Promise<{
|
|
99
|
+
snapshot?: ISnapshot;
|
|
100
|
+
version?: IVersion;
|
|
101
|
+
}>;
|
|
102
|
+
/**
|
|
103
|
+
* Fetches an ISnapshotTree from a storage adapter based on the specified version.
|
|
104
|
+
*
|
|
105
|
+
* @param mc - The monitoring context.
|
|
106
|
+
* @param storageAdapter - The storage adapter providing methods to retrieve the ISnapshotTree and version.
|
|
107
|
+
* @param specifiedVersion - An optional version string specifying the version of the snapshot tree to fetch.
|
|
108
|
+
* @returns - The fetched snapshot tree and its version.
|
|
109
|
+
*/
|
|
110
|
+
export declare function fetchISnapshotTree(mc: MonitoringContext, storageAdapter: Pick<IDocumentStorageService, "getSnapshotTree" | "getVersions">, specifiedVersion: string | undefined): Promise<{
|
|
111
|
+
snapshot?: ISnapshotTree;
|
|
112
|
+
version?: IVersion | undefined;
|
|
113
|
+
}>;
|
|
44
114
|
//# sourceMappingURL=serializedStateManager.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"serializedStateManager.d.ts","sourceRoot":"","sources":["../src/serializedStateManager.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACN,yBAAyB,EACzB,aAAa,EACb,QAAQ,EACR,MAAM,sCAAsC,CAAC;AAC9C,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"serializedStateManager.d.ts","sourceRoot":"","sources":["../src/serializedStateManager.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,15 +2,17 @@
|
|
|
2
2
|
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
5
|
+
import { assert } from "@fluidframework/core-utils/internal";
|
|
6
|
+
import { isInstanceOfISnapshot } from "@fluidframework/driver-utils/internal";
|
|
7
|
+
import { PerformanceEvent, UsageError, createChildMonitoringContext, } from "@fluidframework/telemetry-utils/internal";
|
|
8
8
|
import { getBlobContentsFromTree } from "./containerStorageAdapter.js";
|
|
9
|
+
import { getDocumentAttributes } from "./utils.js";
|
|
9
10
|
export class SerializedStateManager {
|
|
10
|
-
constructor(pendingLocalState, subLogger, storageAdapter, _offlineLoadEnabled) {
|
|
11
|
+
constructor(pendingLocalState, subLogger, storageAdapter, _offlineLoadEnabled, newSnapshotFetched) {
|
|
11
12
|
this.pendingLocalState = pendingLocalState;
|
|
12
13
|
this.storageAdapter = storageAdapter;
|
|
13
14
|
this._offlineLoadEnabled = _offlineLoadEnabled;
|
|
15
|
+
this.newSnapshotFetched = newSnapshotFetched;
|
|
14
16
|
this.processedOps = [];
|
|
15
17
|
this.mc = createChildMonitoringContext({
|
|
16
18
|
logger: subLogger,
|
|
@@ -23,98 +25,97 @@ export class SerializedStateManager {
|
|
|
23
25
|
addProcessedOp(message) {
|
|
24
26
|
if (this.offlineLoadEnabled) {
|
|
25
27
|
this.processedOps.push(message);
|
|
28
|
+
this.updateSnapshotAndProcessedOpsMaybe();
|
|
26
29
|
}
|
|
27
30
|
}
|
|
28
|
-
async getVersion(version) {
|
|
29
|
-
const versions = await this.storageAdapter.getVersions(version, 1);
|
|
30
|
-
return versions[0];
|
|
31
|
-
}
|
|
32
31
|
async fetchSnapshot(specifiedVersion, supportGetSnapshotApi) {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
: { snapshot: this.pendingLocalState.baseSnapshot, version: undefined };
|
|
36
|
-
const snapshotTree = isInstanceOfISnapshot(snapshot)
|
|
37
|
-
? snapshot.snapshotTree
|
|
38
|
-
: snapshot;
|
|
39
|
-
if (this.pendingLocalState) {
|
|
40
|
-
this.snapshot = {
|
|
41
|
-
tree: this.pendingLocalState.baseSnapshot,
|
|
42
|
-
blobs: this.pendingLocalState.snapshotBlobs,
|
|
43
|
-
};
|
|
44
|
-
}
|
|
45
|
-
else {
|
|
46
|
-
assert(snapshotTree !== undefined, 0x8e4 /* Snapshot should exist */);
|
|
32
|
+
if (this.pendingLocalState === undefined) {
|
|
33
|
+
const { baseSnapshot, version } = await getSnapshotTree(this.mc, this.storageAdapter, supportGetSnapshotApi, specifiedVersion);
|
|
47
34
|
// non-interactive clients will not have any pending state we want to save
|
|
48
35
|
if (this.offlineLoadEnabled) {
|
|
49
|
-
const
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
async fetchSnapshotCore(specifiedVersion, supportGetSnapshotApi) {
|
|
56
|
-
if (this.mc.config.getBoolean("Fluid.Container.UseLoadingGroupIdForSnapshotFetch") ===
|
|
57
|
-
true &&
|
|
58
|
-
supportGetSnapshotApi === true) {
|
|
59
|
-
const snapshot = (await this.storageAdapter.getSnapshot?.({
|
|
60
|
-
versionId: specifiedVersion,
|
|
61
|
-
})) ?? undefined;
|
|
62
|
-
const version = snapshot?.snapshotTree.id === undefined
|
|
63
|
-
? undefined
|
|
64
|
-
: {
|
|
65
|
-
id: snapshot.snapshotTree.id,
|
|
66
|
-
treeId: snapshot.snapshotTree.id,
|
|
36
|
+
const snapshotBlobs = await getBlobContentsFromTree(baseSnapshot, this.storageAdapter);
|
|
37
|
+
const attributes = await getDocumentAttributes(this.storageAdapter, baseSnapshot);
|
|
38
|
+
this.snapshot = {
|
|
39
|
+
baseSnapshot,
|
|
40
|
+
snapshotBlobs,
|
|
41
|
+
snapshotSequenceNumber: attributes.sequenceNumber,
|
|
67
42
|
};
|
|
68
|
-
if (snapshot === undefined && specifiedVersion !== undefined) {
|
|
69
|
-
this.mc.logger.sendErrorEvent({
|
|
70
|
-
eventName: "getSnapshotTreeFailed",
|
|
71
|
-
id: specifiedVersion,
|
|
72
|
-
});
|
|
73
|
-
// Not sure if this should be here actually
|
|
74
|
-
}
|
|
75
|
-
else if (snapshot !== undefined && version?.id === undefined) {
|
|
76
|
-
this.mc.logger.sendErrorEvent({
|
|
77
|
-
eventName: "getSnapshotFetchedTreeWithoutVersionId",
|
|
78
|
-
hasVersion: version !== undefined, // if hasVersion is true, this means that the contract with the service was broken.
|
|
79
|
-
});
|
|
80
43
|
}
|
|
81
|
-
return {
|
|
44
|
+
return { baseSnapshot, version };
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
const { baseSnapshot, snapshotBlobs } = this.pendingLocalState;
|
|
48
|
+
const attributes = await getDocumentAttributes(this.storageAdapter, baseSnapshot);
|
|
49
|
+
this.snapshot = {
|
|
50
|
+
baseSnapshot,
|
|
51
|
+
snapshotBlobs,
|
|
52
|
+
snapshotSequenceNumber: attributes.sequenceNumber,
|
|
53
|
+
};
|
|
54
|
+
this.refreshSnapshot ?? (this.refreshSnapshot = (async () => {
|
|
55
|
+
this.latestSnapshot = await getLatestSnapshotInfo(this.mc, this.storageAdapter, supportGetSnapshotApi);
|
|
56
|
+
this.newSnapshotFetched?.();
|
|
57
|
+
this.updateSnapshotAndProcessedOpsMaybe();
|
|
58
|
+
})());
|
|
59
|
+
return { baseSnapshot, version: undefined };
|
|
82
60
|
}
|
|
83
|
-
return this.fetchSnapshotTree(specifiedVersion);
|
|
84
61
|
}
|
|
85
62
|
/**
|
|
86
|
-
*
|
|
87
|
-
* @param specifiedVersion - The specific version of the snapshot to retrieve
|
|
88
|
-
* @returns The snapshot requested, or the latest snapshot if no version was specified, plus version ID
|
|
63
|
+
* Updates class snapshot and processedOps if we have a new snapshot and it's among processedOps range.
|
|
89
64
|
*/
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
//
|
|
94
|
-
|
|
95
|
-
eventName: "NoVersionFoundWhenSpecified",
|
|
96
|
-
id: specifiedVersion,
|
|
97
|
-
});
|
|
65
|
+
updateSnapshotAndProcessedOpsMaybe() {
|
|
66
|
+
if (this.latestSnapshot === undefined || this.processedOps.length === 0) {
|
|
67
|
+
// can't refresh latest snapshot until we have processed the ops up to it.
|
|
68
|
+
// Pending state would be behind the latest snapshot.
|
|
69
|
+
return;
|
|
98
70
|
}
|
|
99
|
-
const
|
|
100
|
-
|
|
101
|
-
|
|
71
|
+
const snapshotSequenceNumber = this.latestSnapshot.snapshotSequenceNumber;
|
|
72
|
+
const firstProcessedOpSequenceNumber = this.processedOps[0].sequenceNumber;
|
|
73
|
+
const lastProcessedOpSequenceNumber = this.processedOps[this.processedOps.length - 1].sequenceNumber;
|
|
74
|
+
if (snapshotSequenceNumber < firstProcessedOpSequenceNumber) {
|
|
75
|
+
// Snapshot seq number is older than our first processed op, which could mean we're fetching
|
|
76
|
+
// the same snapshot that we already have or snapshot is too old, implicating an unexpected behavior.
|
|
77
|
+
this.mc.logger.sendTelemetryEvent({
|
|
78
|
+
eventName: "OldSnapshotFetchWhileRefreshing",
|
|
79
|
+
snapshotSequenceNumber,
|
|
80
|
+
firstProcessedOpSequenceNumber,
|
|
81
|
+
lastProcessedOpSequenceNumber,
|
|
82
|
+
stashedSnapshotSequenceNumber: this.snapshot?.snapshotSequenceNumber,
|
|
83
|
+
});
|
|
84
|
+
this.latestSnapshot = undefined;
|
|
102
85
|
}
|
|
103
|
-
else if (
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
86
|
+
else if (snapshotSequenceNumber <= lastProcessedOpSequenceNumber) {
|
|
87
|
+
// Snapshot seq num is between the first and last processed op.
|
|
88
|
+
// Remove the ops that are already part of the snapshot
|
|
89
|
+
this.processedOps.splice(0, snapshotSequenceNumber - firstProcessedOpSequenceNumber + 1);
|
|
90
|
+
this.snapshot = this.latestSnapshot;
|
|
91
|
+
this.latestSnapshot = undefined;
|
|
92
|
+
this.mc.logger.sendTelemetryEvent({
|
|
93
|
+
eventName: "SnapshotRefreshed",
|
|
94
|
+
snapshotSequenceNumber,
|
|
95
|
+
firstProcessedOpSequenceNumber,
|
|
96
|
+
newFirstProcessedOpSequenceNumber: this.processedOps.length === 0
|
|
97
|
+
? undefined
|
|
98
|
+
: this.processedOps[0].sequenceNumber,
|
|
107
99
|
});
|
|
108
100
|
}
|
|
109
|
-
return { snapshot, version };
|
|
110
101
|
}
|
|
111
102
|
/**
|
|
112
103
|
* This method is only meant to be used by Container.attach() to set the initial
|
|
113
104
|
* base snapshot when attaching.
|
|
114
105
|
* @param snapshot - snapshot and blobs collected while attaching
|
|
115
106
|
*/
|
|
116
|
-
|
|
117
|
-
this.
|
|
107
|
+
setInitialSnapshot(snapshot) {
|
|
108
|
+
if (this.offlineLoadEnabled) {
|
|
109
|
+
assert(this.snapshot === undefined, 0x937 /* inital snapshot should only be defined once */);
|
|
110
|
+
assert(snapshot !== undefined, 0x938 /* attachment snapshot should be defined */);
|
|
111
|
+
const { baseSnapshot, snapshotBlobs } = snapshot;
|
|
112
|
+
const attributesHash = ".protocol" in baseSnapshot.trees
|
|
113
|
+
? baseSnapshot.trees[".protocol"].blobs.attributes
|
|
114
|
+
: baseSnapshot.blobs[".attributes"];
|
|
115
|
+
const attributes = JSON.parse(snapshotBlobs[attributesHash]);
|
|
116
|
+
assert(attributes.sequenceNumber === 0, 0x939 /* trying to set a non attachment snapshot */);
|
|
117
|
+
this.snapshot = { ...snapshot, snapshotSequenceNumber: attributes.sequenceNumber };
|
|
118
|
+
}
|
|
118
119
|
}
|
|
119
120
|
async getPendingLocalStateCore(props, clientId, runtime, resolvedUrl) {
|
|
120
121
|
return PerformanceEvent.timedExecAsync(this.mc.logger, {
|
|
@@ -131,8 +132,8 @@ export class SerializedStateManager {
|
|
|
131
132
|
const pendingState = {
|
|
132
133
|
attached: true,
|
|
133
134
|
pendingRuntimeState,
|
|
134
|
-
baseSnapshot: this.snapshot.
|
|
135
|
-
snapshotBlobs: this.snapshot.
|
|
135
|
+
baseSnapshot: this.snapshot.baseSnapshot,
|
|
136
|
+
snapshotBlobs: this.snapshot.snapshotBlobs,
|
|
136
137
|
savedOps: this.processedOps,
|
|
137
138
|
url: resolvedUrl.url,
|
|
138
139
|
// no need to save this if there is no pending runtime state
|
|
@@ -142,4 +143,100 @@ export class SerializedStateManager {
|
|
|
142
143
|
});
|
|
143
144
|
}
|
|
144
145
|
}
|
|
146
|
+
/**
|
|
147
|
+
* Retrieves the most recent snapshot and returns its info.
|
|
148
|
+
*
|
|
149
|
+
* @param mc - The monitoring context.
|
|
150
|
+
* @param storageAdapter - The storage adapter providing methods to retrieve the snapshot.
|
|
151
|
+
* @param supportGetSnapshotApi - a boolean indicating whether to use the fetchISnapshot or fetchISnapshotTree.
|
|
152
|
+
* @returns a SnapshotInfo object containing the snapshot tree, snapshot blobs and its sequence number.
|
|
153
|
+
*/
|
|
154
|
+
export async function getLatestSnapshotInfo(mc, storageAdapter, supportGetSnapshotApi) {
|
|
155
|
+
return PerformanceEvent.timedExecAsync(mc.logger, { eventName: "GetLatestSnapshotInfo" }, async () => {
|
|
156
|
+
const { baseSnapshot } = await getSnapshotTree(mc, storageAdapter, supportGetSnapshotApi, undefined);
|
|
157
|
+
const snapshotBlobs = await getBlobContentsFromTree(baseSnapshot, storageAdapter);
|
|
158
|
+
const attributes = await getDocumentAttributes(storageAdapter, baseSnapshot);
|
|
159
|
+
const snapshotSequenceNumber = attributes.sequenceNumber;
|
|
160
|
+
return { baseSnapshot, snapshotBlobs, snapshotSequenceNumber };
|
|
161
|
+
}).catch(() => undefined);
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Retrieves a snapshot from the storage adapter and transforms it into an ISnapshotTree object.
|
|
165
|
+
*
|
|
166
|
+
* @param mc - The monitoring context.
|
|
167
|
+
* @param storageAdapter - The storage adapter providing methods to retrieve the snapshot.
|
|
168
|
+
* @param supportGetSnapshotApi - a boolean indicating whether to use the fetchISnapshot or fetchISnapshotTree.
|
|
169
|
+
* @param specifiedVersion - An optional version string specifying the version of the snapshot tree to fetch.
|
|
170
|
+
* @returns - An ISnapshotTree and its version.
|
|
171
|
+
*/
|
|
172
|
+
async function getSnapshotTree(mc, storageAdapter, supportGetSnapshotApi, specifiedVersion) {
|
|
173
|
+
const { snapshot, version } = supportGetSnapshotApi
|
|
174
|
+
? await fetchISnapshot(mc, storageAdapter, specifiedVersion)
|
|
175
|
+
: await fetchISnapshotTree(mc, storageAdapter, specifiedVersion);
|
|
176
|
+
const baseSnapshot = isInstanceOfISnapshot(snapshot)
|
|
177
|
+
? snapshot.snapshotTree
|
|
178
|
+
: snapshot;
|
|
179
|
+
assert(baseSnapshot !== undefined, 0x8e4 /* Snapshot should exist */);
|
|
180
|
+
return { baseSnapshot, version };
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Fetches an ISnapshot from a storage adapter based on the specified version.
|
|
184
|
+
*
|
|
185
|
+
* @param mc - The monitoring context.
|
|
186
|
+
* @param storageAdapter - The storage adapter providing a getSnapshot method to retrieve the ISnapshot and version.
|
|
187
|
+
* @param specifiedVersion - An optional version string specifying the version of the snapshot tree to fetch.
|
|
188
|
+
* @returns - The fetched snapshot tree and its version.
|
|
189
|
+
*/
|
|
190
|
+
export async function fetchISnapshot(mc, storageAdapter, specifiedVersion) {
|
|
191
|
+
const snapshot = await storageAdapter.getSnapshot?.({ versionId: specifiedVersion });
|
|
192
|
+
const version = snapshot?.snapshotTree.id === undefined
|
|
193
|
+
? undefined
|
|
194
|
+
: {
|
|
195
|
+
id: snapshot.snapshotTree.id,
|
|
196
|
+
treeId: snapshot.snapshotTree.id,
|
|
197
|
+
};
|
|
198
|
+
if (snapshot === undefined && specifiedVersion !== undefined) {
|
|
199
|
+
mc.logger.sendErrorEvent({
|
|
200
|
+
eventName: "getSnapshotTreeFailed",
|
|
201
|
+
id: specifiedVersion,
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
else if (snapshot !== undefined && version?.id === undefined) {
|
|
205
|
+
mc.logger.sendErrorEvent({
|
|
206
|
+
eventName: "getSnapshotFetchedTreeWithoutVersionId",
|
|
207
|
+
hasVersion: version !== undefined, // if hasVersion is true, this means that the contract with the service was broken.
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
return { snapshot, version };
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Fetches an ISnapshotTree from a storage adapter based on the specified version.
|
|
214
|
+
*
|
|
215
|
+
* @param mc - The monitoring context.
|
|
216
|
+
* @param storageAdapter - The storage adapter providing methods to retrieve the ISnapshotTree and version.
|
|
217
|
+
* @param specifiedVersion - An optional version string specifying the version of the snapshot tree to fetch.
|
|
218
|
+
* @returns - The fetched snapshot tree and its version.
|
|
219
|
+
*/
|
|
220
|
+
export async function fetchISnapshotTree(mc, storageAdapter, specifiedVersion) {
|
|
221
|
+
const versions = await storageAdapter.getVersions(specifiedVersion ?? null, 1);
|
|
222
|
+
const version = versions[0];
|
|
223
|
+
if (version === undefined && specifiedVersion !== undefined) {
|
|
224
|
+
// We should have a defined version to load from if specified version requested
|
|
225
|
+
mc.logger.sendErrorEvent({
|
|
226
|
+
eventName: "NoVersionFoundWhenSpecified",
|
|
227
|
+
id: specifiedVersion,
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
const snapshot = (await storageAdapter.getSnapshotTree(version)) ?? undefined;
|
|
231
|
+
if (snapshot === undefined && version !== undefined) {
|
|
232
|
+
mc.logger.sendErrorEvent({ eventName: "getSnapshotTreeFailed", id: version.id });
|
|
233
|
+
}
|
|
234
|
+
else if (snapshot !== undefined && version?.id === undefined) {
|
|
235
|
+
mc.logger.sendErrorEvent({
|
|
236
|
+
eventName: "getSnapshotFetchedTreeWithoutVersionId",
|
|
237
|
+
hasVersion: version !== undefined, // if hasVersion is true, this means that the contract with the service was broken.
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
return { snapshot, version };
|
|
241
|
+
}
|
|
145
242
|
//# sourceMappingURL=serializedStateManager.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"serializedStateManager.js","sourceRoot":"","sources":["../src/serializedStateManager.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport {\n\tISequencedDocumentMessage,\n\tISnapshotTree,\n\tIVersion,\n} from \"@fluidframework/protocol-definitions\";\nimport { IGetPendingLocalStateProps, IRuntime } from \"@fluidframework/container-definitions\";\nimport {\n\tITelemetryLoggerExt,\n\tMonitoringContext,\n\tPerformanceEvent,\n\tUsageError,\n\tcreateChildMonitoringContext,\n} from \"@fluidframework/telemetry-utils\";\nimport { assert } from \"@fluidframework/core-utils\";\nimport {\n\tIDocumentStorageService,\n\tIResolvedUrl,\n\tISnapshot,\n} from \"@fluidframework/driver-definitions\";\nimport { isInstanceOfISnapshot } from \"@fluidframework/driver-utils\";\nimport { ISerializableBlobContents, getBlobContentsFromTree } from \"./containerStorageAdapter.js\";\nimport { IPendingContainerState } from \"./container.js\";\n\nexport class SerializedStateManager {\n\tprivate readonly processedOps: ISequencedDocumentMessage[] = [];\n\tprivate snapshot:\n\t\t| {\n\t\t\t\ttree: ISnapshotTree;\n\t\t\t\tblobs: ISerializableBlobContents;\n\t\t }\n\t\t| undefined;\n\tprivate readonly mc: MonitoringContext;\n\n\tconstructor(\n\t\tprivate readonly pendingLocalState: IPendingContainerState | undefined,\n\t\tsubLogger: ITelemetryLoggerExt,\n\t\tprivate readonly storageAdapter: Pick<\n\t\t\tIDocumentStorageService,\n\t\t\t\"readBlob\" | \"getSnapshotTree\" | \"getSnapshot\" | \"getVersions\"\n\t\t>,\n\t\tprivate readonly _offlineLoadEnabled: boolean,\n\t) {\n\t\tthis.mc = createChildMonitoringContext({\n\t\t\tlogger: subLogger,\n\t\t\tnamespace: \"serializedStateManager\",\n\t\t});\n\t}\n\n\tpublic get offlineLoadEnabled(): boolean {\n\t\treturn this._offlineLoadEnabled;\n\t}\n\n\tpublic addProcessedOp(message: ISequencedDocumentMessage) {\n\t\tif (this.offlineLoadEnabled) {\n\t\t\tthis.processedOps.push(message);\n\t\t}\n\t}\n\n\tprivate async getVersion(version: string | null): Promise<IVersion | undefined> {\n\t\tconst versions = await this.storageAdapter.getVersions(version, 1);\n\t\treturn versions[0];\n\t}\n\n\tpublic async fetchSnapshot(\n\t\tspecifiedVersion: string | undefined,\n\t\tsupportGetSnapshotApi: boolean | undefined,\n\t) {\n\t\tconst { snapshot, version } =\n\t\t\tthis.pendingLocalState === undefined\n\t\t\t\t? await this.fetchSnapshotCore(specifiedVersion, supportGetSnapshotApi)\n\t\t\t\t: { snapshot: this.pendingLocalState.baseSnapshot, version: undefined };\n\t\tconst snapshotTree: ISnapshotTree | undefined = isInstanceOfISnapshot(snapshot)\n\t\t\t? snapshot.snapshotTree\n\t\t\t: snapshot;\n\t\tif (this.pendingLocalState) {\n\t\t\tthis.snapshot = {\n\t\t\t\ttree: this.pendingLocalState.baseSnapshot,\n\t\t\t\tblobs: this.pendingLocalState.snapshotBlobs,\n\t\t\t};\n\t\t} else {\n\t\t\tassert(snapshotTree !== undefined, 0x8e4 /* Snapshot should exist */);\n\t\t\t// non-interactive clients will not have any pending state we want to save\n\t\t\tif (this.offlineLoadEnabled) {\n\t\t\t\tconst blobs = await getBlobContentsFromTree(snapshotTree, this.storageAdapter);\n\t\t\t\tthis.snapshot = { tree: snapshotTree, blobs };\n\t\t\t}\n\t\t}\n\t\treturn { snapshotTree, version };\n\t}\n\n\tprivate async fetchSnapshotCore(\n\t\tspecifiedVersion: string | undefined,\n\t\tsupportGetSnapshotApi: boolean | undefined,\n\t): Promise<{ snapshot?: ISnapshot | ISnapshotTree; version?: IVersion }> {\n\t\tif (\n\t\t\tthis.mc.config.getBoolean(\"Fluid.Container.UseLoadingGroupIdForSnapshotFetch\") ===\n\t\t\t\ttrue &&\n\t\t\tsupportGetSnapshotApi === true\n\t\t) {\n\t\t\tconst snapshot =\n\t\t\t\t(await this.storageAdapter.getSnapshot?.({\n\t\t\t\t\tversionId: specifiedVersion,\n\t\t\t\t})) ?? undefined;\n\t\t\tconst version: IVersion | undefined =\n\t\t\t\tsnapshot?.snapshotTree.id === undefined\n\t\t\t\t\t? undefined\n\t\t\t\t\t: {\n\t\t\t\t\t\t\tid: snapshot.snapshotTree.id,\n\t\t\t\t\t\t\ttreeId: snapshot.snapshotTree.id,\n\t\t\t\t\t };\n\n\t\t\tif (snapshot === undefined && specifiedVersion !== undefined) {\n\t\t\t\tthis.mc.logger.sendErrorEvent({\n\t\t\t\t\teventName: \"getSnapshotTreeFailed\",\n\t\t\t\t\tid: specifiedVersion,\n\t\t\t\t});\n\t\t\t\t// Not sure if this should be here actually\n\t\t\t} else if (snapshot !== undefined && version?.id === undefined) {\n\t\t\t\tthis.mc.logger.sendErrorEvent({\n\t\t\t\t\teventName: \"getSnapshotFetchedTreeWithoutVersionId\",\n\t\t\t\t\thasVersion: version !== undefined, // if hasVersion is true, this means that the contract with the service was broken.\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn { snapshot, version };\n\t\t}\n\t\treturn this.fetchSnapshotTree(specifiedVersion);\n\t}\n\n\t/**\n\t * Get the most recent snapshot, or a specific version.\n\t * @param specifiedVersion - The specific version of the snapshot to retrieve\n\t * @returns The snapshot requested, or the latest snapshot if no version was specified, plus version ID\n\t */\n\tprivate async fetchSnapshotTree(\n\t\tspecifiedVersion: string | undefined,\n\t): Promise<{ snapshot?: ISnapshotTree; version?: IVersion | undefined }> {\n\t\tconst version = await this.getVersion(specifiedVersion ?? null);\n\n\t\tif (version === undefined && specifiedVersion !== undefined) {\n\t\t\t// We should have a defined version to load from if specified version requested\n\t\t\tthis.mc.logger.sendErrorEvent({\n\t\t\t\teventName: \"NoVersionFoundWhenSpecified\",\n\t\t\t\tid: specifiedVersion,\n\t\t\t});\n\t\t}\n\t\tconst snapshot = (await this.storageAdapter.getSnapshotTree(version)) ?? undefined;\n\n\t\tif (snapshot === undefined && version !== undefined) {\n\t\t\tthis.mc.logger.sendErrorEvent({ eventName: \"getSnapshotTreeFailed\", id: version.id });\n\t\t} else if (snapshot !== undefined && version?.id === undefined) {\n\t\t\tthis.mc.logger.sendErrorEvent({\n\t\t\t\teventName: \"getSnapshotFetchedTreeWithoutVersionId\",\n\t\t\t\thasVersion: version !== undefined, // if hasVersion is true, this means that the contract with the service was broken.\n\t\t\t});\n\t\t}\n\t\treturn { snapshot, version };\n\t}\n\n\t/**\n\t * This method is only meant to be used by Container.attach() to set the initial\n\t * base snapshot when attaching.\n\t * @param snapshot - snapshot and blobs collected while attaching\n\t */\n\tpublic setSnapshot(\n\t\tsnapshot:\n\t\t\t| {\n\t\t\t\t\ttree: ISnapshotTree;\n\t\t\t\t\tblobs: ISerializableBlobContents;\n\t\t\t }\n\t\t\t| undefined,\n\t) {\n\t\tthis.snapshot = snapshot;\n\t}\n\n\tpublic async getPendingLocalStateCore(\n\t\tprops: IGetPendingLocalStateProps,\n\t\tclientId: string | undefined,\n\t\truntime: Pick<IRuntime, \"getPendingLocalState\">,\n\t\tresolvedUrl: IResolvedUrl,\n\t) {\n\t\treturn PerformanceEvent.timedExecAsync(\n\t\t\tthis.mc.logger,\n\t\t\t{\n\t\t\t\teventName: \"getPendingLocalState\",\n\t\t\t\tnotifyImminentClosure: props.notifyImminentClosure,\n\t\t\t\tprocessedOpsSize: this.processedOps.length,\n\t\t\t\tclientId,\n\t\t\t},\n\t\t\tasync () => {\n\t\t\t\tif (!this.offlineLoadEnabled) {\n\t\t\t\t\tthrow new UsageError(\n\t\t\t\t\t\t\"Can't get pending local state unless offline load is enabled\",\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tassert(this.snapshot !== undefined, 0x8e5 /* no base data */);\n\t\t\t\tconst pendingRuntimeState = await runtime.getPendingLocalState(props);\n\t\t\t\tconst pendingState: IPendingContainerState = {\n\t\t\t\t\tattached: true,\n\t\t\t\t\tpendingRuntimeState,\n\t\t\t\t\tbaseSnapshot: this.snapshot.tree,\n\t\t\t\t\tsnapshotBlobs: this.snapshot.blobs,\n\t\t\t\t\tsavedOps: this.processedOps,\n\t\t\t\t\turl: resolvedUrl.url,\n\t\t\t\t\t// no need to save this if there is no pending runtime state\n\t\t\t\t\tclientId: pendingRuntimeState !== undefined ? clientId : undefined,\n\t\t\t\t};\n\n\t\t\t\treturn JSON.stringify(pendingState);\n\t\t\t},\n\t\t);\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"serializedStateManager.js","sourceRoot":"","sources":["../src/serializedStateManager.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport {\n\tIGetPendingLocalStateProps,\n\tIRuntime,\n} from \"@fluidframework/container-definitions/internal\";\nimport { assert } from \"@fluidframework/core-utils/internal\";\nimport {\n\tIDocumentStorageService,\n\tIResolvedUrl,\n\tISnapshot,\n} from \"@fluidframework/driver-definitions/internal\";\nimport { isInstanceOfISnapshot } from \"@fluidframework/driver-utils/internal\";\nimport {\n\ttype IDocumentAttributes,\n\tISequencedDocumentMessage,\n\tISnapshotTree,\n\tIVersion,\n} from \"@fluidframework/protocol-definitions\";\nimport { ITelemetryLoggerExt } from \"@fluidframework/telemetry-utils\";\nimport {\n\tMonitoringContext,\n\tPerformanceEvent,\n\tUsageError,\n\tcreateChildMonitoringContext,\n} from \"@fluidframework/telemetry-utils/internal\";\n\nimport { ISerializableBlobContents, getBlobContentsFromTree } from \"./containerStorageAdapter.js\";\nimport { getDocumentAttributes } from \"./utils.js\";\n\nexport interface SnapshotWithBlobs {\n\t/**\n\t * Snapshot from which container initially loaded.\n\t */\n\tbaseSnapshot: ISnapshotTree;\n\t/**\n\t * Serializable blobs from the base snapshot. Used to load offline since\n\t * storage is not available.\n\t */\n\tsnapshotBlobs: ISerializableBlobContents;\n}\n/**\n * State saved by a container at close time, to be used to load a new instance\n * of the container to the same state\n * @internal\n */\nexport interface IPendingContainerState extends SnapshotWithBlobs {\n\tattached: true;\n\tpendingRuntimeState: unknown;\n\t/**\n\t * All ops since base snapshot sequence number up to the latest op\n\t * seen when the container was closed. Used to apply stashed (saved pending)\n\t * ops at the same sequence number at which they were made.\n\t */\n\tsavedOps: ISequencedDocumentMessage[];\n\turl: string;\n\tclientId?: string;\n}\n\n/**\n * State saved by a container in detached state, to be used to load a new instance\n * of the container to the same state (rehydrate)\n * @internal\n */\nexport interface IPendingDetachedContainerState extends SnapshotWithBlobs {\n\tattached: false;\n\thasAttachmentBlobs: boolean;\n\tpendingRuntimeState?: unknown;\n}\n\nexport interface ISnapshotInfo extends SnapshotWithBlobs {\n\tsnapshotSequenceNumber: number;\n}\n\nexport class SerializedStateManager {\n\tprivate readonly processedOps: ISequencedDocumentMessage[] = [];\n\tprivate snapshot: ISnapshotInfo | undefined;\n\tprivate readonly mc: MonitoringContext;\n\tprivate latestSnapshot: ISnapshotInfo | undefined;\n\tprivate refreshSnapshot: Promise<void> | undefined;\n\n\tconstructor(\n\t\tprivate readonly pendingLocalState: IPendingContainerState | undefined,\n\t\tsubLogger: ITelemetryLoggerExt,\n\t\tprivate readonly storageAdapter: Pick<\n\t\t\tIDocumentStorageService,\n\t\t\t\"readBlob\" | \"getSnapshotTree\" | \"getSnapshot\" | \"getVersions\"\n\t\t>,\n\t\tprivate readonly _offlineLoadEnabled: boolean,\n\t\tprivate readonly newSnapshotFetched?: () => void,\n\t) {\n\t\tthis.mc = createChildMonitoringContext({\n\t\t\tlogger: subLogger,\n\t\t\tnamespace: \"serializedStateManager\",\n\t\t});\n\t}\n\n\tpublic get offlineLoadEnabled(): boolean {\n\t\treturn this._offlineLoadEnabled;\n\t}\n\n\tpublic addProcessedOp(message: ISequencedDocumentMessage) {\n\t\tif (this.offlineLoadEnabled) {\n\t\t\tthis.processedOps.push(message);\n\t\t\tthis.updateSnapshotAndProcessedOpsMaybe();\n\t\t}\n\t}\n\n\tpublic async fetchSnapshot(\n\t\tspecifiedVersion: string | undefined,\n\t\tsupportGetSnapshotApi: boolean,\n\t) {\n\t\tif (this.pendingLocalState === undefined) {\n\t\t\tconst { baseSnapshot, version } = await getSnapshotTree(\n\t\t\t\tthis.mc,\n\t\t\t\tthis.storageAdapter,\n\t\t\t\tsupportGetSnapshotApi,\n\t\t\t\tspecifiedVersion,\n\t\t\t);\n\t\t\t// non-interactive clients will not have any pending state we want to save\n\t\t\tif (this.offlineLoadEnabled) {\n\t\t\t\tconst snapshotBlobs = await getBlobContentsFromTree(\n\t\t\t\t\tbaseSnapshot,\n\t\t\t\t\tthis.storageAdapter,\n\t\t\t\t);\n\t\t\t\tconst attributes = await getDocumentAttributes(this.storageAdapter, baseSnapshot);\n\t\t\t\tthis.snapshot = {\n\t\t\t\t\tbaseSnapshot,\n\t\t\t\t\tsnapshotBlobs,\n\t\t\t\t\tsnapshotSequenceNumber: attributes.sequenceNumber,\n\t\t\t\t};\n\t\t\t}\n\t\t\treturn { baseSnapshot, version };\n\t\t} else {\n\t\t\tconst { baseSnapshot, snapshotBlobs } = this.pendingLocalState;\n\t\t\tconst attributes = await getDocumentAttributes(this.storageAdapter, baseSnapshot);\n\t\t\tthis.snapshot = {\n\t\t\t\tbaseSnapshot,\n\t\t\t\tsnapshotBlobs,\n\t\t\t\tsnapshotSequenceNumber: attributes.sequenceNumber,\n\t\t\t};\n\t\t\tthis.refreshSnapshot ??= (async () => {\n\t\t\t\tthis.latestSnapshot = await getLatestSnapshotInfo(\n\t\t\t\t\tthis.mc,\n\t\t\t\t\tthis.storageAdapter,\n\t\t\t\t\tsupportGetSnapshotApi,\n\t\t\t\t);\n\t\t\t\tthis.newSnapshotFetched?.();\n\t\t\t\tthis.updateSnapshotAndProcessedOpsMaybe();\n\t\t\t})();\n\n\t\t\treturn { baseSnapshot, version: undefined };\n\t\t}\n\t}\n\n\t/**\n\t * Updates class snapshot and processedOps if we have a new snapshot and it's among processedOps range.\n\t */\n\tprivate updateSnapshotAndProcessedOpsMaybe() {\n\t\tif (this.latestSnapshot === undefined || this.processedOps.length === 0) {\n\t\t\t// can't refresh latest snapshot until we have processed the ops up to it.\n\t\t\t// Pending state would be behind the latest snapshot.\n\t\t\treturn;\n\t\t}\n\t\tconst snapshotSequenceNumber = this.latestSnapshot.snapshotSequenceNumber;\n\t\tconst firstProcessedOpSequenceNumber = this.processedOps[0].sequenceNumber;\n\t\tconst lastProcessedOpSequenceNumber =\n\t\t\tthis.processedOps[this.processedOps.length - 1].sequenceNumber;\n\n\t\tif (snapshotSequenceNumber < firstProcessedOpSequenceNumber) {\n\t\t\t// Snapshot seq number is older than our first processed op, which could mean we're fetching\n\t\t\t// the same snapshot that we already have or snapshot is too old, implicating an unexpected behavior.\n\t\t\tthis.mc.logger.sendTelemetryEvent({\n\t\t\t\teventName: \"OldSnapshotFetchWhileRefreshing\",\n\t\t\t\tsnapshotSequenceNumber,\n\t\t\t\tfirstProcessedOpSequenceNumber,\n\t\t\t\tlastProcessedOpSequenceNumber,\n\t\t\t\tstashedSnapshotSequenceNumber: this.snapshot?.snapshotSequenceNumber,\n\t\t\t});\n\t\t\tthis.latestSnapshot = undefined;\n\t\t} else if (snapshotSequenceNumber <= lastProcessedOpSequenceNumber) {\n\t\t\t// Snapshot seq num is between the first and last processed op.\n\t\t\t// Remove the ops that are already part of the snapshot\n\t\t\tthis.processedOps.splice(\n\t\t\t\t0,\n\t\t\t\tsnapshotSequenceNumber - firstProcessedOpSequenceNumber + 1,\n\t\t\t);\n\t\t\tthis.snapshot = this.latestSnapshot;\n\t\t\tthis.latestSnapshot = undefined;\n\t\t\tthis.mc.logger.sendTelemetryEvent({\n\t\t\t\teventName: \"SnapshotRefreshed\",\n\t\t\t\tsnapshotSequenceNumber,\n\t\t\t\tfirstProcessedOpSequenceNumber,\n\t\t\t\tnewFirstProcessedOpSequenceNumber:\n\t\t\t\t\tthis.processedOps.length === 0\n\t\t\t\t\t\t? undefined\n\t\t\t\t\t\t: this.processedOps[0].sequenceNumber,\n\t\t\t});\n\t\t}\n\t}\n\n\t/**\n\t * This method is only meant to be used by Container.attach() to set the initial\n\t * base snapshot when attaching.\n\t * @param snapshot - snapshot and blobs collected while attaching\n\t */\n\tpublic setInitialSnapshot(snapshot: SnapshotWithBlobs | undefined) {\n\t\tif (this.offlineLoadEnabled) {\n\t\t\tassert(\n\t\t\t\tthis.snapshot === undefined,\n\t\t\t\t0x937 /* inital snapshot should only be defined once */,\n\t\t\t);\n\t\t\tassert(snapshot !== undefined, 0x938 /* attachment snapshot should be defined */);\n\t\t\tconst { baseSnapshot, snapshotBlobs } = snapshot;\n\t\t\tconst attributesHash =\n\t\t\t\t\".protocol\" in baseSnapshot.trees\n\t\t\t\t\t? baseSnapshot.trees[\".protocol\"].blobs.attributes\n\t\t\t\t\t: baseSnapshot.blobs[\".attributes\"];\n\t\t\tconst attributes = JSON.parse(snapshotBlobs[attributesHash]);\n\t\t\tassert(\n\t\t\t\tattributes.sequenceNumber === 0,\n\t\t\t\t0x939 /* trying to set a non attachment snapshot */,\n\t\t\t);\n\t\t\tthis.snapshot = { ...snapshot, snapshotSequenceNumber: attributes.sequenceNumber };\n\t\t}\n\t}\n\n\tpublic async getPendingLocalStateCore(\n\t\tprops: IGetPendingLocalStateProps,\n\t\tclientId: string | undefined,\n\t\truntime: Pick<IRuntime, \"getPendingLocalState\">,\n\t\tresolvedUrl: IResolvedUrl,\n\t) {\n\t\treturn PerformanceEvent.timedExecAsync(\n\t\t\tthis.mc.logger,\n\t\t\t{\n\t\t\t\teventName: \"getPendingLocalState\",\n\t\t\t\tnotifyImminentClosure: props.notifyImminentClosure,\n\t\t\t\tprocessedOpsSize: this.processedOps.length,\n\t\t\t\tclientId,\n\t\t\t},\n\t\t\tasync () => {\n\t\t\t\tif (!this.offlineLoadEnabled) {\n\t\t\t\t\tthrow new UsageError(\n\t\t\t\t\t\t\"Can't get pending local state unless offline load is enabled\",\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tassert(this.snapshot !== undefined, 0x8e5 /* no base data */);\n\t\t\t\tconst pendingRuntimeState = await runtime.getPendingLocalState(props);\n\t\t\t\tconst pendingState: IPendingContainerState = {\n\t\t\t\t\tattached: true,\n\t\t\t\t\tpendingRuntimeState,\n\t\t\t\t\tbaseSnapshot: this.snapshot.baseSnapshot,\n\t\t\t\t\tsnapshotBlobs: this.snapshot.snapshotBlobs,\n\t\t\t\t\tsavedOps: this.processedOps,\n\t\t\t\t\turl: resolvedUrl.url,\n\t\t\t\t\t// no need to save this if there is no pending runtime state\n\t\t\t\t\tclientId: pendingRuntimeState !== undefined ? clientId : undefined,\n\t\t\t\t};\n\n\t\t\t\treturn JSON.stringify(pendingState);\n\t\t\t},\n\t\t);\n\t}\n}\n\n/**\n * Retrieves the most recent snapshot and returns its info.\n *\n * @param mc - The monitoring context.\n * @param storageAdapter - The storage adapter providing methods to retrieve the snapshot.\n * @param supportGetSnapshotApi - a boolean indicating whether to use the fetchISnapshot or fetchISnapshotTree.\n * @returns a SnapshotInfo object containing the snapshot tree, snapshot blobs and its sequence number.\n */\nexport async function getLatestSnapshotInfo(\n\tmc: MonitoringContext,\n\tstorageAdapter: Pick<\n\t\tIDocumentStorageService,\n\t\t\"getSnapshot\" | \"getSnapshotTree\" | \"getVersions\" | \"readBlob\"\n\t>,\n\tsupportGetSnapshotApi: boolean,\n): Promise<ISnapshotInfo | undefined> {\n\treturn PerformanceEvent.timedExecAsync(\n\t\tmc.logger,\n\t\t{ eventName: \"GetLatestSnapshotInfo\" },\n\t\tasync () => {\n\t\t\tconst { baseSnapshot } = await getSnapshotTree(\n\t\t\t\tmc,\n\t\t\t\tstorageAdapter,\n\t\t\t\tsupportGetSnapshotApi,\n\t\t\t\tundefined,\n\t\t\t);\n\t\t\tconst snapshotBlobs = await getBlobContentsFromTree(baseSnapshot, storageAdapter);\n\t\t\tconst attributes: IDocumentAttributes = await getDocumentAttributes(\n\t\t\t\tstorageAdapter,\n\t\t\t\tbaseSnapshot,\n\t\t\t);\n\t\t\tconst snapshotSequenceNumber = attributes.sequenceNumber;\n\t\t\treturn { baseSnapshot, snapshotBlobs, snapshotSequenceNumber };\n\t\t},\n\t).catch(() => undefined);\n}\n\n/**\n * Retrieves a snapshot from the storage adapter and transforms it into an ISnapshotTree object.\n *\n * @param mc - The monitoring context.\n * @param storageAdapter - The storage adapter providing methods to retrieve the snapshot.\n * @param supportGetSnapshotApi - a boolean indicating whether to use the fetchISnapshot or fetchISnapshotTree.\n * @param specifiedVersion - An optional version string specifying the version of the snapshot tree to fetch.\n * @returns - An ISnapshotTree and its version.\n */\nasync function getSnapshotTree(\n\tmc: MonitoringContext,\n\tstorageAdapter: Pick<\n\t\tIDocumentStorageService,\n\t\t\"getSnapshot\" | \"getSnapshotTree\" | \"getVersions\"\n\t>,\n\tsupportGetSnapshotApi: boolean,\n\tspecifiedVersion: string | undefined,\n): Promise<{ baseSnapshot: ISnapshotTree; version?: IVersion }> {\n\tconst { snapshot, version } = supportGetSnapshotApi\n\t\t? await fetchISnapshot(mc, storageAdapter, specifiedVersion)\n\t\t: await fetchISnapshotTree(mc, storageAdapter, specifiedVersion);\n\tconst baseSnapshot: ISnapshotTree | undefined = isInstanceOfISnapshot(snapshot)\n\t\t? snapshot.snapshotTree\n\t\t: snapshot;\n\tassert(baseSnapshot !== undefined, 0x8e4 /* Snapshot should exist */);\n\treturn { baseSnapshot, version };\n}\n\n/**\n * Fetches an ISnapshot from a storage adapter based on the specified version.\n *\n * @param mc - The monitoring context.\n * @param storageAdapter - The storage adapter providing a getSnapshot method to retrieve the ISnapshot and version.\n * @param specifiedVersion - An optional version string specifying the version of the snapshot tree to fetch.\n * @returns - The fetched snapshot tree and its version.\n */\nexport async function fetchISnapshot(\n\tmc: MonitoringContext,\n\tstorageAdapter: Pick<IDocumentStorageService, \"getSnapshot\">,\n\tspecifiedVersion: string | undefined,\n): Promise<{ snapshot?: ISnapshot; version?: IVersion }> {\n\tconst snapshot = await storageAdapter.getSnapshot?.({ versionId: specifiedVersion });\n\tconst version: IVersion | undefined =\n\t\tsnapshot?.snapshotTree.id === undefined\n\t\t\t? undefined\n\t\t\t: {\n\t\t\t\t\tid: snapshot.snapshotTree.id,\n\t\t\t\t\ttreeId: snapshot.snapshotTree.id,\n\t\t\t };\n\n\tif (snapshot === undefined && specifiedVersion !== undefined) {\n\t\tmc.logger.sendErrorEvent({\n\t\t\teventName: \"getSnapshotTreeFailed\",\n\t\t\tid: specifiedVersion,\n\t\t});\n\t} else if (snapshot !== undefined && version?.id === undefined) {\n\t\tmc.logger.sendErrorEvent({\n\t\t\teventName: \"getSnapshotFetchedTreeWithoutVersionId\",\n\t\t\thasVersion: version !== undefined, // if hasVersion is true, this means that the contract with the service was broken.\n\t\t});\n\t}\n\treturn { snapshot, version };\n}\n\n/**\n * Fetches an ISnapshotTree from a storage adapter based on the specified version.\n *\n * @param mc - The monitoring context.\n * @param storageAdapter - The storage adapter providing methods to retrieve the ISnapshotTree and version.\n * @param specifiedVersion - An optional version string specifying the version of the snapshot tree to fetch.\n * @returns - The fetched snapshot tree and its version.\n */\nexport async function fetchISnapshotTree(\n\tmc: MonitoringContext,\n\tstorageAdapter: Pick<IDocumentStorageService, \"getSnapshotTree\" | \"getVersions\">,\n\tspecifiedVersion: string | undefined,\n): Promise<{ snapshot?: ISnapshotTree; version?: IVersion | undefined }> {\n\tconst versions = await storageAdapter.getVersions(specifiedVersion ?? null, 1);\n\tconst version = versions[0];\n\n\tif (version === undefined && specifiedVersion !== undefined) {\n\t\t// We should have a defined version to load from if specified version requested\n\t\tmc.logger.sendErrorEvent({\n\t\t\teventName: \"NoVersionFoundWhenSpecified\",\n\t\t\tid: specifiedVersion,\n\t\t});\n\t}\n\tconst snapshot = (await storageAdapter.getSnapshotTree(version)) ?? undefined;\n\n\tif (snapshot === undefined && version !== undefined) {\n\t\tmc.logger.sendErrorEvent({ eventName: \"getSnapshotTreeFailed\", id: version.id });\n\t} else if (snapshot !== undefined && version?.id === undefined) {\n\t\tmc.logger.sendErrorEvent({\n\t\t\teventName: \"getSnapshotFetchedTreeWithoutVersionId\",\n\t\t\thasVersion: version !== undefined, // if hasVersion is true, this means that the contract with the service was broken.\n\t\t});\n\t}\n\treturn { snapshot, version };\n}\n"]}
|
package/lib/utils.d.ts
CHANGED
|
@@ -2,10 +2,11 @@
|
|
|
2
2
|
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
|
-
import {
|
|
6
|
-
import { CombinedAppAndProtocolSummary, DeltaStreamConnectionForbiddenError } from "@fluidframework/driver-utils";
|
|
5
|
+
import { IDocumentStorageService, type ISnapshot } from "@fluidframework/driver-definitions/internal";
|
|
6
|
+
import { CombinedAppAndProtocolSummary, DeltaStreamConnectionForbiddenError } from "@fluidframework/driver-utils/internal";
|
|
7
|
+
import { IDocumentAttributes, ISnapshotTree, ISummaryTree } from "@fluidframework/protocol-definitions";
|
|
7
8
|
import { ISerializableBlobContents } from "./containerStorageAdapter.js";
|
|
8
|
-
import { IPendingDetachedContainerState } from "./
|
|
9
|
+
import type { IPendingDetachedContainerState, ISnapshotInfo, SnapshotWithBlobs } from "./serializedStateManager.js";
|
|
9
10
|
export interface ISnapshotTreeWithBlobContents extends ISnapshotTree {
|
|
10
11
|
blobsContents: {
|
|
11
12
|
[path: string]: ArrayBufferLike;
|
|
@@ -18,7 +19,7 @@ export interface ISnapshotTreeWithBlobContents extends ISnapshotTree {
|
|
|
18
19
|
* Interface to represent the parsed parts of IResolvedUrl.url to help
|
|
19
20
|
* in getting info about different parts of the url.
|
|
20
21
|
* May not be compatible or relevant for any Url Resolver
|
|
21
|
-
* @
|
|
22
|
+
* @alpha
|
|
22
23
|
*/
|
|
23
24
|
export interface IParsedUrl {
|
|
24
25
|
/**
|
|
@@ -46,7 +47,7 @@ export interface IParsedUrl {
|
|
|
46
47
|
* with urls of type: protocol://<string>/.../..?<querystring>
|
|
47
48
|
* @param url - This is the IResolvedUrl.url part of the resolved url.
|
|
48
49
|
* @returns The IParsedUrl representing the input URL, or undefined if the format was not supported
|
|
49
|
-
* @
|
|
50
|
+
* @alpha
|
|
50
51
|
*/
|
|
51
52
|
export declare function tryParseCompatibleResolvedUrl(url: string): IParsedUrl | undefined;
|
|
52
53
|
/**
|
|
@@ -56,10 +57,23 @@ export declare function tryParseCompatibleResolvedUrl(url: string): IParsedUrl |
|
|
|
56
57
|
* @internal
|
|
57
58
|
*/
|
|
58
59
|
export declare function combineAppAndProtocolSummary(appSummary: ISummaryTree, protocolSummary: ISummaryTree): CombinedAppAndProtocolSummary;
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
60
|
+
/**
|
|
61
|
+
* Converts a snapshot to snapshotInfo with its blob contents
|
|
62
|
+
* to align detached container format with IPendingContainerState
|
|
63
|
+
*
|
|
64
|
+
* Note, this assumes the ISnapshot sequence number is defined. Otherwise an assert will be thrown
|
|
65
|
+
* @param snapshot - ISnapshot
|
|
66
|
+
*/
|
|
67
|
+
export declare function convertSnapshotToSnapshotInfo(snapshot: ISnapshot): ISnapshotInfo;
|
|
68
|
+
/**
|
|
69
|
+
* Converts a snapshot to snapshotInfo with its blob contents
|
|
70
|
+
* to align detached container format with IPendingContainerState
|
|
71
|
+
*
|
|
72
|
+
* Note, this assumes the ISnapshot sequence number is defined. Otherwise an assert will be thrown
|
|
73
|
+
* @param snapshot - ISnapshot
|
|
74
|
+
*/
|
|
75
|
+
export declare function convertSnapshotInfoToSnapshot(snapshotInfo: ISnapshotInfo, snapshotSequenceNumber: number): ISnapshot;
|
|
76
|
+
export declare const getSnapshotTreeAndBlobsFromSerializedContainer: (detachedContainerSnapshot: ISummaryTree) => SnapshotWithBlobs;
|
|
63
77
|
export declare function getProtocolSnapshotTree(snapshot: ISnapshotTree): ISnapshotTree;
|
|
64
78
|
export declare const combineSnapshotTreeAndSnapshotBlobs: (baseSnapshot: ISnapshotTree, snapshotBlobs: ISerializableBlobContents) => ISnapshotTreeWithBlobContents;
|
|
65
79
|
export declare function isDeltaStreamConnectionForbiddenError(error: any): error is DeltaStreamConnectionForbiddenError;
|
|
@@ -69,4 +83,5 @@ export declare function getDetachedContainerStateFromSerializedContainer(seriali
|
|
|
69
83
|
* If there are multiple calls they will all get the same promise to wait on.
|
|
70
84
|
*/
|
|
71
85
|
export declare const runSingle: <A extends any[], R>(func: (...args: A) => Promise<R>) => (...args: A) => Promise<R>;
|
|
86
|
+
export declare function getDocumentAttributes(storage: Pick<IDocumentStorageService, "readBlob">, tree: ISnapshotTree | undefined): Promise<IDocumentAttributes>;
|
|
72
87
|
//# sourceMappingURL=utils.d.ts.map
|
package/lib/utils.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,EACN,uBAAuB,EACvB,KAAK,SAAS,EACd,MAAM,6CAA6C,CAAC;AACrD,OAAO,EACN,6BAA6B,EAC7B,mCAAmC,EAGnC,MAAM,uCAAuC,CAAC;AAC/C,OAAO,EACN,mBAAmB,EACnB,aAAa,EACb,YAAY,EAEZ,MAAM,sCAAsC,CAAC;AAI9C,OAAO,EAAE,yBAAyB,EAAE,MAAM,8BAA8B,CAAC;AACzE,OAAO,KAAK,EACX,8BAA8B,EAC9B,aAAa,EACb,iBAAiB,EACjB,MAAM,6BAA6B,CAAC;AAIrC,MAAM,WAAW,6BAA8B,SAAQ,aAAa;IACnE,aAAa,EAAE;QAAE,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,CAAA;KAAE,CAAC;IACnD,KAAK,EAAE;QAAE,CAAC,IAAI,EAAE,MAAM,GAAG,6BAA6B,CAAA;KAAE,CAAC;CACzD;AAED;;;;;GAKG;AACH,MAAM,WAAW,UAAU;IAC1B;;OAEG;IACH,EAAE,EAAE,MAAM,CAAC;IACX;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;IACb;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC;CAC5B;AAED;;;;;;;;GAQG;AACH,wBAAgB,6BAA6B,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS,CAiBjF;AAED;;;;;GAKG;AACH,wBAAgB,4BAA4B,CAC3C,UAAU,EAAE,YAAY,EACxB,eAAe,EAAE,YAAY,GAC3B,6BAA6B,CAiB/B;AAqDD;;;;;;GAMG;AACH,wBAAgB,6BAA6B,CAAC,QAAQ,EAAE,SAAS,GAAG,aAAa,CAWhF;AAED;;;;;;GAMG;AACH,wBAAgB,6BAA6B,CAC5C,YAAY,EAAE,aAAa,EAC3B,sBAAsB,EAAE,MAAM,GAC5B,SAAS,CAaX;AAqBD,eAAO,MAAM,8CAA8C,8BAC/B,YAAY,KACrC,iBAYF,CAAC;AAEF,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,aAAa,GAAG,aAAa,CAE9E;AAED,eAAO,MAAM,mCAAmC,iBACjC,aAAa,iBACZ,yBAAyB,KACtC,6BAwBF,CAAC;AAEF,wBAAgB,qCAAqC,CACpD,KAAK,EAAE,GAAG,GACR,KAAK,IAAI,mCAAmC,CAM9C;AAoBD,wBAAgB,gDAAgD,CAC/D,mBAAmB,EAAE,MAAM,GACzB,8BAA8B,CAkBhC;AAED;;;GAGG;AACH,eAAO,MAAM,SAAS,sFAsBrB,CAAC;AAEF,wBAAsB,qBAAqB,CAC1C,OAAO,EAAE,IAAI,CAAC,uBAAuB,EAAE,UAAU,CAAC,EAClD,IAAI,EAAE,aAAa,GAAG,SAAS,GAC7B,OAAO,CAAC,mBAAmB,CAAC,CAiB9B"}
|