@fluidframework/container-loader 2.0.0-dev-rc.2.0.0.246488 → 2.0.0-dev-rc.3.0.0.253463
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 +6 -9
- 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.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 +42 -42
- 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-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 +9 -46
- package/dist/container.d.ts.map +1 -1
- package/dist/container.js +96 -108
- 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 +7 -6
- package/dist/deltaManager.d.ts.map +1 -1
- package/dist/deltaManager.js +45 -45
- 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/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/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 +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 +87 -16
- package/dist/serializedStateManager.d.ts.map +1 -1
- package/dist/serializedStateManager.js +164 -80
- package/dist/serializedStateManager.js.map +1 -1
- package/dist/utils.d.ts +6 -7
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +39 -23
- package/dist/utils.js.map +1 -1
- 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 +5 -5
- 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-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 +9 -46
- package/lib/container.d.ts.map +1 -1
- package/lib/container.js +28 -40
- 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 +7 -6
- package/lib/deltaManager.d.ts.map +1 -1
- package/lib/deltaManager.js +5 -5
- 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/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/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 +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 +87 -16
- package/lib/serializedStateManager.d.ts.map +1 -1
- package/lib/serializedStateManager.js +156 -75
- package/lib/serializedStateManager.js.map +1 -1
- package/lib/tsdoc-metadata.json +11 -0
- package/lib/utils.d.ts +6 -7
- package/lib/utils.d.ts.map +1 -1
- package/lib/utils.js +27 -12
- package/lib/utils.js.map +1 -1
- package/package.json +19 -28
- package/src/attachment.ts +9 -8
- package/src/audience.ts +2 -2
- package/src/catchUpMonitor.ts +2 -2
- package/src/connectionManager.ts +19 -19
- package/src/connectionStateHandler.ts +7 -7
- package/src/container.ts +78 -133
- 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 +31 -25
- 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 +1 -1
- package/src/retriableDocumentStorageService.ts +6 -5
- package/src/serializedStateManager.ts +276 -110
- package/src/utils.ts +51 -20
- 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/src/utils.ts
CHANGED
|
@@ -3,19 +3,30 @@
|
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import { v4 as uuid } from "uuid";
|
|
7
6
|
import { Uint8ArrayToString, stringToBuffer } from "@fluid-internal/client-utils";
|
|
8
|
-
import { assert, compareArrays, unreachableCase } from "@fluidframework/core-utils";
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
7
|
+
import { assert, compareArrays, unreachableCase } from "@fluidframework/core-utils/internal";
|
|
8
|
+
import { DriverErrorTypes } from "@fluidframework/driver-definitions";
|
|
9
|
+
import { IDocumentStorageService } from "@fluidframework/driver-definitions/internal";
|
|
11
10
|
import {
|
|
12
11
|
CombinedAppAndProtocolSummary,
|
|
13
12
|
DeltaStreamConnectionForbiddenError,
|
|
14
13
|
isCombinedAppAndProtocolSummary,
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
readAndParse,
|
|
15
|
+
} from "@fluidframework/driver-utils/internal";
|
|
16
|
+
import {
|
|
17
|
+
IDocumentAttributes,
|
|
18
|
+
ISnapshotTree,
|
|
19
|
+
ISummaryTree,
|
|
20
|
+
SummaryType,
|
|
21
|
+
} from "@fluidframework/protocol-definitions";
|
|
22
|
+
import { LoggingError, UsageError } from "@fluidframework/telemetry-utils/internal";
|
|
23
|
+
import { v4 as uuid } from "uuid";
|
|
24
|
+
|
|
17
25
|
import { ISerializableBlobContents } from "./containerStorageAdapter.js";
|
|
18
|
-
import {
|
|
26
|
+
import type {
|
|
27
|
+
IPendingDetachedContainerState,
|
|
28
|
+
SnapshotWithBlobs,
|
|
29
|
+
} from "./serializedStateManager.js";
|
|
19
30
|
|
|
20
31
|
// This is used when we rehydrate a container from the snapshot. Here we put the blob contents
|
|
21
32
|
// in separate property: blobContents.
|
|
@@ -111,10 +122,7 @@ export function combineAppAndProtocolSummary(
|
|
|
111
122
|
* to align detached container format with IPendingContainerState
|
|
112
123
|
* @param summary - ISummaryTree
|
|
113
124
|
*/
|
|
114
|
-
function convertSummaryToSnapshotAndBlobs(summary: ISummaryTree): {
|
|
115
|
-
tree: ISnapshotTree;
|
|
116
|
-
blobs: ISerializableBlobContents;
|
|
117
|
-
} {
|
|
125
|
+
function convertSummaryToSnapshotAndBlobs(summary: ISummaryTree): SnapshotWithBlobs {
|
|
118
126
|
let blobContents: ISerializableBlobContents = {};
|
|
119
127
|
const treeNode: ISnapshotTree = {
|
|
120
128
|
blobs: {},
|
|
@@ -129,9 +137,9 @@ function convertSummaryToSnapshotAndBlobs(summary: ISummaryTree): {
|
|
|
129
137
|
|
|
130
138
|
switch (summaryObject.type) {
|
|
131
139
|
case SummaryType.Tree: {
|
|
132
|
-
const
|
|
133
|
-
treeNode.trees[key] =
|
|
134
|
-
blobContents = { ...blobContents, ...
|
|
140
|
+
const innerSnapshot = convertSummaryToSnapshotAndBlobs(summaryObject);
|
|
141
|
+
treeNode.trees[key] = innerSnapshot.baseSnapshot;
|
|
142
|
+
blobContents = { ...blobContents, ...innerSnapshot.snapshotBlobs };
|
|
135
143
|
break;
|
|
136
144
|
}
|
|
137
145
|
case SummaryType.Attachment:
|
|
@@ -157,7 +165,8 @@ function convertSummaryToSnapshotAndBlobs(summary: ISummaryTree): {
|
|
|
157
165
|
}
|
|
158
166
|
}
|
|
159
167
|
}
|
|
160
|
-
|
|
168
|
+
const pendingSnapshot = { baseSnapshot: treeNode, snapshotBlobs: blobContents };
|
|
169
|
+
return pendingSnapshot;
|
|
161
170
|
}
|
|
162
171
|
|
|
163
172
|
/**
|
|
@@ -168,7 +177,7 @@ function convertSummaryToSnapshotAndBlobs(summary: ISummaryTree): {
|
|
|
168
177
|
function convertProtocolAndAppSummaryToSnapshotAndBlobs(
|
|
169
178
|
protocolSummaryTree: ISummaryTree,
|
|
170
179
|
appSummaryTree: ISummaryTree,
|
|
171
|
-
):
|
|
180
|
+
): SnapshotWithBlobs {
|
|
172
181
|
const combinedSummary: ISummaryTree = {
|
|
173
182
|
type: SummaryType.Tree,
|
|
174
183
|
tree: { ...appSummaryTree.tree },
|
|
@@ -181,7 +190,7 @@ function convertProtocolAndAppSummaryToSnapshotAndBlobs(
|
|
|
181
190
|
|
|
182
191
|
export const getSnapshotTreeAndBlobsFromSerializedContainer = (
|
|
183
192
|
detachedContainerSnapshot: ISummaryTree,
|
|
184
|
-
):
|
|
193
|
+
): SnapshotWithBlobs => {
|
|
185
194
|
assert(
|
|
186
195
|
isCombinedAppAndProtocolSummary(detachedContainerSnapshot),
|
|
187
196
|
0x8e6 /* Protocol and App summary trees should be present */,
|
|
@@ -264,12 +273,12 @@ export function getDetachedContainerStateFromSerializedContainer(
|
|
|
264
273
|
if (isPendingDetachedContainerState(parsedContainerState)) {
|
|
265
274
|
return parsedContainerState;
|
|
266
275
|
} else if (isCombinedAppAndProtocolSummary(parsedContainerState)) {
|
|
267
|
-
const {
|
|
276
|
+
const { baseSnapshot, snapshotBlobs } =
|
|
268
277
|
getSnapshotTreeAndBlobsFromSerializedContainer(parsedContainerState);
|
|
269
278
|
const detachedContainerState: IPendingDetachedContainerState = {
|
|
270
279
|
attached: false,
|
|
271
|
-
baseSnapshot
|
|
272
|
-
snapshotBlobs
|
|
280
|
+
baseSnapshot,
|
|
281
|
+
snapshotBlobs,
|
|
273
282
|
hasAttachmentBlobs: parsedContainerState.tree[hasBlobsSummaryTree] !== undefined,
|
|
274
283
|
};
|
|
275
284
|
return detachedContainerState;
|
|
@@ -305,3 +314,25 @@ export const runSingle = <A extends any[], R>(func: (...args: A) => Promise<R>)
|
|
|
305
314
|
return running.result;
|
|
306
315
|
};
|
|
307
316
|
};
|
|
317
|
+
|
|
318
|
+
export async function getDocumentAttributes(
|
|
319
|
+
storage: Pick<IDocumentStorageService, "readBlob">,
|
|
320
|
+
tree: ISnapshotTree | undefined,
|
|
321
|
+
): Promise<IDocumentAttributes> {
|
|
322
|
+
if (tree === undefined) {
|
|
323
|
+
return {
|
|
324
|
+
minimumSequenceNumber: 0,
|
|
325
|
+
sequenceNumber: 0,
|
|
326
|
+
};
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
// Backward compatibility: old docs would have ".attributes" instead of "attributes"
|
|
330
|
+
const attributesHash =
|
|
331
|
+
".protocol" in tree.trees
|
|
332
|
+
? tree.trees[".protocol"].blobs.attributes
|
|
333
|
+
: tree.blobs[".attributes"];
|
|
334
|
+
|
|
335
|
+
const attributes = await readAndParse<IDocumentAttributes>(storage, attributesHash);
|
|
336
|
+
|
|
337
|
+
return attributes;
|
|
338
|
+
}
|
|
@@ -1,380 +0,0 @@
|
|
|
1
|
-
/*!
|
|
2
|
-
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
|
-
* Licensed under the MIT License.
|
|
4
|
-
*/
|
|
5
|
-
import { strict as assert } from "assert";
|
|
6
|
-
import { AttachState } from "@fluidframework/container-definitions";
|
|
7
|
-
import { v4 as uuid } from "uuid";
|
|
8
|
-
import { SummaryType } from "@fluidframework/protocol-definitions";
|
|
9
|
-
import { stringToBuffer } from "@fluid-internal/client-utils";
|
|
10
|
-
import { runRetriableAttachProcess, } from "../attachment.js";
|
|
11
|
-
import { combineAppAndProtocolSummary } from "../utils.js";
|
|
12
|
-
const emptySummary = combineAppAndProtocolSummary({ tree: {}, type: SummaryType.Tree }, { tree: {}, type: SummaryType.Tree });
|
|
13
|
-
const addCallCounts = (obj) => {
|
|
14
|
-
const calls = Object.keys(obj).reduce((pv, cv) => {
|
|
15
|
-
pv[cv] = 0;
|
|
16
|
-
return pv;
|
|
17
|
-
}, {});
|
|
18
|
-
return new Proxy(obj, {
|
|
19
|
-
get: (t, p, r) => {
|
|
20
|
-
if (p === "calls") {
|
|
21
|
-
return calls;
|
|
22
|
-
}
|
|
23
|
-
else {
|
|
24
|
-
calls[p]++;
|
|
25
|
-
return Reflect.get(t, p, r);
|
|
26
|
-
}
|
|
27
|
-
},
|
|
28
|
-
});
|
|
29
|
-
};
|
|
30
|
-
const createDetachStorage = (blobCount) => {
|
|
31
|
-
const blobs = new Map(Array.from({ length: blobCount }).map((_, i) => [
|
|
32
|
-
i.toString(),
|
|
33
|
-
stringToBuffer(`${i}-content`, "utf-8"),
|
|
34
|
-
]));
|
|
35
|
-
return addCallCounts({
|
|
36
|
-
get size() {
|
|
37
|
-
return blobs.size;
|
|
38
|
-
},
|
|
39
|
-
getBlobIds() {
|
|
40
|
-
return [...blobs.keys()];
|
|
41
|
-
},
|
|
42
|
-
async readBlob(id) {
|
|
43
|
-
const content = blobs.get(id);
|
|
44
|
-
assert(content !== undefined, `no blob content for [${id}]`);
|
|
45
|
-
return content;
|
|
46
|
-
},
|
|
47
|
-
});
|
|
48
|
-
};
|
|
49
|
-
const createProxyWithFailDefault = (partial = {}) => {
|
|
50
|
-
return new Proxy(partial, {
|
|
51
|
-
get: (t, p, r) => {
|
|
52
|
-
if (p in t) {
|
|
53
|
-
return Reflect.get(t, p, r);
|
|
54
|
-
}
|
|
55
|
-
return new Proxy({}, {
|
|
56
|
-
get: () => assert.fail(`unexpected call too ${p.toString()}`),
|
|
57
|
-
});
|
|
58
|
-
},
|
|
59
|
-
});
|
|
60
|
-
};
|
|
61
|
-
describe("runRetriableAttachProcess", () => {
|
|
62
|
-
describe("end to end process", () => {
|
|
63
|
-
it("From DetachedDefaultData without blobs or offline", async () => {
|
|
64
|
-
const initial = {
|
|
65
|
-
state: AttachState.Detached,
|
|
66
|
-
};
|
|
67
|
-
let attachmentData;
|
|
68
|
-
await runRetriableAttachProcess({
|
|
69
|
-
initialAttachmentData: initial,
|
|
70
|
-
offlineLoadEnabled: false,
|
|
71
|
-
setAttachmentData: (data) => (attachmentData = data),
|
|
72
|
-
createAttachmentSummary: (redirectTable) => {
|
|
73
|
-
assert.strictEqual(redirectTable, undefined, "redirectTable");
|
|
74
|
-
return emptySummary;
|
|
75
|
-
},
|
|
76
|
-
createOrGetStorageService: async () => createProxyWithFailDefault(),
|
|
77
|
-
});
|
|
78
|
-
assert.strictEqual(attachmentData?.state, AttachState.Attached, "should be attached");
|
|
79
|
-
});
|
|
80
|
-
it("From DetachedDefaultData with offline and without blobs", async () => {
|
|
81
|
-
const initial = {
|
|
82
|
-
state: AttachState.Detached,
|
|
83
|
-
};
|
|
84
|
-
let attachmentData;
|
|
85
|
-
const snapshot = await runRetriableAttachProcess({
|
|
86
|
-
initialAttachmentData: initial,
|
|
87
|
-
offlineLoadEnabled: true,
|
|
88
|
-
setAttachmentData: (data) => (attachmentData = data),
|
|
89
|
-
createAttachmentSummary: (redirectTable) => {
|
|
90
|
-
assert.strictEqual(redirectTable, undefined, "redirectTable");
|
|
91
|
-
return emptySummary;
|
|
92
|
-
},
|
|
93
|
-
createOrGetStorageService: async () => ({
|
|
94
|
-
createBlob: async () => assert.fail("no blobs should be created"),
|
|
95
|
-
uploadSummaryWithContext: async () => assert.fail("no summary should be uploaded outside of create"),
|
|
96
|
-
}),
|
|
97
|
-
});
|
|
98
|
-
assert.strictEqual(attachmentData?.state, AttachState.Attached, "should be attached");
|
|
99
|
-
assert.notStrictEqual(snapshot, undefined, "should have snapshot");
|
|
100
|
-
});
|
|
101
|
-
it("From DetachedDefaultData with blobs and without offline", async () => {
|
|
102
|
-
const initial = {
|
|
103
|
-
state: AttachState.Detached,
|
|
104
|
-
};
|
|
105
|
-
let attachmentData;
|
|
106
|
-
const blobCount = 10;
|
|
107
|
-
const detachedBlobStorage = createDetachStorage(blobCount);
|
|
108
|
-
const storageAdapter = addCallCounts({
|
|
109
|
-
createBlob: async () => Promise.resolve({ id: uuid() }),
|
|
110
|
-
uploadSummaryWithContext: async () => Promise.resolve(uuid()),
|
|
111
|
-
});
|
|
112
|
-
await runRetriableAttachProcess({
|
|
113
|
-
initialAttachmentData: initial,
|
|
114
|
-
offlineLoadEnabled: false,
|
|
115
|
-
setAttachmentData: (data) => (attachmentData = data),
|
|
116
|
-
createAttachmentSummary: (redirectTable) => {
|
|
117
|
-
assert.strictEqual(redirectTable?.size, blobCount, "redirectTable?.size");
|
|
118
|
-
return emptySummary;
|
|
119
|
-
},
|
|
120
|
-
createOrGetStorageService: async () => storageAdapter,
|
|
121
|
-
detachedBlobStorage,
|
|
122
|
-
});
|
|
123
|
-
// expect every blob to read, and uploaded
|
|
124
|
-
assert.strictEqual(detachedBlobStorage.calls.readBlob, blobCount, "detachedBlobStorage.calls.readBlob");
|
|
125
|
-
assert.strictEqual(storageAdapter.calls.createBlob, blobCount, "storageAdapter.calls.createBlob");
|
|
126
|
-
// after blobs are uploaded summary should be
|
|
127
|
-
assert.strictEqual(storageAdapter.calls.uploadSummaryWithContext, 1, "storageAdapter.calls.uploadSummaryWithContext");
|
|
128
|
-
assert.strictEqual(attachmentData?.state, AttachState.Attached, "should be attached");
|
|
129
|
-
});
|
|
130
|
-
it("From DetachedDefaultData with zero blobs and without offline", async () => {
|
|
131
|
-
const initial = {
|
|
132
|
-
state: AttachState.Detached,
|
|
133
|
-
};
|
|
134
|
-
let attachmentData;
|
|
135
|
-
await runRetriableAttachProcess({
|
|
136
|
-
initialAttachmentData: initial,
|
|
137
|
-
offlineLoadEnabled: false,
|
|
138
|
-
setAttachmentData: (data) => (attachmentData = data),
|
|
139
|
-
createAttachmentSummary: (redirectTable) => {
|
|
140
|
-
assert.strictEqual(redirectTable, undefined, "redirectTable");
|
|
141
|
-
return emptySummary;
|
|
142
|
-
},
|
|
143
|
-
createOrGetStorageService: async () => createProxyWithFailDefault(),
|
|
144
|
-
// we have blobs storage, but it is empty,
|
|
145
|
-
// so it should be treat like there are no blobs
|
|
146
|
-
detachedBlobStorage: createProxyWithFailDefault({ size: 0 }),
|
|
147
|
-
});
|
|
148
|
-
assert.strictEqual(attachmentData?.state, AttachState.Attached, "should be attached");
|
|
149
|
-
});
|
|
150
|
-
});
|
|
151
|
-
describe("ends in intermediate state due to failure", () => {
|
|
152
|
-
it("From DetachedDefaultData without blobs with createAttachmentSummary failure", async () => {
|
|
153
|
-
const initial = {
|
|
154
|
-
state: AttachState.Detached,
|
|
155
|
-
};
|
|
156
|
-
let attachmentData;
|
|
157
|
-
const error = new Error("createAttachmentSummary failure");
|
|
158
|
-
try {
|
|
159
|
-
await runRetriableAttachProcess(createProxyWithFailDefault({
|
|
160
|
-
initialAttachmentData: initial,
|
|
161
|
-
detachedBlobStorage: undefined,
|
|
162
|
-
createAttachmentSummary: () => {
|
|
163
|
-
throw error;
|
|
164
|
-
},
|
|
165
|
-
}));
|
|
166
|
-
assert.fail("failure expected");
|
|
167
|
-
}
|
|
168
|
-
catch (e) {
|
|
169
|
-
assert.deepStrictEqual(e, error);
|
|
170
|
-
}
|
|
171
|
-
assert.deepStrictEqual(attachmentData, undefined, "attachment data shouldn't have been set");
|
|
172
|
-
});
|
|
173
|
-
it("From DetachedDefaultData without blobs getStorageService failure", async () => {
|
|
174
|
-
const initial = {
|
|
175
|
-
state: AttachState.Detached,
|
|
176
|
-
};
|
|
177
|
-
let attachmentData;
|
|
178
|
-
const error = new Error("getStorageService failure");
|
|
179
|
-
try {
|
|
180
|
-
await runRetriableAttachProcess(createProxyWithFailDefault({
|
|
181
|
-
initialAttachmentData: initial,
|
|
182
|
-
setAttachmentData: (data) => (attachmentData = data),
|
|
183
|
-
createAttachmentSummary: () => emptySummary,
|
|
184
|
-
detachedBlobStorage: undefined,
|
|
185
|
-
createOrGetStorageService: () => {
|
|
186
|
-
throw error;
|
|
187
|
-
},
|
|
188
|
-
}));
|
|
189
|
-
assert.fail("failure expected");
|
|
190
|
-
}
|
|
191
|
-
catch (e) {
|
|
192
|
-
assert.deepStrictEqual(e, error);
|
|
193
|
-
}
|
|
194
|
-
assert.deepStrictEqual(attachmentData, {
|
|
195
|
-
state: AttachState.Attaching,
|
|
196
|
-
blobs: "none",
|
|
197
|
-
summary: emptySummary,
|
|
198
|
-
}, "should have made it to attaching state");
|
|
199
|
-
});
|
|
200
|
-
it("From DetachedDefaultData with blobs with createBlob failure", async () => {
|
|
201
|
-
const initial = {
|
|
202
|
-
state: AttachState.Detached,
|
|
203
|
-
};
|
|
204
|
-
let attachmentData;
|
|
205
|
-
const blobCount = 10;
|
|
206
|
-
const detachedBlobStorage = createDetachStorage(blobCount);
|
|
207
|
-
const error = new Error("createBlob failure");
|
|
208
|
-
try {
|
|
209
|
-
await runRetriableAttachProcess({
|
|
210
|
-
initialAttachmentData: initial,
|
|
211
|
-
offlineLoadEnabled: false,
|
|
212
|
-
setAttachmentData: (data) => (attachmentData = data),
|
|
213
|
-
createAttachmentSummary: () => emptySummary,
|
|
214
|
-
createOrGetStorageService: async () => createProxyWithFailDefault({
|
|
215
|
-
createBlob: () => {
|
|
216
|
-
throw error;
|
|
217
|
-
},
|
|
218
|
-
}),
|
|
219
|
-
detachedBlobStorage,
|
|
220
|
-
});
|
|
221
|
-
assert.fail("failure expected");
|
|
222
|
-
}
|
|
223
|
-
catch (e) {
|
|
224
|
-
assert.deepStrictEqual(e, error);
|
|
225
|
-
}
|
|
226
|
-
assert.deepStrictEqual(attachmentData, {
|
|
227
|
-
state: AttachState.Detached,
|
|
228
|
-
blobs: "outstanding",
|
|
229
|
-
redirectTable: new Map(),
|
|
230
|
-
}, "should have made it to attaching state");
|
|
231
|
-
});
|
|
232
|
-
it("From DetachedDefaultData with blobs with createAttachmentSummary failure", async () => {
|
|
233
|
-
const initial = {
|
|
234
|
-
state: AttachState.Detached,
|
|
235
|
-
};
|
|
236
|
-
let attachmentData;
|
|
237
|
-
const blobCount = 10;
|
|
238
|
-
const detachedBlobStorage = createDetachStorage(blobCount);
|
|
239
|
-
const error = new Error("createAttachmentSummary failure");
|
|
240
|
-
try {
|
|
241
|
-
await runRetriableAttachProcess({
|
|
242
|
-
initialAttachmentData: initial,
|
|
243
|
-
offlineLoadEnabled: false,
|
|
244
|
-
setAttachmentData: (data) => (attachmentData = data),
|
|
245
|
-
createAttachmentSummary: () => {
|
|
246
|
-
throw error;
|
|
247
|
-
},
|
|
248
|
-
createOrGetStorageService: async () => createProxyWithFailDefault({
|
|
249
|
-
createBlob: async () => Promise.resolve({ id: uuid() }),
|
|
250
|
-
}),
|
|
251
|
-
detachedBlobStorage,
|
|
252
|
-
});
|
|
253
|
-
assert.fail("failure expected");
|
|
254
|
-
}
|
|
255
|
-
catch (e) {
|
|
256
|
-
assert.deepStrictEqual(e, error);
|
|
257
|
-
}
|
|
258
|
-
assert.deepStrictEqual(
|
|
259
|
-
// override redirectTable as it makes validation pain, and we have good coverage in other tests
|
|
260
|
-
{
|
|
261
|
-
...attachmentData,
|
|
262
|
-
redirectTable: attachmentData && "redirectTable" in attachmentData ? new Map() : undefined,
|
|
263
|
-
}, {
|
|
264
|
-
state: AttachState.Detached,
|
|
265
|
-
blobs: "outstanding",
|
|
266
|
-
redirectTable: new Map(),
|
|
267
|
-
}, "should have made it to attaching state");
|
|
268
|
-
});
|
|
269
|
-
it("From DetachedDefaultData with blobs with uploadSummaryWithContext failure", async () => {
|
|
270
|
-
const initial = {
|
|
271
|
-
state: AttachState.Detached,
|
|
272
|
-
};
|
|
273
|
-
let attachmentData;
|
|
274
|
-
const blobCount = 10;
|
|
275
|
-
const detachedBlobStorage = createDetachStorage(blobCount);
|
|
276
|
-
const error = new Error("uploadSummaryWithContext failure");
|
|
277
|
-
try {
|
|
278
|
-
await runRetriableAttachProcess({
|
|
279
|
-
initialAttachmentData: initial,
|
|
280
|
-
offlineLoadEnabled: false,
|
|
281
|
-
setAttachmentData: (data) => (attachmentData = data),
|
|
282
|
-
createAttachmentSummary: (redirectTable) => {
|
|
283
|
-
assert.strictEqual(redirectTable?.size, 10, "redirectTable?.size");
|
|
284
|
-
return emptySummary;
|
|
285
|
-
},
|
|
286
|
-
createOrGetStorageService: async () => ({
|
|
287
|
-
createBlob: async () => Promise.resolve({ id: uuid() }),
|
|
288
|
-
uploadSummaryWithContext: () => {
|
|
289
|
-
throw error;
|
|
290
|
-
},
|
|
291
|
-
}),
|
|
292
|
-
detachedBlobStorage,
|
|
293
|
-
});
|
|
294
|
-
assert.fail("failure expected");
|
|
295
|
-
}
|
|
296
|
-
catch (e) {
|
|
297
|
-
assert.deepStrictEqual(e, error);
|
|
298
|
-
}
|
|
299
|
-
assert.deepStrictEqual(attachmentData, {
|
|
300
|
-
state: AttachState.Attaching,
|
|
301
|
-
blobs: "done",
|
|
302
|
-
summary: emptySummary,
|
|
303
|
-
}, "should have made it to attaching state");
|
|
304
|
-
});
|
|
305
|
-
});
|
|
306
|
-
describe("from intermediate state", () => {
|
|
307
|
-
it("From DetachedDataWithOutstandingBlobs", async () => {
|
|
308
|
-
const initial = {
|
|
309
|
-
state: AttachState.Detached,
|
|
310
|
-
blobs: "outstanding",
|
|
311
|
-
redirectTable: new Map(),
|
|
312
|
-
};
|
|
313
|
-
let attachmentData;
|
|
314
|
-
const blobCount = 10;
|
|
315
|
-
const detachedBlobStorage = createDetachStorage(blobCount);
|
|
316
|
-
const storageAdapter = addCallCounts({
|
|
317
|
-
createBlob: async () => Promise.resolve({ id: uuid() }),
|
|
318
|
-
uploadSummaryWithContext: async () => Promise.resolve(uuid()),
|
|
319
|
-
});
|
|
320
|
-
await runRetriableAttachProcess({
|
|
321
|
-
initialAttachmentData: initial,
|
|
322
|
-
offlineLoadEnabled: false,
|
|
323
|
-
setAttachmentData: (data) => (attachmentData = data),
|
|
324
|
-
createAttachmentSummary: (redirectTable) => {
|
|
325
|
-
assert.strictEqual(redirectTable?.size, blobCount, "redirectTable?.size");
|
|
326
|
-
return emptySummary;
|
|
327
|
-
},
|
|
328
|
-
createOrGetStorageService: async () => storageAdapter,
|
|
329
|
-
detachedBlobStorage,
|
|
330
|
-
});
|
|
331
|
-
// expect every blob to read, and uploaded
|
|
332
|
-
assert.strictEqual(initial.redirectTable.size, blobCount, "initial.redirectTable.size");
|
|
333
|
-
assert.strictEqual(detachedBlobStorage.calls.readBlob, blobCount, "detachedBlobStorage.calls.readBlob");
|
|
334
|
-
assert.strictEqual(storageAdapter.calls.createBlob, blobCount, "storageAdapter.calls.createBlob");
|
|
335
|
-
// after blobs are uploaded summary should be
|
|
336
|
-
assert.strictEqual(storageAdapter.calls.uploadSummaryWithContext, 1, "storageAdapter.calls.uploadSummaryWithContext");
|
|
337
|
-
assert.strictEqual(attachmentData?.state, AttachState.Attached, "should be attached");
|
|
338
|
-
});
|
|
339
|
-
it("From AttachingDataWithBlobs", async () => {
|
|
340
|
-
const initial = {
|
|
341
|
-
state: AttachState.Attaching,
|
|
342
|
-
blobs: "done",
|
|
343
|
-
summary: emptySummary,
|
|
344
|
-
};
|
|
345
|
-
let attachmentData;
|
|
346
|
-
const snapshot = await runRetriableAttachProcess(createProxyWithFailDefault({
|
|
347
|
-
initialAttachmentData: initial,
|
|
348
|
-
offlineLoadEnabled: true,
|
|
349
|
-
setAttachmentData: (data) => (attachmentData = data),
|
|
350
|
-
createOrGetStorageService: async () =>
|
|
351
|
-
// only the summary should be left to upload
|
|
352
|
-
createProxyWithFailDefault({
|
|
353
|
-
uploadSummaryWithContext: async () => Promise.resolve(uuid()),
|
|
354
|
-
}),
|
|
355
|
-
}));
|
|
356
|
-
assert.strictEqual(attachmentData?.state, AttachState.Attached, "should be attached");
|
|
357
|
-
assert.notStrictEqual(snapshot, undefined, "should have snapshot");
|
|
358
|
-
});
|
|
359
|
-
it("From AttachingDataWithoutBlobs", async () => {
|
|
360
|
-
const initial = {
|
|
361
|
-
state: AttachState.Attaching,
|
|
362
|
-
blobs: "none",
|
|
363
|
-
summary: emptySummary,
|
|
364
|
-
};
|
|
365
|
-
let attachmentData;
|
|
366
|
-
const snapshot = await runRetriableAttachProcess(createProxyWithFailDefault({
|
|
367
|
-
initialAttachmentData: initial,
|
|
368
|
-
offlineLoadEnabled: true,
|
|
369
|
-
setAttachmentData: (data) => (attachmentData = data),
|
|
370
|
-
createOrGetStorageService: async (summary) => {
|
|
371
|
-
assert.notStrictEqual(summary, undefined, "data.summary");
|
|
372
|
-
return createProxyWithFailDefault();
|
|
373
|
-
},
|
|
374
|
-
}));
|
|
375
|
-
assert.strictEqual(attachmentData?.state, AttachState.Attached, "should be attached");
|
|
376
|
-
assert.notStrictEqual(snapshot, undefined, "should have snapshot");
|
|
377
|
-
});
|
|
378
|
-
});
|
|
379
|
-
});
|
|
380
|
-
//# sourceMappingURL=attachment.spec.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"attachment.spec.js","sourceRoot":"","sources":["../../src/test/attachment.spec.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 { strict as assert } from \"assert\";\nimport { AttachState } from \"@fluidframework/container-definitions\";\nimport { v4 as uuid } from \"uuid\";\nimport { SummaryType } from \"@fluidframework/protocol-definitions\";\nimport { stringToBuffer } from \"@fluid-internal/client-utils\";\nimport { IDocumentStorageService } from \"@fluidframework/driver-definitions\";\nimport {\n\tAttachProcessProps,\n\tAttachingDataWithBlobs,\n\tDetachedDataWithOutstandingBlobs,\n\trunRetriableAttachProcess,\n\tDetachedDefaultData,\n\tAttachmentData,\n\tAttachingDataWithoutBlobs,\n} from \"../attachment.js\";\nimport { combineAppAndProtocolSummary } from \"../utils.js\";\n\nconst emptySummary = combineAppAndProtocolSummary(\n\t{ tree: {}, type: SummaryType.Tree },\n\t{ tree: {}, type: SummaryType.Tree },\n);\n\ntype ObjectWithCallCounts<T extends Record<string, any>> = T &\n\tRecord<\"calls\", Record<keyof T, number>>;\n\nconst addCallCounts = <T extends Record<string, any>>(obj: T): ObjectWithCallCounts<T> => {\n\tconst calls = Object.keys(obj).reduce((pv, cv) => {\n\t\tpv[cv] = 0;\n\t\treturn pv;\n\t}, {}) as Record<keyof T, number>;\n\n\treturn new Proxy<ObjectWithCallCounts<T>>(obj as ObjectWithCallCounts<T>, {\n\t\tget: (t, p, r): any => {\n\t\t\tif (p === \"calls\") {\n\t\t\t\treturn calls;\n\t\t\t} else {\n\t\t\t\tcalls[p as keyof T]++;\n\t\t\t\treturn Reflect.get(t, p, r);\n\t\t\t}\n\t\t},\n\t});\n};\n\nconst createDetachStorage = (\n\tblobCount: number,\n): ObjectWithCallCounts<Exclude<AttachProcessProps[\"detachedBlobStorage\"], undefined>> => {\n\tconst blobs = new Map<string, ArrayBufferLike>(\n\t\tArray.from({ length: blobCount }).map((_, i) => [\n\t\t\ti.toString(),\n\t\t\tstringToBuffer(`${i}-content`, \"utf-8\"),\n\t\t]),\n\t);\n\n\treturn addCallCounts({\n\t\tget size() {\n\t\t\treturn blobs.size;\n\t\t},\n\t\tgetBlobIds() {\n\t\t\treturn [...blobs.keys()];\n\t\t},\n\t\tasync readBlob(id) {\n\t\t\tconst content = blobs.get(id);\n\t\t\tassert(content !== undefined, `no blob content for [${id}]`);\n\t\t\treturn content;\n\t\t},\n\t});\n};\n\nconst createProxyWithFailDefault = <T extends Record<string, any> | undefined>(\n\tpartial: Partial<T> = {},\n): T => {\n\treturn new Proxy(partial, {\n\t\tget: (t, p, r): any => {\n\t\t\tif (p in t) {\n\t\t\t\treturn Reflect.get(t, p, r);\n\t\t\t}\n\n\t\t\treturn new Proxy(\n\t\t\t\t{},\n\t\t\t\t{\n\t\t\t\t\tget: () => assert.fail(`unexpected call too ${p.toString()}`),\n\t\t\t\t},\n\t\t\t);\n\t\t},\n\t}) as T;\n};\n\ndescribe(\"runRetriableAttachProcess\", () => {\n\tdescribe(\"end to end process\", () => {\n\t\tit(\"From DetachedDefaultData without blobs or offline\", async () => {\n\t\t\tconst initial: DetachedDefaultData = {\n\t\t\t\tstate: AttachState.Detached,\n\t\t\t};\n\t\t\tlet attachmentData: AttachmentData | undefined;\n\t\t\tawait runRetriableAttachProcess({\n\t\t\t\tinitialAttachmentData: initial,\n\t\t\t\tofflineLoadEnabled: false,\n\t\t\t\tsetAttachmentData: (data) => (attachmentData = data),\n\t\t\t\tcreateAttachmentSummary: (redirectTable) => {\n\t\t\t\t\tassert.strictEqual(redirectTable, undefined, \"redirectTable\");\n\t\t\t\t\treturn emptySummary;\n\t\t\t\t},\n\t\t\t\tcreateOrGetStorageService: async () =>\n\t\t\t\t\tcreateProxyWithFailDefault<IDocumentStorageService>(),\n\t\t\t});\n\n\t\t\tassert.strictEqual(attachmentData?.state, AttachState.Attached, \"should be attached\");\n\t\t});\n\n\t\tit(\"From DetachedDefaultData with offline and without blobs\", async () => {\n\t\t\tconst initial: DetachedDefaultData = {\n\t\t\t\tstate: AttachState.Detached,\n\t\t\t};\n\t\t\tlet attachmentData: AttachmentData | undefined;\n\t\t\tconst snapshot = await runRetriableAttachProcess({\n\t\t\t\tinitialAttachmentData: initial,\n\t\t\t\tofflineLoadEnabled: true,\n\t\t\t\tsetAttachmentData: (data) => (attachmentData = data),\n\t\t\t\tcreateAttachmentSummary: (redirectTable) => {\n\t\t\t\t\tassert.strictEqual(redirectTable, undefined, \"redirectTable\");\n\t\t\t\t\treturn emptySummary;\n\t\t\t\t},\n\t\t\t\tcreateOrGetStorageService: async () => ({\n\t\t\t\t\tcreateBlob: async () => assert.fail(\"no blobs should be created\"),\n\t\t\t\t\tuploadSummaryWithContext: async () =>\n\t\t\t\t\t\tassert.fail(\"no summary should be uploaded outside of create\"),\n\t\t\t\t}),\n\t\t\t});\n\n\t\t\tassert.strictEqual(attachmentData?.state, AttachState.Attached, \"should be attached\");\n\t\t\tassert.notStrictEqual(snapshot, undefined, \"should have snapshot\");\n\t\t});\n\n\t\tit(\"From DetachedDefaultData with blobs and without offline\", async () => {\n\t\t\tconst initial: DetachedDefaultData = {\n\t\t\t\tstate: AttachState.Detached,\n\t\t\t};\n\t\t\tlet attachmentData: AttachmentData | undefined;\n\t\t\tconst blobCount = 10;\n\t\t\tconst detachedBlobStorage = createDetachStorage(blobCount);\n\t\t\tconst storageAdapter = addCallCounts({\n\t\t\t\tcreateBlob: async () => Promise.resolve({ id: uuid() }),\n\t\t\t\tuploadSummaryWithContext: async () => Promise.resolve(uuid()),\n\t\t\t});\n\t\t\tawait runRetriableAttachProcess({\n\t\t\t\tinitialAttachmentData: initial,\n\t\t\t\tofflineLoadEnabled: false,\n\t\t\t\tsetAttachmentData: (data) => (attachmentData = data),\n\t\t\t\tcreateAttachmentSummary: (redirectTable) => {\n\t\t\t\t\tassert.strictEqual(redirectTable?.size, blobCount, \"redirectTable?.size\");\n\t\t\t\t\treturn emptySummary;\n\t\t\t\t},\n\t\t\t\tcreateOrGetStorageService: async () => storageAdapter,\n\t\t\t\tdetachedBlobStorage,\n\t\t\t});\n\n\t\t\t// expect every blob to read, and uploaded\n\t\t\tassert.strictEqual(\n\t\t\t\tdetachedBlobStorage.calls.readBlob,\n\t\t\t\tblobCount,\n\t\t\t\t\"detachedBlobStorage.calls.readBlob\",\n\t\t\t);\n\t\t\tassert.strictEqual(\n\t\t\t\tstorageAdapter.calls.createBlob,\n\t\t\t\tblobCount,\n\t\t\t\t\"storageAdapter.calls.createBlob\",\n\t\t\t);\n\n\t\t\t// after blobs are uploaded summary should be\n\t\t\tassert.strictEqual(\n\t\t\t\tstorageAdapter.calls.uploadSummaryWithContext,\n\t\t\t\t1,\n\t\t\t\t\"storageAdapter.calls.uploadSummaryWithContext\",\n\t\t\t);\n\n\t\t\tassert.strictEqual(attachmentData?.state, AttachState.Attached, \"should be attached\");\n\t\t});\n\n\t\tit(\"From DetachedDefaultData with zero blobs and without offline\", async () => {\n\t\t\tconst initial: DetachedDefaultData = {\n\t\t\t\tstate: AttachState.Detached,\n\t\t\t};\n\t\t\tlet attachmentData: AttachmentData | undefined;\n\t\t\tawait runRetriableAttachProcess({\n\t\t\t\tinitialAttachmentData: initial,\n\t\t\t\tofflineLoadEnabled: false,\n\t\t\t\tsetAttachmentData: (data) => (attachmentData = data),\n\t\t\t\tcreateAttachmentSummary: (redirectTable) => {\n\t\t\t\t\tassert.strictEqual(redirectTable, undefined, \"redirectTable\");\n\t\t\t\t\treturn emptySummary;\n\t\t\t\t},\n\t\t\t\tcreateOrGetStorageService: async () => createProxyWithFailDefault(),\n\t\t\t\t// we have blobs storage, but it is empty,\n\t\t\t\t// so it should be treat like there are no blobs\n\t\t\t\tdetachedBlobStorage: createProxyWithFailDefault<\n\t\t\t\t\tAttachProcessProps[\"detachedBlobStorage\"]\n\t\t\t\t>({ size: 0 }),\n\t\t\t});\n\n\t\t\tassert.strictEqual(attachmentData?.state, AttachState.Attached, \"should be attached\");\n\t\t});\n\t});\n\n\tdescribe(\"ends in intermediate state due to failure\", () => {\n\t\tit(\"From DetachedDefaultData without blobs with createAttachmentSummary failure\", async () => {\n\t\t\tconst initial: DetachedDefaultData = {\n\t\t\t\tstate: AttachState.Detached,\n\t\t\t};\n\t\t\tlet attachmentData: AttachmentData | undefined;\n\t\t\tconst error = new Error(\"createAttachmentSummary failure\");\n\t\t\ttry {\n\t\t\t\tawait runRetriableAttachProcess(\n\t\t\t\t\tcreateProxyWithFailDefault<AttachProcessProps>({\n\t\t\t\t\t\tinitialAttachmentData: initial,\n\t\t\t\t\t\tdetachedBlobStorage: undefined,\n\t\t\t\t\t\tcreateAttachmentSummary: () => {\n\t\t\t\t\t\t\tthrow error;\n\t\t\t\t\t\t},\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t\tassert.fail(\"failure expected\");\n\t\t\t} catch (e) {\n\t\t\t\tassert.deepStrictEqual(e, error);\n\t\t\t}\n\n\t\t\tassert.deepStrictEqual(\n\t\t\t\tattachmentData,\n\t\t\t\tundefined,\n\t\t\t\t\"attachment data shouldn't have been set\",\n\t\t\t);\n\t\t});\n\n\t\tit(\"From DetachedDefaultData without blobs getStorageService failure\", async () => {\n\t\t\tconst initial: DetachedDefaultData = {\n\t\t\t\tstate: AttachState.Detached,\n\t\t\t};\n\t\t\tlet attachmentData: AttachmentData | undefined;\n\t\t\tconst error = new Error(\"getStorageService failure\");\n\t\t\ttry {\n\t\t\t\tawait runRetriableAttachProcess(\n\t\t\t\t\tcreateProxyWithFailDefault<AttachProcessProps>({\n\t\t\t\t\t\tinitialAttachmentData: initial,\n\t\t\t\t\t\tsetAttachmentData: (data) => (attachmentData = data),\n\t\t\t\t\t\tcreateAttachmentSummary: () => emptySummary,\n\t\t\t\t\t\tdetachedBlobStorage: undefined,\n\t\t\t\t\t\tcreateOrGetStorageService: () => {\n\t\t\t\t\t\t\tthrow error;\n\t\t\t\t\t\t},\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t\tassert.fail(\"failure expected\");\n\t\t\t} catch (e) {\n\t\t\t\tassert.deepStrictEqual(e, error);\n\t\t\t}\n\n\t\t\tassert.deepStrictEqual<AttachingDataWithoutBlobs>(\n\t\t\t\tattachmentData,\n\t\t\t\t{\n\t\t\t\t\tstate: AttachState.Attaching,\n\t\t\t\t\tblobs: \"none\",\n\t\t\t\t\tsummary: emptySummary,\n\t\t\t\t},\n\t\t\t\t\"should have made it to attaching state\",\n\t\t\t);\n\t\t});\n\n\t\tit(\"From DetachedDefaultData with blobs with createBlob failure\", async () => {\n\t\t\tconst initial: DetachedDefaultData = {\n\t\t\t\tstate: AttachState.Detached,\n\t\t\t};\n\t\t\tlet attachmentData: AttachmentData | undefined;\n\t\t\tconst blobCount = 10;\n\t\t\tconst detachedBlobStorage = createDetachStorage(blobCount);\n\t\t\tconst error = new Error(\"createBlob failure\");\n\t\t\ttry {\n\t\t\t\tawait runRetriableAttachProcess({\n\t\t\t\t\tinitialAttachmentData: initial,\n\t\t\t\t\tofflineLoadEnabled: false,\n\t\t\t\t\tsetAttachmentData: (data) => (attachmentData = data),\n\t\t\t\t\tcreateAttachmentSummary: () => emptySummary,\n\t\t\t\t\tcreateOrGetStorageService: async () =>\n\t\t\t\t\t\tcreateProxyWithFailDefault<IDocumentStorageService>({\n\t\t\t\t\t\t\tcreateBlob: () => {\n\t\t\t\t\t\t\t\tthrow error;\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t}),\n\t\t\t\t\tdetachedBlobStorage,\n\t\t\t\t});\n\t\t\t\tassert.fail(\"failure expected\");\n\t\t\t} catch (e) {\n\t\t\t\tassert.deepStrictEqual(e, error);\n\t\t\t}\n\n\t\t\tassert.deepStrictEqual<DetachedDataWithOutstandingBlobs>(\n\t\t\t\tattachmentData,\n\t\t\t\t{\n\t\t\t\t\tstate: AttachState.Detached,\n\t\t\t\t\tblobs: \"outstanding\",\n\t\t\t\t\tredirectTable: new Map(),\n\t\t\t\t},\n\t\t\t\t\"should have made it to attaching state\",\n\t\t\t);\n\t\t});\n\n\t\tit(\"From DetachedDefaultData with blobs with createAttachmentSummary failure\", async () => {\n\t\t\tconst initial: DetachedDefaultData = {\n\t\t\t\tstate: AttachState.Detached,\n\t\t\t};\n\t\t\tlet attachmentData: AttachmentData | undefined;\n\t\t\tconst blobCount = 10;\n\t\t\tconst detachedBlobStorage = createDetachStorage(blobCount);\n\t\t\tconst error = new Error(\"createAttachmentSummary failure\");\n\t\t\ttry {\n\t\t\t\tawait runRetriableAttachProcess({\n\t\t\t\t\tinitialAttachmentData: initial,\n\t\t\t\t\tofflineLoadEnabled: false,\n\t\t\t\t\tsetAttachmentData: (data) => (attachmentData = data),\n\t\t\t\t\tcreateAttachmentSummary: () => {\n\t\t\t\t\t\tthrow error;\n\t\t\t\t\t},\n\t\t\t\t\tcreateOrGetStorageService: async () =>\n\t\t\t\t\t\tcreateProxyWithFailDefault<IDocumentStorageService>({\n\t\t\t\t\t\t\tcreateBlob: async () => Promise.resolve({ id: uuid() }),\n\t\t\t\t\t\t}),\n\t\t\t\t\tdetachedBlobStorage,\n\t\t\t\t});\n\t\t\t\tassert.fail(\"failure expected\");\n\t\t\t} catch (e) {\n\t\t\t\tassert.deepStrictEqual(e, error);\n\t\t\t}\n\n\t\t\tassert.deepStrictEqual<DetachedDataWithOutstandingBlobs>(\n\t\t\t\t// override redirectTable as it makes validation pain, and we have good coverage in other tests\n\t\t\t\t{\n\t\t\t\t\t...attachmentData,\n\t\t\t\t\tredirectTable:\n\t\t\t\t\t\tattachmentData && \"redirectTable\" in attachmentData ? new Map() : undefined,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tstate: AttachState.Detached,\n\t\t\t\t\tblobs: \"outstanding\",\n\t\t\t\t\tredirectTable: new Map(),\n\t\t\t\t},\n\t\t\t\t\"should have made it to attaching state\",\n\t\t\t);\n\t\t});\n\n\t\tit(\"From DetachedDefaultData with blobs with uploadSummaryWithContext failure\", async () => {\n\t\t\tconst initial: DetachedDefaultData = {\n\t\t\t\tstate: AttachState.Detached,\n\t\t\t};\n\t\t\tlet attachmentData: AttachmentData | undefined;\n\t\t\tconst blobCount = 10;\n\t\t\tconst detachedBlobStorage = createDetachStorage(blobCount);\n\t\t\tconst error = new Error(\"uploadSummaryWithContext failure\");\n\t\t\ttry {\n\t\t\t\tawait runRetriableAttachProcess({\n\t\t\t\t\tinitialAttachmentData: initial,\n\t\t\t\t\tofflineLoadEnabled: false,\n\t\t\t\t\tsetAttachmentData: (data) => (attachmentData = data),\n\t\t\t\t\tcreateAttachmentSummary: (redirectTable) => {\n\t\t\t\t\t\tassert.strictEqual(redirectTable?.size, 10, \"redirectTable?.size\");\n\t\t\t\t\t\treturn emptySummary;\n\t\t\t\t\t},\n\t\t\t\t\tcreateOrGetStorageService: async () => ({\n\t\t\t\t\t\tcreateBlob: async () => Promise.resolve({ id: uuid() }),\n\t\t\t\t\t\tuploadSummaryWithContext: () => {\n\t\t\t\t\t\t\tthrow error;\n\t\t\t\t\t\t},\n\t\t\t\t\t}),\n\t\t\t\t\tdetachedBlobStorage,\n\t\t\t\t});\n\t\t\t\tassert.fail(\"failure expected\");\n\t\t\t} catch (e) {\n\t\t\t\tassert.deepStrictEqual(e, error);\n\t\t\t}\n\n\t\t\tassert.deepStrictEqual<AttachingDataWithBlobs>(\n\t\t\t\tattachmentData,\n\t\t\t\t{\n\t\t\t\t\tstate: AttachState.Attaching,\n\t\t\t\t\tblobs: \"done\",\n\t\t\t\t\tsummary: emptySummary,\n\t\t\t\t},\n\t\t\t\t\"should have made it to attaching state\",\n\t\t\t);\n\t\t});\n\t});\n\n\tdescribe(\"from intermediate state\", () => {\n\t\tit(\"From DetachedDataWithOutstandingBlobs\", async () => {\n\t\t\tconst initial: DetachedDataWithOutstandingBlobs = {\n\t\t\t\tstate: AttachState.Detached,\n\t\t\t\tblobs: \"outstanding\",\n\t\t\t\tredirectTable: new Map(),\n\t\t\t};\n\t\t\tlet attachmentData: AttachmentData | undefined;\n\t\t\tconst blobCount = 10;\n\t\t\tconst detachedBlobStorage = createDetachStorage(blobCount);\n\t\t\tconst storageAdapter = addCallCounts({\n\t\t\t\tcreateBlob: async () => Promise.resolve({ id: uuid() }),\n\t\t\t\tuploadSummaryWithContext: async () => Promise.resolve(uuid()),\n\t\t\t});\n\t\t\tawait runRetriableAttachProcess({\n\t\t\t\tinitialAttachmentData: initial,\n\t\t\t\tofflineLoadEnabled: false,\n\t\t\t\tsetAttachmentData: (data) => (attachmentData = data),\n\t\t\t\tcreateAttachmentSummary: (redirectTable) => {\n\t\t\t\t\tassert.strictEqual(redirectTable?.size, blobCount, \"redirectTable?.size\");\n\t\t\t\t\treturn emptySummary;\n\t\t\t\t},\n\t\t\t\tcreateOrGetStorageService: async () => storageAdapter,\n\t\t\t\tdetachedBlobStorage,\n\t\t\t});\n\n\t\t\t// expect every blob to read, and uploaded\n\t\t\tassert.strictEqual(initial.redirectTable.size, blobCount, \"initial.redirectTable.size\");\n\n\t\t\tassert.strictEqual(\n\t\t\t\tdetachedBlobStorage.calls.readBlob,\n\t\t\t\tblobCount,\n\t\t\t\t\"detachedBlobStorage.calls.readBlob\",\n\t\t\t);\n\t\t\tassert.strictEqual(\n\t\t\t\tstorageAdapter.calls.createBlob,\n\t\t\t\tblobCount,\n\t\t\t\t\"storageAdapter.calls.createBlob\",\n\t\t\t);\n\n\t\t\t// after blobs are uploaded summary should be\n\t\t\tassert.strictEqual(\n\t\t\t\tstorageAdapter.calls.uploadSummaryWithContext,\n\t\t\t\t1,\n\t\t\t\t\"storageAdapter.calls.uploadSummaryWithContext\",\n\t\t\t);\n\n\t\t\tassert.strictEqual(attachmentData?.state, AttachState.Attached, \"should be attached\");\n\t\t});\n\n\t\tit(\"From AttachingDataWithBlobs\", async () => {\n\t\t\tconst initial: AttachingDataWithBlobs = {\n\t\t\t\tstate: AttachState.Attaching,\n\t\t\t\tblobs: \"done\",\n\t\t\t\tsummary: emptySummary,\n\t\t\t};\n\t\t\tlet attachmentData: AttachmentData | undefined;\n\t\t\tconst snapshot = await runRetriableAttachProcess(\n\t\t\t\tcreateProxyWithFailDefault<AttachProcessProps>({\n\t\t\t\t\tinitialAttachmentData: initial,\n\t\t\t\t\tofflineLoadEnabled: true,\n\t\t\t\t\tsetAttachmentData: (data) => (attachmentData = data),\n\t\t\t\t\tcreateOrGetStorageService: async () =>\n\t\t\t\t\t\t// only the summary should be left to upload\n\t\t\t\t\t\tcreateProxyWithFailDefault<IDocumentStorageService>({\n\t\t\t\t\t\t\tuploadSummaryWithContext: async () => Promise.resolve(uuid()),\n\t\t\t\t\t\t}),\n\t\t\t\t}),\n\t\t\t);\n\n\t\t\tassert.strictEqual(attachmentData?.state, AttachState.Attached, \"should be attached\");\n\t\t\tassert.notStrictEqual(snapshot, undefined, \"should have snapshot\");\n\t\t});\n\n\t\tit(\"From AttachingDataWithoutBlobs\", async () => {\n\t\t\tconst initial: AttachingDataWithoutBlobs = {\n\t\t\t\tstate: AttachState.Attaching,\n\t\t\t\tblobs: \"none\",\n\t\t\t\tsummary: emptySummary,\n\t\t\t};\n\t\t\tlet attachmentData: AttachmentData | undefined;\n\t\t\tconst snapshot = await runRetriableAttachProcess(\n\t\t\t\tcreateProxyWithFailDefault<AttachProcessProps>({\n\t\t\t\t\tinitialAttachmentData: initial,\n\t\t\t\t\tofflineLoadEnabled: true,\n\t\t\t\t\tsetAttachmentData: (data) => (attachmentData = data),\n\t\t\t\t\tcreateOrGetStorageService: async (summary) => {\n\t\t\t\t\t\tassert.notStrictEqual(summary, undefined, \"data.summary\");\n\t\t\t\t\t\treturn createProxyWithFailDefault();\n\t\t\t\t\t},\n\t\t\t\t}),\n\t\t\t);\n\n\t\t\tassert.strictEqual(attachmentData?.state, AttachState.Attached, \"should be attached\");\n\t\t\tassert.notStrictEqual(snapshot, undefined, \"should have snapshot\");\n\t\t});\n\t});\n});\n"]}
|
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
/*!
|
|
2
|
-
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
|
-
* Licensed under the MIT License.
|
|
4
|
-
*/
|
|
5
|
-
import { strict as assert } from "assert";
|
|
6
|
-
import { TypedEventEmitter } from "@fluid-internal/client-utils";
|
|
7
|
-
import { CatchUpMonitor } from "../catchUpMonitor.js";
|
|
8
|
-
class MockDeltaManagerForCatchingUp extends TypedEventEmitter {
|
|
9
|
-
constructor(lastSequenceNumber = 5, lastKnownSeqNumber = 10) {
|
|
10
|
-
super();
|
|
11
|
-
this.lastSequenceNumber = lastSequenceNumber;
|
|
12
|
-
this.lastKnownSeqNumber = lastKnownSeqNumber;
|
|
13
|
-
}
|
|
14
|
-
/** Simulate processing op with the given sequence number, to trigger CatchUpMonitor */
|
|
15
|
-
emitOpWithSequenceNumber(sequenceNumber) {
|
|
16
|
-
this.emit("op", { sequenceNumber });
|
|
17
|
-
}
|
|
18
|
-
/** Trigger the CatchUpMonitor by emitting op with the target sequence number */
|
|
19
|
-
emitOpToCatchUp() {
|
|
20
|
-
this.emitOpWithSequenceNumber(this.lastKnownSeqNumber);
|
|
21
|
-
}
|
|
22
|
-
static create(sequenceNumbers = {}) {
|
|
23
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
|
24
|
-
return new MockDeltaManagerForCatchingUp(sequenceNumbers.lastSequenceNumber, sequenceNumbers.lastKnownSeqNumber);
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
describe("CatchUpMonitor", () => {
|
|
28
|
-
let monitor;
|
|
29
|
-
afterEach(() => {
|
|
30
|
-
monitor?.dispose();
|
|
31
|
-
});
|
|
32
|
-
it("constructor validates DeltaManager sequence number coherency", async () => {
|
|
33
|
-
const mockDeltaManager = MockDeltaManagerForCatchingUp.create({
|
|
34
|
-
lastSequenceNumber: 20,
|
|
35
|
-
lastKnownSeqNumber: 15, // Should be impossible in real world
|
|
36
|
-
});
|
|
37
|
-
assert.throws(() => new CatchUpMonitor(mockDeltaManager, () => { }), "Expect assert when DeltaManager in invalid state");
|
|
38
|
-
});
|
|
39
|
-
it("Emits caughtUp event when caught up to the point it was created", () => {
|
|
40
|
-
const mockDeltaManager = MockDeltaManagerForCatchingUp.create({
|
|
41
|
-
lastSequenceNumber: 10,
|
|
42
|
-
lastKnownSeqNumber: 15,
|
|
43
|
-
});
|
|
44
|
-
let caughtUp = false;
|
|
45
|
-
mockDeltaManager.lastKnownSeqNumber = 20;
|
|
46
|
-
monitor = new CatchUpMonitor(mockDeltaManager, () => {
|
|
47
|
-
caughtUp = true;
|
|
48
|
-
});
|
|
49
|
-
mockDeltaManager.lastKnownSeqNumber = 25; // Shouldn't change anything about the monitor
|
|
50
|
-
mockDeltaManager.emitOpWithSequenceNumber(19); // Less than 20
|
|
51
|
-
assert(!caughtUp, "Shouldn't be considered caught up yet");
|
|
52
|
-
mockDeltaManager.emitOpWithSequenceNumber(21); // Greater than 20
|
|
53
|
-
assert(caughtUp, "Should be considered caught up now");
|
|
54
|
-
});
|
|
55
|
-
it("Emits caught up immediately if last known/processed sequence numbers match", () => {
|
|
56
|
-
const mockDeltaManager = MockDeltaManagerForCatchingUp.create({
|
|
57
|
-
lastSequenceNumber: 10,
|
|
58
|
-
lastKnownSeqNumber: 10,
|
|
59
|
-
});
|
|
60
|
-
let caughtUp = false;
|
|
61
|
-
monitor = new CatchUpMonitor(mockDeltaManager, () => {
|
|
62
|
-
caughtUp = true;
|
|
63
|
-
});
|
|
64
|
-
assert(caughtUp, "caughtUp should have fired immediately");
|
|
65
|
-
});
|
|
66
|
-
it("Only emits caughtUp once", () => {
|
|
67
|
-
const mockDeltaManager = MockDeltaManagerForCatchingUp.create({
|
|
68
|
-
lastSequenceNumber: 10,
|
|
69
|
-
lastKnownSeqNumber: 15,
|
|
70
|
-
});
|
|
71
|
-
let caughtUpCount = 0;
|
|
72
|
-
monitor = new CatchUpMonitor(mockDeltaManager, () => {
|
|
73
|
-
++caughtUpCount;
|
|
74
|
-
});
|
|
75
|
-
mockDeltaManager.emitOpWithSequenceNumber(15);
|
|
76
|
-
assert.equal(caughtUpCount, 1, "caughtUp should have fired once");
|
|
77
|
-
mockDeltaManager.emitOpWithSequenceNumber(16);
|
|
78
|
-
assert.equal(caughtUpCount, 1, "caughtUp should have fired only once");
|
|
79
|
-
});
|
|
80
|
-
it("Dispose removes all listeners", () => {
|
|
81
|
-
const mockDeltaManager = MockDeltaManagerForCatchingUp.create();
|
|
82
|
-
monitor = new CatchUpMonitor(mockDeltaManager, () => { });
|
|
83
|
-
monitor.dispose();
|
|
84
|
-
assert(monitor.disposed, "dispose() should set disposed");
|
|
85
|
-
assert.equal(mockDeltaManager.listenerCount("op"), 0, "CatchUpMonitor.dispose should remove listener on DeltaManager");
|
|
86
|
-
});
|
|
87
|
-
});
|
|
88
|
-
//# sourceMappingURL=catchUpMonitor.spec.js.map
|