@fluidframework/container-loader 2.0.0-dev-rc.3.0.0.250606 → 2.0.0-dev-rc.3.0.0.254274
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/api-report/container-loader.api.md +11 -11
- package/dist/attachment.d.ts +2 -2
- package/dist/attachment.d.ts.map +1 -1
- package/dist/attachment.js +3 -3
- 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 +2 -2
- package/dist/audience.js.map +1 -1
- package/dist/catchUpMonitor.js +2 -2
- package/dist/catchUpMonitor.js.map +1 -1
- package/dist/connectionManager.d.ts +1 -1
- package/dist/connectionManager.d.ts.map +1 -1
- package/dist/connectionManager.js +41 -41
- package/dist/connectionManager.js.map +1 -1
- package/dist/connectionStateHandler.d.ts.map +1 -1
- package/dist/connectionStateHandler.js +27 -27
- package/dist/connectionStateHandler.js.map +1 -1
- package/dist/container-loader-alpha.d.ts +11 -11
- package/dist/container-loader-beta.d.ts +11 -11
- package/dist/container-loader-public.d.ts +11 -11
- package/dist/container-loader-untrimmed.d.ts +11 -11
- package/dist/container.d.ts +5 -3
- package/dist/container.d.ts.map +1 -1
- package/dist/container.js +83 -81
- package/dist/container.js.map +1 -1
- package/dist/containerContext.d.ts +5 -3
- package/dist/containerContext.d.ts.map +1 -1
- package/dist/containerContext.js.map +1 -1
- package/dist/containerStorageAdapter.d.ts +2 -2
- 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 +3 -2
- 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 +7 -3
- package/dist/deltaManager.d.ts.map +1 -1
- package/dist/deltaManager.js +52 -49
- package/dist/deltaManager.js.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/loader.d.ts +2 -2
- package/dist/loader.d.ts.map +1 -1
- package/dist/loader.js +21 -21
- package/dist/loader.js.map +1 -1
- package/dist/location-redirection-utilities/resolveWithLocationRedirection.d.ts +1 -1
- 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.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/quorum.d.ts +1 -1
- package/dist/quorum.d.ts.map +1 -1
- package/dist/quorum.js.map +1 -1
- package/dist/retriableDocumentStorageService.d.ts +1 -1
- 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 +40 -9
- package/dist/serializedStateManager.d.ts.map +1 -1
- package/dist/serializedStateManager.js +133 -24
- package/dist/serializedStateManager.js.map +1 -1
- package/dist/utils.d.ts +19 -3
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +57 -15
- package/dist/utils.js.map +1 -1
- package/lib/attachment.d.ts +2 -2
- 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.js +1 -1
- package/lib/catchUpMonitor.js.map +1 -1
- package/lib/connectionManager.d.ts +1 -1
- package/lib/connectionManager.d.ts.map +1 -1
- package/lib/connectionManager.js +4 -4
- package/lib/connectionManager.js.map +1 -1
- package/lib/connectionStateHandler.d.ts.map +1 -1
- package/lib/connectionStateHandler.js +2 -2
- package/lib/connectionStateHandler.js.map +1 -1
- package/lib/container-loader-alpha.d.ts +11 -11
- package/lib/container-loader-beta.d.ts +11 -11
- package/lib/container-loader-public.d.ts +11 -11
- package/lib/container-loader-untrimmed.d.ts +11 -11
- package/lib/container.d.ts +5 -3
- package/lib/container.d.ts.map +1 -1
- package/lib/container.js +14 -12
- package/lib/container.js.map +1 -1
- package/lib/containerContext.d.ts +5 -3
- package/lib/containerContext.d.ts.map +1 -1
- package/lib/containerContext.js.map +1 -1
- package/lib/containerStorageAdapter.d.ts +2 -2
- 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 +3 -2
- 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 +7 -3
- package/lib/deltaManager.d.ts.map +1 -1
- package/lib/deltaManager.js +12 -9
- package/lib/deltaManager.js.map +1 -1
- package/lib/deltaQueue.js +1 -1
- 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/loader.d.ts +2 -2
- package/lib/loader.d.ts.map +1 -1
- package/lib/loader.js +2 -2
- package/lib/loader.js.map +1 -1
- package/lib/location-redirection-utilities/resolveWithLocationRedirection.d.ts +1 -1
- 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.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/quorum.d.ts +1 -1
- package/lib/quorum.d.ts.map +1 -1
- package/lib/quorum.js.map +1 -1
- package/lib/retriableDocumentStorageService.d.ts +1 -1
- 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 +40 -9
- package/lib/serializedStateManager.d.ts.map +1 -1
- package/lib/serializedStateManager.js +127 -19
- package/lib/serializedStateManager.js.map +1 -1
- package/lib/tsdoc-metadata.json +11 -0
- package/lib/utils.d.ts +19 -3
- package/lib/utils.d.ts.map +1 -1
- package/lib/utils.js +44 -4
- package/lib/utils.js.map +1 -1
- package/package.json +19 -31
- package/src/attachment.ts +4 -3
- package/src/audience.ts +2 -2
- package/src/catchUpMonitor.ts +1 -1
- package/src/connectionManager.ts +7 -7
- package/src/connectionStateHandler.ts +4 -4
- package/src/container.ts +26 -22
- package/src/containerContext.ts +8 -5
- package/src/containerStorageAdapter.ts +5 -4
- package/src/contracts.ts +2 -3
- package/src/debugLogger.ts +2 -3
- package/src/deltaManager.ts +23 -13
- package/src/deltaQueue.ts +1 -1
- package/src/error.ts +5 -4
- package/src/loader.ts +5 -4
- package/src/location-redirection-utilities/resolveWithLocationRedirection.ts +3 -3
- package/src/noopHeuristic.ts +2 -2
- package/src/packageVersion.ts +1 -1
- package/src/protocol.ts +2 -2
- package/src/protocolTreeDocumentStorageService.ts +4 -1
- package/src/quorum.ts +1 -1
- package/src/retriableDocumentStorageService.ts +5 -4
- package/src/serializedStateManager.ts +188 -23
- package/src/utils.ts +56 -5
- 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 -151
- 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 -96
- package/lib/test/utils.spec.js.map +0 -1
package/src/protocol.ts
CHANGED
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import { IAudienceOwner } from "@fluidframework/container-definitions";
|
|
7
|
-
import { canBeCoalescedByService } from "@fluidframework/driver-utils";
|
|
6
|
+
import { IAudienceOwner } from "@fluidframework/container-definitions/internal";
|
|
7
|
+
import { canBeCoalescedByService } from "@fluidframework/driver-utils/internal";
|
|
8
8
|
import {
|
|
9
9
|
IProtocolHandler as IBaseProtocolHandler,
|
|
10
10
|
IQuorumSnapshot,
|
|
@@ -4,7 +4,10 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import { IDisposable } from "@fluidframework/core-interfaces";
|
|
7
|
-
import {
|
|
7
|
+
import {
|
|
8
|
+
IDocumentStorageService,
|
|
9
|
+
ISummaryContext,
|
|
10
|
+
} from "@fluidframework/driver-definitions/internal";
|
|
8
11
|
import { ISummaryTree } from "@fluidframework/protocol-definitions";
|
|
9
12
|
|
|
10
13
|
/**
|
package/src/quorum.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import { IFluidCodeDetails } from "@fluidframework/container-definitions";
|
|
6
|
+
import { IFluidCodeDetails } from "@fluidframework/container-definitions/internal";
|
|
7
7
|
import { ICommittedProposal } from "@fluidframework/protocol-definitions";
|
|
8
8
|
|
|
9
9
|
export function initQuorumValuesFromCodeDetails(
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import { IDisposable } from "@fluidframework/core-interfaces";
|
|
7
|
-
import { assert } from "@fluidframework/core-utils";
|
|
7
|
+
import { assert } from "@fluidframework/core-utils/internal";
|
|
8
8
|
import {
|
|
9
9
|
FetchSource,
|
|
10
10
|
IDocumentStorageService,
|
|
@@ -12,8 +12,8 @@ import {
|
|
|
12
12
|
ISnapshot,
|
|
13
13
|
ISnapshotFetchOptions,
|
|
14
14
|
ISummaryContext,
|
|
15
|
-
} from "@fluidframework/driver-definitions";
|
|
16
|
-
import { runWithRetry } from "@fluidframework/driver-utils";
|
|
15
|
+
} from "@fluidframework/driver-definitions/internal";
|
|
16
|
+
import { runWithRetry } from "@fluidframework/driver-utils/internal";
|
|
17
17
|
import {
|
|
18
18
|
ICreateBlobResponse,
|
|
19
19
|
ISnapshotTree,
|
|
@@ -21,7 +21,8 @@ import {
|
|
|
21
21
|
ISummaryTree,
|
|
22
22
|
IVersion,
|
|
23
23
|
} from "@fluidframework/protocol-definitions";
|
|
24
|
-
import {
|
|
24
|
+
import { ITelemetryLoggerExt } from "@fluidframework/telemetry-utils";
|
|
25
|
+
import { GenericError, UsageError } from "@fluidframework/telemetry-utils/internal";
|
|
25
26
|
|
|
26
27
|
export class RetriableDocumentStorageService implements IDocumentStorageService, IDisposable {
|
|
27
28
|
private _disposed = false;
|
|
@@ -3,27 +3,33 @@
|
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import {
|
|
7
|
-
|
|
6
|
+
import {
|
|
7
|
+
IGetPendingLocalStateProps,
|
|
8
|
+
IRuntime,
|
|
9
|
+
} from "@fluidframework/container-definitions/internal";
|
|
10
|
+
import { assert } from "@fluidframework/core-utils/internal";
|
|
8
11
|
import {
|
|
9
12
|
IDocumentStorageService,
|
|
10
13
|
IResolvedUrl,
|
|
11
14
|
ISnapshot,
|
|
12
|
-
} from "@fluidframework/driver-definitions";
|
|
13
|
-
import { isInstanceOfISnapshot } from "@fluidframework/driver-utils";
|
|
15
|
+
} from "@fluidframework/driver-definitions/internal";
|
|
16
|
+
import { isInstanceOfISnapshot } from "@fluidframework/driver-utils/internal";
|
|
14
17
|
import {
|
|
18
|
+
type IDocumentAttributes,
|
|
15
19
|
ISequencedDocumentMessage,
|
|
16
20
|
ISnapshotTree,
|
|
17
21
|
IVersion,
|
|
18
22
|
} from "@fluidframework/protocol-definitions";
|
|
23
|
+
import { ITelemetryLoggerExt } from "@fluidframework/telemetry-utils";
|
|
19
24
|
import {
|
|
20
|
-
ITelemetryLoggerExt,
|
|
21
25
|
MonitoringContext,
|
|
22
26
|
PerformanceEvent,
|
|
23
27
|
UsageError,
|
|
24
28
|
createChildMonitoringContext,
|
|
25
|
-
} from "@fluidframework/telemetry-utils";
|
|
29
|
+
} from "@fluidframework/telemetry-utils/internal";
|
|
30
|
+
|
|
26
31
|
import { ISerializableBlobContents, getBlobContentsFromTree } from "./containerStorageAdapter.js";
|
|
32
|
+
import { getDocumentAttributes } from "./utils.js";
|
|
27
33
|
|
|
28
34
|
export interface SnapshotWithBlobs {
|
|
29
35
|
/**
|
|
@@ -65,10 +71,16 @@ export interface IPendingDetachedContainerState extends SnapshotWithBlobs {
|
|
|
65
71
|
pendingRuntimeState?: unknown;
|
|
66
72
|
}
|
|
67
73
|
|
|
74
|
+
export interface ISnapshotInfo extends SnapshotWithBlobs {
|
|
75
|
+
snapshotSequenceNumber: number;
|
|
76
|
+
}
|
|
77
|
+
|
|
68
78
|
export class SerializedStateManager {
|
|
69
79
|
private readonly processedOps: ISequencedDocumentMessage[] = [];
|
|
70
|
-
private snapshot:
|
|
80
|
+
private snapshot: ISnapshotInfo | undefined;
|
|
71
81
|
private readonly mc: MonitoringContext;
|
|
82
|
+
private latestSnapshot: ISnapshotInfo | undefined;
|
|
83
|
+
private refreshSnapshot: Promise<void> | undefined;
|
|
72
84
|
|
|
73
85
|
constructor(
|
|
74
86
|
private readonly pendingLocalState: IPendingContainerState | undefined,
|
|
@@ -78,6 +90,7 @@ export class SerializedStateManager {
|
|
|
78
90
|
"readBlob" | "getSnapshotTree" | "getSnapshot" | "getVersions"
|
|
79
91
|
>,
|
|
80
92
|
private readonly _offlineLoadEnabled: boolean,
|
|
93
|
+
private readonly newSnapshotFetched?: () => void,
|
|
81
94
|
) {
|
|
82
95
|
this.mc = createChildMonitoringContext({
|
|
83
96
|
logger: subLogger,
|
|
@@ -92,6 +105,7 @@ export class SerializedStateManager {
|
|
|
92
105
|
public addProcessedOp(message: ISequencedDocumentMessage) {
|
|
93
106
|
if (this.offlineLoadEnabled) {
|
|
94
107
|
this.processedOps.push(message);
|
|
108
|
+
this.updateSnapshotAndProcessedOpsMaybe();
|
|
95
109
|
}
|
|
96
110
|
}
|
|
97
111
|
|
|
@@ -100,36 +114,112 @@ export class SerializedStateManager {
|
|
|
100
114
|
supportGetSnapshotApi: boolean,
|
|
101
115
|
) {
|
|
102
116
|
if (this.pendingLocalState === undefined) {
|
|
103
|
-
const {
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
assert(baseSnapshot !== undefined, 0x8e4 /* Snapshot should exist */);
|
|
117
|
+
const { baseSnapshot, version } = await getSnapshotTree(
|
|
118
|
+
this.mc,
|
|
119
|
+
this.storageAdapter,
|
|
120
|
+
supportGetSnapshotApi,
|
|
121
|
+
specifiedVersion,
|
|
122
|
+
);
|
|
110
123
|
// non-interactive clients will not have any pending state we want to save
|
|
111
124
|
if (this.offlineLoadEnabled) {
|
|
112
125
|
const snapshotBlobs = await getBlobContentsFromTree(
|
|
113
126
|
baseSnapshot,
|
|
114
127
|
this.storageAdapter,
|
|
115
128
|
);
|
|
116
|
-
|
|
129
|
+
const attributes = await getDocumentAttributes(this.storageAdapter, baseSnapshot);
|
|
130
|
+
this.snapshot = {
|
|
131
|
+
baseSnapshot,
|
|
132
|
+
snapshotBlobs,
|
|
133
|
+
snapshotSequenceNumber: attributes.sequenceNumber,
|
|
134
|
+
};
|
|
117
135
|
}
|
|
118
136
|
return { baseSnapshot, version };
|
|
119
137
|
} else {
|
|
120
138
|
const { baseSnapshot, snapshotBlobs } = this.pendingLocalState;
|
|
121
|
-
|
|
139
|
+
const attributes = await getDocumentAttributes(this.storageAdapter, baseSnapshot);
|
|
140
|
+
this.snapshot = {
|
|
141
|
+
baseSnapshot,
|
|
142
|
+
snapshotBlobs,
|
|
143
|
+
snapshotSequenceNumber: attributes.sequenceNumber,
|
|
144
|
+
};
|
|
145
|
+
this.refreshSnapshot ??= (async () => {
|
|
146
|
+
this.latestSnapshot = await getLatestSnapshotInfo(
|
|
147
|
+
this.mc,
|
|
148
|
+
this.storageAdapter,
|
|
149
|
+
supportGetSnapshotApi,
|
|
150
|
+
);
|
|
151
|
+
this.newSnapshotFetched?.();
|
|
152
|
+
this.updateSnapshotAndProcessedOpsMaybe();
|
|
153
|
+
})();
|
|
154
|
+
|
|
122
155
|
return { baseSnapshot, version: undefined };
|
|
123
156
|
}
|
|
124
157
|
}
|
|
125
158
|
|
|
159
|
+
/**
|
|
160
|
+
* Updates class snapshot and processedOps if we have a new snapshot and it's among processedOps range.
|
|
161
|
+
*/
|
|
162
|
+
private updateSnapshotAndProcessedOpsMaybe() {
|
|
163
|
+
if (this.latestSnapshot === undefined || this.processedOps.length === 0) {
|
|
164
|
+
// can't refresh latest snapshot until we have processed the ops up to it.
|
|
165
|
+
// Pending state would be behind the latest snapshot.
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
const snapshotSequenceNumber = this.latestSnapshot.snapshotSequenceNumber;
|
|
169
|
+
const firstProcessedOpSequenceNumber = this.processedOps[0].sequenceNumber;
|
|
170
|
+
const lastProcessedOpSequenceNumber =
|
|
171
|
+
this.processedOps[this.processedOps.length - 1].sequenceNumber;
|
|
172
|
+
|
|
173
|
+
if (snapshotSequenceNumber < firstProcessedOpSequenceNumber) {
|
|
174
|
+
// Snapshot seq number is older than our first processed op, which could mean we're fetching
|
|
175
|
+
// the same snapshot that we already have or snapshot is too old, implicating an unexpected behavior.
|
|
176
|
+
this.mc.logger.sendTelemetryEvent({
|
|
177
|
+
eventName: "OldSnapshotFetchWhileRefreshing",
|
|
178
|
+
snapshotSequenceNumber,
|
|
179
|
+
firstProcessedOpSequenceNumber,
|
|
180
|
+
lastProcessedOpSequenceNumber,
|
|
181
|
+
stashedSnapshotSequenceNumber: this.snapshot?.snapshotSequenceNumber,
|
|
182
|
+
});
|
|
183
|
+
this.latestSnapshot = undefined;
|
|
184
|
+
} else if (snapshotSequenceNumber <= lastProcessedOpSequenceNumber) {
|
|
185
|
+
// Snapshot seq num is between the first and last processed op.
|
|
186
|
+
// Remove the ops that are already part of the snapshot
|
|
187
|
+
this.processedOps.splice(
|
|
188
|
+
0,
|
|
189
|
+
snapshotSequenceNumber - firstProcessedOpSequenceNumber + 1,
|
|
190
|
+
);
|
|
191
|
+
this.snapshot = this.latestSnapshot;
|
|
192
|
+
this.latestSnapshot = undefined;
|
|
193
|
+
this.mc.logger.sendTelemetryEvent({
|
|
194
|
+
eventName: "SnapshotRefreshed",
|
|
195
|
+
snapshotSequenceNumber,
|
|
196
|
+
firstProcessedOpSequenceNumber,
|
|
197
|
+
newFirstProcessedOpSequenceNumber:
|
|
198
|
+
this.processedOps.length === 0
|
|
199
|
+
? undefined
|
|
200
|
+
: this.processedOps[0].sequenceNumber,
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
126
205
|
/**
|
|
127
206
|
* This method is only meant to be used by Container.attach() to set the initial
|
|
128
207
|
* base snapshot when attaching.
|
|
129
208
|
* @param snapshot - snapshot and blobs collected while attaching
|
|
130
209
|
*/
|
|
131
|
-
public
|
|
132
|
-
this.
|
|
210
|
+
public setInitialSnapshot(snapshot: SnapshotWithBlobs | undefined) {
|
|
211
|
+
if (this.offlineLoadEnabled) {
|
|
212
|
+
assert(this.snapshot === undefined, "inital snapshot should only be defined once");
|
|
213
|
+
assert(snapshot !== undefined, "attachment snapshot should be defined");
|
|
214
|
+
const { baseSnapshot, snapshotBlobs } = snapshot;
|
|
215
|
+
const attributesHash =
|
|
216
|
+
".protocol" in baseSnapshot.trees
|
|
217
|
+
? baseSnapshot.trees[".protocol"].blobs.attributes
|
|
218
|
+
: baseSnapshot.blobs[".attributes"];
|
|
219
|
+
const attributes = JSON.parse(snapshotBlobs[attributesHash]);
|
|
220
|
+
assert(attributes.sequenceNumber === 0, "trying to set a non attachment snapshot");
|
|
221
|
+
this.snapshot = { ...snapshot, snapshotSequenceNumber: attributes.sequenceNumber };
|
|
222
|
+
}
|
|
133
223
|
}
|
|
134
224
|
|
|
135
225
|
public async getPendingLocalStateCore(
|
|
@@ -171,11 +261,84 @@ export class SerializedStateManager {
|
|
|
171
261
|
}
|
|
172
262
|
}
|
|
173
263
|
|
|
264
|
+
/**
|
|
265
|
+
* Retrieves the most recent snapshot and returns its info.
|
|
266
|
+
*
|
|
267
|
+
* @param mc - The monitoring context.
|
|
268
|
+
* @param storageAdapter - The storage adapter providing methods to retrieve the snapshot.
|
|
269
|
+
* @param supportGetSnapshotApi - a boolean indicating whether to use the fetchISnapshot or fetchISnapshotTree.
|
|
270
|
+
* @returns a SnapshotInfo object containing the snapshot tree, snapshot blobs and its sequence number.
|
|
271
|
+
*/
|
|
272
|
+
export async function getLatestSnapshotInfo(
|
|
273
|
+
mc: MonitoringContext,
|
|
274
|
+
storageAdapter: Pick<
|
|
275
|
+
IDocumentStorageService,
|
|
276
|
+
"getSnapshot" | "getSnapshotTree" | "getVersions" | "readBlob"
|
|
277
|
+
>,
|
|
278
|
+
supportGetSnapshotApi: boolean,
|
|
279
|
+
): Promise<ISnapshotInfo | undefined> {
|
|
280
|
+
return PerformanceEvent.timedExecAsync(
|
|
281
|
+
mc.logger,
|
|
282
|
+
{ eventName: "GetLatestSnapshotInfo" },
|
|
283
|
+
async () => {
|
|
284
|
+
const { baseSnapshot } = await getSnapshotTree(
|
|
285
|
+
mc,
|
|
286
|
+
storageAdapter,
|
|
287
|
+
supportGetSnapshotApi,
|
|
288
|
+
undefined,
|
|
289
|
+
);
|
|
290
|
+
const snapshotBlobs = await getBlobContentsFromTree(baseSnapshot, storageAdapter);
|
|
291
|
+
const attributes: IDocumentAttributes = await getDocumentAttributes(
|
|
292
|
+
storageAdapter,
|
|
293
|
+
baseSnapshot,
|
|
294
|
+
);
|
|
295
|
+
const snapshotSequenceNumber = attributes.sequenceNumber;
|
|
296
|
+
return { baseSnapshot, snapshotBlobs, snapshotSequenceNumber };
|
|
297
|
+
},
|
|
298
|
+
).catch(() => undefined);
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
/**
|
|
302
|
+
* Retrieves a snapshot from the storage adapter and transforms it into an ISnapshotTree object.
|
|
303
|
+
*
|
|
304
|
+
* @param mc - The monitoring context.
|
|
305
|
+
* @param storageAdapter - The storage adapter providing methods to retrieve the snapshot.
|
|
306
|
+
* @param supportGetSnapshotApi - a boolean indicating whether to use the fetchISnapshot or fetchISnapshotTree.
|
|
307
|
+
* @param specifiedVersion - An optional version string specifying the version of the snapshot tree to fetch.
|
|
308
|
+
* @returns - An ISnapshotTree and its version.
|
|
309
|
+
*/
|
|
310
|
+
async function getSnapshotTree(
|
|
311
|
+
mc: MonitoringContext,
|
|
312
|
+
storageAdapter: Pick<
|
|
313
|
+
IDocumentStorageService,
|
|
314
|
+
"getSnapshot" | "getSnapshotTree" | "getVersions"
|
|
315
|
+
>,
|
|
316
|
+
supportGetSnapshotApi: boolean,
|
|
317
|
+
specifiedVersion: string | undefined,
|
|
318
|
+
): Promise<{ baseSnapshot: ISnapshotTree; version?: IVersion }> {
|
|
319
|
+
const { snapshot, version } = supportGetSnapshotApi
|
|
320
|
+
? await fetchISnapshot(mc, storageAdapter, specifiedVersion)
|
|
321
|
+
: await fetchISnapshotTree(mc, storageAdapter, specifiedVersion);
|
|
322
|
+
const baseSnapshot: ISnapshotTree | undefined = isInstanceOfISnapshot(snapshot)
|
|
323
|
+
? snapshot.snapshotTree
|
|
324
|
+
: snapshot;
|
|
325
|
+
assert(baseSnapshot !== undefined, 0x8e4 /* Snapshot should exist */);
|
|
326
|
+
return { baseSnapshot, version };
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
/**
|
|
330
|
+
* Fetches an ISnapshot from a storage adapter based on the specified version.
|
|
331
|
+
*
|
|
332
|
+
* @param mc - The monitoring context.
|
|
333
|
+
* @param storageAdapter - The storage adapter providing a getSnapshot method to retrieve the ISnapshot and version.
|
|
334
|
+
* @param specifiedVersion - An optional version string specifying the version of the snapshot tree to fetch.
|
|
335
|
+
* @returns - The fetched snapshot tree and its version.
|
|
336
|
+
*/
|
|
174
337
|
export async function fetchISnapshot(
|
|
175
338
|
mc: MonitoringContext,
|
|
176
339
|
storageAdapter: Pick<IDocumentStorageService, "getSnapshot">,
|
|
177
340
|
specifiedVersion: string | undefined,
|
|
178
|
-
): Promise<{ snapshot?: ISnapshot
|
|
341
|
+
): Promise<{ snapshot?: ISnapshot; version?: IVersion }> {
|
|
179
342
|
const snapshot = await storageAdapter.getSnapshot?.({ versionId: specifiedVersion });
|
|
180
343
|
const version: IVersion | undefined =
|
|
181
344
|
snapshot?.snapshotTree.id === undefined
|
|
@@ -190,7 +353,6 @@ export async function fetchISnapshot(
|
|
|
190
353
|
eventName: "getSnapshotTreeFailed",
|
|
191
354
|
id: specifiedVersion,
|
|
192
355
|
});
|
|
193
|
-
// Not sure if this should be here actually
|
|
194
356
|
} else if (snapshot !== undefined && version?.id === undefined) {
|
|
195
357
|
mc.logger.sendErrorEvent({
|
|
196
358
|
eventName: "getSnapshotFetchedTreeWithoutVersionId",
|
|
@@ -201,9 +363,12 @@ export async function fetchISnapshot(
|
|
|
201
363
|
}
|
|
202
364
|
|
|
203
365
|
/**
|
|
204
|
-
*
|
|
205
|
-
*
|
|
206
|
-
* @
|
|
366
|
+
* Fetches an ISnapshotTree from a storage adapter based on the specified version.
|
|
367
|
+
*
|
|
368
|
+
* @param mc - The monitoring context.
|
|
369
|
+
* @param storageAdapter - The storage adapter providing methods to retrieve the ISnapshotTree and version.
|
|
370
|
+
* @param specifiedVersion - An optional version string specifying the version of the snapshot tree to fetch.
|
|
371
|
+
* @returns - The fetched snapshot tree and its version.
|
|
207
372
|
*/
|
|
208
373
|
export async function fetchISnapshotTree(
|
|
209
374
|
mc: MonitoringContext,
|
package/src/utils.ts
CHANGED
|
@@ -3,26 +3,32 @@
|
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import { Uint8ArrayToString, stringToBuffer } from "@fluid-internal/client-utils";
|
|
7
|
-
import { assert, compareArrays, unreachableCase } from "@fluidframework/core-utils";
|
|
8
|
-
import { DriverErrorTypes
|
|
6
|
+
import { Uint8ArrayToString, bufferToString, stringToBuffer } from "@fluid-internal/client-utils";
|
|
7
|
+
import { assert, compareArrays, unreachableCase } from "@fluidframework/core-utils/internal";
|
|
8
|
+
import { DriverErrorTypes } from "@fluidframework/driver-definitions";
|
|
9
|
+
import {
|
|
10
|
+
IDocumentStorageService,
|
|
11
|
+
type ISnapshot,
|
|
12
|
+
} from "@fluidframework/driver-definitions/internal";
|
|
9
13
|
import {
|
|
10
14
|
CombinedAppAndProtocolSummary,
|
|
11
15
|
DeltaStreamConnectionForbiddenError,
|
|
12
16
|
isCombinedAppAndProtocolSummary,
|
|
13
17
|
readAndParse,
|
|
14
|
-
} from "@fluidframework/driver-utils";
|
|
18
|
+
} from "@fluidframework/driver-utils/internal";
|
|
15
19
|
import {
|
|
16
20
|
IDocumentAttributes,
|
|
17
21
|
ISnapshotTree,
|
|
18
22
|
ISummaryTree,
|
|
19
23
|
SummaryType,
|
|
20
24
|
} from "@fluidframework/protocol-definitions";
|
|
21
|
-
import { LoggingError, UsageError } from "@fluidframework/telemetry-utils";
|
|
25
|
+
import { LoggingError, UsageError } from "@fluidframework/telemetry-utils/internal";
|
|
22
26
|
import { v4 as uuid } from "uuid";
|
|
27
|
+
|
|
23
28
|
import { ISerializableBlobContents } from "./containerStorageAdapter.js";
|
|
24
29
|
import type {
|
|
25
30
|
IPendingDetachedContainerState,
|
|
31
|
+
ISnapshotInfo,
|
|
26
32
|
SnapshotWithBlobs,
|
|
27
33
|
} from "./serializedStateManager.js";
|
|
28
34
|
|
|
@@ -167,6 +173,51 @@ function convertSummaryToSnapshotAndBlobs(summary: ISummaryTree): SnapshotWithBl
|
|
|
167
173
|
return pendingSnapshot;
|
|
168
174
|
}
|
|
169
175
|
|
|
176
|
+
/**
|
|
177
|
+
* Converts a snapshot to snapshotInfo with its blob contents
|
|
178
|
+
* to align detached container format with IPendingContainerState
|
|
179
|
+
*
|
|
180
|
+
* Note, this assumes the ISnapshot sequence number is defined. Otherwise an assert will be thrown
|
|
181
|
+
* @param snapshot - ISnapshot
|
|
182
|
+
*/
|
|
183
|
+
export function convertSnapshotToSnapshotInfo(snapshot: ISnapshot): ISnapshotInfo {
|
|
184
|
+
assert(snapshot.sequenceNumber !== undefined, "Snapshot sequence number is missing");
|
|
185
|
+
const snapshotBlobs: ISerializableBlobContents = {};
|
|
186
|
+
for (const [blobId, arrayBufferLike] of snapshot.blobContents.entries()) {
|
|
187
|
+
snapshotBlobs[blobId] = bufferToString(arrayBufferLike, "utf8");
|
|
188
|
+
}
|
|
189
|
+
return {
|
|
190
|
+
baseSnapshot: snapshot.snapshotTree,
|
|
191
|
+
snapshotBlobs,
|
|
192
|
+
snapshotSequenceNumber: snapshot.sequenceNumber,
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Converts a snapshot to snapshotInfo with its blob contents
|
|
198
|
+
* to align detached container format with IPendingContainerState
|
|
199
|
+
*
|
|
200
|
+
* Note, this assumes the ISnapshot sequence number is defined. Otherwise an assert will be thrown
|
|
201
|
+
* @param snapshot - ISnapshot
|
|
202
|
+
*/
|
|
203
|
+
export function convertSnapshotInfoToSnapshot(
|
|
204
|
+
snapshotInfo: ISnapshotInfo,
|
|
205
|
+
snapshotSequenceNumber: number,
|
|
206
|
+
): ISnapshot {
|
|
207
|
+
const blobContents = new Map<string, ArrayBufferLike>();
|
|
208
|
+
for (const [blobId, serializedContent] of Object.entries(snapshotInfo.snapshotBlobs)) {
|
|
209
|
+
blobContents.set(blobId, stringToBuffer(serializedContent, "utf8"));
|
|
210
|
+
}
|
|
211
|
+
return {
|
|
212
|
+
snapshotTree: snapshotInfo.baseSnapshot,
|
|
213
|
+
blobContents,
|
|
214
|
+
ops: [],
|
|
215
|
+
sequenceNumber: snapshotSequenceNumber,
|
|
216
|
+
latestSequenceNumber: undefined,
|
|
217
|
+
snapshotFormatV: 1,
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
|
|
170
221
|
/**
|
|
171
222
|
* Converts summary parts into a SnapshotTree and its blob contents.
|
|
172
223
|
* @param protocolSummaryTree - Protocol Summary Tree
|