@fluidframework/container-loader 2.1.0-276985 → 2.1.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 +4 -0
- package/README.md +132 -30
- package/api-extractor/api-extractor.current.json +5 -0
- package/api-extractor/api-extractor.legacy.json +1 -1
- package/api-extractor.json +1 -1
- package/api-report/container-loader.legacy.public.api.md +17 -0
- package/dist/connectionManager.d.ts.map +1 -1
- package/dist/connectionManager.js +9 -6
- package/dist/connectionManager.js.map +1 -1
- package/dist/container.d.ts.map +1 -1
- package/dist/container.js +28 -6
- package/dist/container.js.map +1 -1
- package/dist/containerStorageAdapter.d.ts +1 -1
- package/dist/containerStorageAdapter.d.ts.map +1 -1
- package/dist/containerStorageAdapter.js +14 -4
- package/dist/containerStorageAdapter.js.map +1 -1
- package/dist/contracts.d.ts.map +1 -1
- package/dist/contracts.js +4 -12
- package/dist/contracts.js.map +1 -1
- package/dist/deltaManager.d.ts.map +1 -1
- package/dist/deltaManager.js +18 -3
- package/dist/deltaManager.js.map +1 -1
- package/dist/legacy.d.ts +1 -1
- package/dist/packageVersion.d.ts +1 -1
- package/dist/packageVersion.d.ts.map +1 -1
- package/dist/packageVersion.js +1 -1
- package/dist/packageVersion.js.map +1 -1
- package/dist/public.d.ts +1 -1
- package/dist/serializedStateManager.d.ts.map +1 -1
- package/dist/serializedStateManager.js +18 -5
- package/dist/serializedStateManager.js.map +1 -1
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +11 -2
- package/dist/utils.js.map +1 -1
- package/internal.d.ts +1 -1
- package/legacy.d.ts +1 -1
- package/lib/connectionManager.d.ts.map +1 -1
- package/lib/connectionManager.js +9 -6
- package/lib/connectionManager.js.map +1 -1
- package/lib/container.d.ts.map +1 -1
- package/lib/container.js +28 -6
- package/lib/container.js.map +1 -1
- package/lib/containerStorageAdapter.d.ts +1 -1
- package/lib/containerStorageAdapter.d.ts.map +1 -1
- package/lib/containerStorageAdapter.js +16 -6
- package/lib/containerStorageAdapter.js.map +1 -1
- package/lib/contracts.d.ts.map +1 -1
- package/lib/contracts.js +4 -12
- package/lib/contracts.js.map +1 -1
- package/lib/deltaManager.d.ts.map +1 -1
- package/lib/deltaManager.js +18 -3
- package/lib/deltaManager.js.map +1 -1
- package/lib/legacy.d.ts +1 -1
- package/lib/packageVersion.d.ts +1 -1
- package/lib/packageVersion.d.ts.map +1 -1
- package/lib/packageVersion.js +1 -1
- package/lib/packageVersion.js.map +1 -1
- package/lib/public.d.ts +1 -1
- package/lib/serializedStateManager.d.ts.map +1 -1
- package/lib/serializedStateManager.js +18 -5
- package/lib/serializedStateManager.js.map +1 -1
- package/lib/utils.d.ts.map +1 -1
- package/lib/utils.js +11 -2
- package/lib/utils.js.map +1 -1
- package/package.json +25 -23
- package/src/connectionManager.ts +13 -12
- package/src/container.ts +31 -8
- package/src/containerStorageAdapter.ts +22 -7
- package/src/contracts.ts +5 -11
- package/src/deltaManager.ts +18 -6
- package/src/packageVersion.ts +1 -1
- package/src/serializedStateManager.ts +20 -12
- package/src/utils.ts +15 -6
- package/tsconfig.json +0 -1
|
@@ -20,7 +20,7 @@ import {
|
|
|
20
20
|
ISnapshotTree,
|
|
21
21
|
IVersion,
|
|
22
22
|
} from "@fluidframework/driver-definitions/internal";
|
|
23
|
-
import { UsageError } from "@fluidframework/driver-utils/internal";
|
|
23
|
+
import { isInstanceOfISnapshot, UsageError } from "@fluidframework/driver-utils/internal";
|
|
24
24
|
import { ITelemetryLoggerExt } from "@fluidframework/telemetry-utils/internal";
|
|
25
25
|
|
|
26
26
|
// eslint-disable-next-line import/no-deprecated
|
|
@@ -31,7 +31,7 @@ import type {
|
|
|
31
31
|
ISerializedStateManagerDocumentStorageService,
|
|
32
32
|
ISnapshotInfo,
|
|
33
33
|
} from "./serializedStateManager.js";
|
|
34
|
-
import { convertSnapshotInfoToSnapshot
|
|
34
|
+
import { convertSnapshotInfoToSnapshot } from "./utils.js";
|
|
35
35
|
|
|
36
36
|
/**
|
|
37
37
|
* Stringified blobs from a summary/snapshot tree.
|
|
@@ -174,13 +174,15 @@ export class ContainerStorageAdapter
|
|
|
174
174
|
let snapshot: ISnapshot;
|
|
175
175
|
if (
|
|
176
176
|
this.loadingGroupIdSnapshotsFromPendingState !== undefined &&
|
|
177
|
-
snapshotFetchOptions?.loadingGroupIds !== undefined
|
|
177
|
+
snapshotFetchOptions?.loadingGroupIds?.[0] !== undefined
|
|
178
178
|
) {
|
|
179
179
|
const localSnapshot =
|
|
180
180
|
this.loadingGroupIdSnapshotsFromPendingState[snapshotFetchOptions.loadingGroupIds[0]];
|
|
181
181
|
assert(localSnapshot !== undefined, 0x970 /* Local snapshot must be present */);
|
|
182
|
-
|
|
183
|
-
|
|
182
|
+
snapshot = convertSnapshotInfoToSnapshot(
|
|
183
|
+
localSnapshot,
|
|
184
|
+
localSnapshot.snapshotSequenceNumber,
|
|
185
|
+
);
|
|
184
186
|
} else {
|
|
185
187
|
if (this._storageService.getSnapshot === undefined) {
|
|
186
188
|
throw new UsageError(
|
|
@@ -315,11 +317,19 @@ const redirectTableBlobName = ".redirectTable";
|
|
|
315
317
|
* Get blob contents of a snapshot tree from storage (or, ideally, cache)
|
|
316
318
|
*/
|
|
317
319
|
export async function getBlobContentsFromTree(
|
|
318
|
-
snapshot: ISnapshotTree,
|
|
320
|
+
snapshot: ISnapshot | ISnapshotTree,
|
|
319
321
|
storage: Pick<IDocumentStorageService, "readBlob">,
|
|
320
322
|
): Promise<ISerializableBlobContents> {
|
|
321
323
|
const blobs = {};
|
|
322
|
-
|
|
324
|
+
if (isInstanceOfISnapshot(snapshot)) {
|
|
325
|
+
const blobContents = snapshot.blobContents;
|
|
326
|
+
for (const [id, content] of blobContents.entries()) {
|
|
327
|
+
// ArrayBufferLike will not survive JSON.stringify()
|
|
328
|
+
blobs[id] = bufferToString(content, "utf8");
|
|
329
|
+
}
|
|
330
|
+
} else {
|
|
331
|
+
await getBlobContentsFromTreeCore(snapshot, blobs, storage);
|
|
332
|
+
}
|
|
323
333
|
return blobs;
|
|
324
334
|
}
|
|
325
335
|
|
|
@@ -352,6 +362,7 @@ async function getBlobManagerTreeFromTree(
|
|
|
352
362
|
storage: Pick<IDocumentStorageService, "readBlob">,
|
|
353
363
|
): Promise<void> {
|
|
354
364
|
const id = tree.blobs[redirectTableBlobName];
|
|
365
|
+
assert(id !== undefined, 0x9ce /* id is undefined in getBlobManagerTreeFromTree */);
|
|
355
366
|
const blob = await storage.readBlob(id);
|
|
356
367
|
// ArrayBufferLike will not survive JSON.stringify()
|
|
357
368
|
blobs[id] = bufferToString(blob, "utf8");
|
|
@@ -394,6 +405,10 @@ function getBlobManagerTreeFromTreeWithBlobContents(
|
|
|
394
405
|
blobs: ISerializableBlobContents,
|
|
395
406
|
): void {
|
|
396
407
|
const id = tree.blobs[redirectTableBlobName];
|
|
408
|
+
assert(
|
|
409
|
+
id !== undefined,
|
|
410
|
+
0x9cf /* id is undefined in getBlobManagerTreeFromTreeWithBlobContents */,
|
|
411
|
+
);
|
|
397
412
|
const blob = tree.blobsContents?.[id];
|
|
398
413
|
assert(blob !== undefined, 0x70f /* Blob must be present in blobsContents */);
|
|
399
414
|
// ArrayBufferLike will not survive JSON.stringify()
|
package/src/contracts.ts
CHANGED
|
@@ -214,15 +214,9 @@ export const getPackageName = (
|
|
|
214
214
|
codeDetails: IFluidCodeDetails | undefined,
|
|
215
215
|
): IContainerPackageInfo => {
|
|
216
216
|
// TODO: use a real type
|
|
217
|
-
//
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
containerPackageName = codeDetails?.package.name;
|
|
223
|
-
} else {
|
|
224
|
-
containerPackageName = codeDetails?.package;
|
|
225
|
-
}
|
|
226
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
227
|
-
return { name: containerPackageName };
|
|
217
|
+
// This is the normal path that any modern customer would hit
|
|
218
|
+
const containerPackageName: string | undefined = isFluidPackage(codeDetails?.package)
|
|
219
|
+
? codeDetails?.package.name
|
|
220
|
+
: codeDetails?.package;
|
|
221
|
+
return { name: containerPackageName as string };
|
|
228
222
|
};
|
package/src/deltaManager.ts
CHANGED
|
@@ -357,16 +357,22 @@ export class DeltaManager<TConnectionManager extends IConnectionManager>
|
|
|
357
357
|
|
|
358
358
|
if (batch.length === 1) {
|
|
359
359
|
assert(
|
|
360
|
-
|
|
360
|
+
// Non null asserting here because of the length check above
|
|
361
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
362
|
+
(batch[0]!.metadata as IBatchMetadata)?.batch === undefined,
|
|
361
363
|
0x3c9 /* no batch markup on single message */,
|
|
362
364
|
);
|
|
363
365
|
} else {
|
|
364
366
|
assert(
|
|
365
|
-
|
|
367
|
+
// TODO why are we non null asserting here?
|
|
368
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
369
|
+
(batch[0]!.metadata as IBatchMetadata)?.batch === true,
|
|
366
370
|
0x3ca /* no start batch markup */,
|
|
367
371
|
);
|
|
368
372
|
assert(
|
|
369
|
-
|
|
373
|
+
// TODO why are we non null asserting here?
|
|
374
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
375
|
+
(batch[batch.length - 1]!.metadata as IBatchMetadata)?.batch === false,
|
|
370
376
|
0x3cb /* no end batch markup */,
|
|
371
377
|
);
|
|
372
378
|
}
|
|
@@ -892,8 +898,12 @@ export class DeltaManager<TConnectionManager extends IConnectionManager>
|
|
|
892
898
|
return;
|
|
893
899
|
}
|
|
894
900
|
|
|
895
|
-
|
|
896
|
-
|
|
901
|
+
// Non null asserting here because of the length check above
|
|
902
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
903
|
+
const from = messages[0]!.sequenceNumber;
|
|
904
|
+
// Non null asserting here because of the length check above
|
|
905
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
906
|
+
const last = messages[messages.length - 1]!.sequenceNumber;
|
|
897
907
|
|
|
898
908
|
// Report stats about missing and duplicate ops
|
|
899
909
|
// This helps better understand why we fetch ops from storage, and thus may delay
|
|
@@ -960,7 +970,9 @@ export class DeltaManager<TConnectionManager extends IConnectionManager>
|
|
|
960
970
|
}
|
|
961
971
|
}
|
|
962
972
|
|
|
963
|
-
|
|
973
|
+
// Non null asserting here because of the length check above
|
|
974
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
975
|
+
this.updateLatestKnownOpSeqNumber(messages[messages.length - 1]!.sequenceNumber);
|
|
964
976
|
|
|
965
977
|
const n = this.previouslyProcessedMessage?.sequenceNumber;
|
|
966
978
|
assert(
|
package/src/packageVersion.ts
CHANGED
|
@@ -188,7 +188,9 @@ export class SerializedStateManager {
|
|
|
188
188
|
if (pendingLocalState && pendingLocalState.savedOps.length > 0) {
|
|
189
189
|
const savedOpsSize = pendingLocalState.savedOps.length;
|
|
190
190
|
this.lastSavedOpSequenceNumber =
|
|
191
|
-
|
|
191
|
+
// Non null asserting here because of the length check above
|
|
192
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
193
|
+
pendingLocalState.savedOps[savedOpsSize - 1]!.sequenceNumber;
|
|
192
194
|
}
|
|
193
195
|
containerEvent.on("saved", () => this.updateSnapshotAndProcessedOpsMaybe());
|
|
194
196
|
}
|
|
@@ -240,10 +242,7 @@ export class SerializedStateManager {
|
|
|
240
242
|
const baseSnapshotTree: ISnapshotTree | undefined = getSnapshotTree(baseSnapshot);
|
|
241
243
|
// non-interactive clients will not have any pending state we want to save
|
|
242
244
|
if (this.offlineLoadEnabled) {
|
|
243
|
-
const snapshotBlobs = await getBlobContentsFromTree(
|
|
244
|
-
baseSnapshotTree,
|
|
245
|
-
this.storageAdapter,
|
|
246
|
-
);
|
|
245
|
+
const snapshotBlobs = await getBlobContentsFromTree(baseSnapshot, this.storageAdapter);
|
|
247
246
|
const attributes = await getDocumentAttributes(this.storageAdapter, baseSnapshotTree);
|
|
248
247
|
this.snapshot = {
|
|
249
248
|
baseSnapshot: baseSnapshotTree,
|
|
@@ -344,7 +343,9 @@ export class SerializedStateManager {
|
|
|
344
343
|
if (
|
|
345
344
|
snapshotSequenceNumber === undefined ||
|
|
346
345
|
this.processedOps.length === 0 ||
|
|
347
|
-
|
|
346
|
+
// Non null asserting here because of the length check above
|
|
347
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
348
|
+
this.processedOps[this.processedOps.length - 1]!.sequenceNumber <
|
|
348
349
|
this.lastSavedOpSequenceNumber ||
|
|
349
350
|
this.containerDirty()
|
|
350
351
|
) {
|
|
@@ -352,9 +353,13 @@ export class SerializedStateManager {
|
|
|
352
353
|
// Pending state would be behind the latest snapshot.
|
|
353
354
|
return -1;
|
|
354
355
|
}
|
|
355
|
-
|
|
356
|
+
// Non null asserting here because of the length check above
|
|
357
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
358
|
+
const firstProcessedOpSequenceNumber = this.processedOps[0]!.sequenceNumber;
|
|
356
359
|
const lastProcessedOpSequenceNumber =
|
|
357
|
-
|
|
360
|
+
// Non null asserting here because of the length check above
|
|
361
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
362
|
+
this.processedOps[this.processedOps.length - 1]!.sequenceNumber;
|
|
358
363
|
|
|
359
364
|
if (snapshotSequenceNumber < firstProcessedOpSequenceNumber) {
|
|
360
365
|
// Snapshot seq number is older than our first processed op, which could mean we're fetching
|
|
@@ -380,7 +385,9 @@ export class SerializedStateManager {
|
|
|
380
385
|
snapshotSequenceNumber,
|
|
381
386
|
firstProcessedOpSequenceNumber,
|
|
382
387
|
newFirstProcessedOpSequenceNumber:
|
|
383
|
-
|
|
388
|
+
// Non null asserting here because of the length check above
|
|
389
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
390
|
+
this.processedOps.length === 0 ? undefined : this.processedOps[0]!.sequenceNumber,
|
|
384
391
|
});
|
|
385
392
|
}
|
|
386
393
|
return snapshotSequenceNumber;
|
|
@@ -404,8 +411,9 @@ export class SerializedStateManager {
|
|
|
404
411
|
".protocol" in baseSnapshot.trees
|
|
405
412
|
? baseSnapshot.trees[".protocol"].blobs.attributes
|
|
406
413
|
: baseSnapshot.blobs[".attributes"];
|
|
407
|
-
//
|
|
408
|
-
|
|
414
|
+
// TODO why are we non null asserting here?
|
|
415
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-non-null-assertion
|
|
416
|
+
const attributes = JSON.parse(snapshotBlobs[attributesHash!]!);
|
|
409
417
|
assert(
|
|
410
418
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
411
419
|
attributes.sequenceNumber === 0,
|
|
@@ -513,7 +521,7 @@ export async function getLatestSnapshotInfo(
|
|
|
513
521
|
|
|
514
522
|
const baseSnapshotTree: ISnapshotTree | undefined = getSnapshotTree(baseSnapshot);
|
|
515
523
|
const snapshotFetchedTime = Date.now();
|
|
516
|
-
const snapshotBlobs = await getBlobContentsFromTree(
|
|
524
|
+
const snapshotBlobs = await getBlobContentsFromTree(baseSnapshot, storageAdapter);
|
|
517
525
|
const attributes: IDocumentAttributes = await getDocumentAttributes(
|
|
518
526
|
storageAdapter,
|
|
519
527
|
baseSnapshotTree,
|
package/src/utils.ts
CHANGED
|
@@ -94,8 +94,12 @@ export function tryParseCompatibleResolvedUrl(url: string): IParsedUrl | undefin
|
|
|
94
94
|
const match = regex.exec(parsed.pathname);
|
|
95
95
|
return match?.length === 3
|
|
96
96
|
? {
|
|
97
|
-
|
|
98
|
-
|
|
97
|
+
// Non null asserting here because of the length check above
|
|
98
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
99
|
+
id: match[1]!,
|
|
100
|
+
// Non null asserting here because of the length check above
|
|
101
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
102
|
+
path: match[2]!,
|
|
99
103
|
query,
|
|
100
104
|
// URLSearchParams returns null if the param is not provided.
|
|
101
105
|
version: parsed.searchParams.get("version") ?? undefined,
|
|
@@ -147,7 +151,9 @@ function convertSummaryToSnapshotAndBlobs(summary: ISummaryTree): SnapshotWithBl
|
|
|
147
151
|
};
|
|
148
152
|
const keys = Object.keys(summary.tree);
|
|
149
153
|
for (const key of keys) {
|
|
150
|
-
|
|
154
|
+
// TODO change this to use object.entries
|
|
155
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
156
|
+
const summaryObject = summary.tree[key]!;
|
|
151
157
|
|
|
152
158
|
switch (summaryObject.type) {
|
|
153
159
|
case SummaryType.Tree: {
|
|
@@ -280,8 +286,9 @@ export const combineSnapshotTreeAndSnapshotBlobs = (
|
|
|
280
286
|
|
|
281
287
|
// Process blobs in the current level
|
|
282
288
|
for (const [, id] of Object.entries(baseSnapshot.blobs)) {
|
|
283
|
-
|
|
284
|
-
|
|
289
|
+
const snapshot = snapshotBlobs[id];
|
|
290
|
+
if (snapshot !== undefined) {
|
|
291
|
+
blobsContents[id] = stringToBuffer(snapshot, "utf8");
|
|
285
292
|
}
|
|
286
293
|
}
|
|
287
294
|
|
|
@@ -420,7 +427,9 @@ export async function getDocumentAttributes(
|
|
|
420
427
|
? tree.trees[".protocol"].blobs.attributes
|
|
421
428
|
: tree.blobs[".attributes"];
|
|
422
429
|
|
|
423
|
-
|
|
430
|
+
// Non null asserting here because of the length check above
|
|
431
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
432
|
+
const attributes = await readAndParse<IDocumentAttributes>(storage, attributesHash!);
|
|
424
433
|
|
|
425
434
|
return attributes;
|
|
426
435
|
}
|