@fluidframework/container-loader 2.0.0-internal.6.1.2 → 2.0.0-internal.6.2.1
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 +38 -0
- package/README.md +4 -3
- package/dist/connectionManager.d.ts +1 -1
- package/dist/connectionManager.d.ts.map +1 -1
- package/dist/connectionManager.js +2 -3
- package/dist/connectionManager.js.map +1 -1
- package/dist/container.d.ts +8 -1
- package/dist/container.d.ts.map +1 -1
- package/dist/container.js +56 -45
- package/dist/container.js.map +1 -1
- package/dist/contracts.d.ts +2 -2
- package/dist/contracts.d.ts.map +1 -1
- package/dist/contracts.js.map +1 -1
- package/dist/deltaManager.d.ts +2 -3
- package/dist/deltaManager.d.ts.map +1 -1
- package/dist/deltaManager.js +11 -11
- package/dist/deltaManager.js.map +1 -1
- package/dist/disposal.d.ts +2 -2
- package/dist/disposal.d.ts.map +1 -1
- package/dist/disposal.js +1 -1
- package/dist/disposal.js.map +1 -1
- package/dist/error.d.ts +23 -0
- package/dist/error.d.ts.map +1 -0
- package/dist/error.js +32 -0
- package/dist/error.js.map +1 -0
- package/dist/loader.d.ts +9 -2
- package/dist/loader.d.ts.map +1 -1
- package/dist/loader.js +12 -7
- package/dist/loader.js.map +1 -1
- package/dist/noopHeuristic.d.ts +1 -1
- package/dist/noopHeuristic.d.ts.map +1 -1
- 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/retriableDocumentStorageService.d.ts.map +1 -1
- package/dist/retriableDocumentStorageService.js +2 -2
- package/dist/retriableDocumentStorageService.js.map +1 -1
- package/lib/connectionManager.d.ts +1 -1
- package/lib/connectionManager.d.ts.map +1 -1
- package/lib/connectionManager.js +1 -2
- package/lib/connectionManager.js.map +1 -1
- package/lib/container.d.ts +8 -1
- package/lib/container.d.ts.map +1 -1
- package/lib/container.js +44 -33
- package/lib/container.js.map +1 -1
- package/lib/contracts.d.ts +2 -2
- package/lib/contracts.d.ts.map +1 -1
- package/lib/contracts.js.map +1 -1
- package/lib/deltaManager.d.ts +2 -3
- package/lib/deltaManager.d.ts.map +1 -1
- package/lib/deltaManager.js +2 -2
- package/lib/deltaManager.js.map +1 -1
- package/lib/disposal.d.ts +2 -2
- package/lib/disposal.d.ts.map +1 -1
- package/lib/disposal.js +1 -1
- package/lib/disposal.js.map +1 -1
- package/lib/error.d.ts +23 -0
- package/lib/error.d.ts.map +1 -0
- package/lib/error.js +28 -0
- package/lib/error.js.map +1 -0
- package/lib/loader.d.ts +9 -2
- package/lib/loader.d.ts.map +1 -1
- package/lib/loader.js +11 -6
- package/lib/loader.js.map +1 -1
- package/lib/noopHeuristic.d.ts +1 -1
- package/lib/noopHeuristic.d.ts.map +1 -1
- 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/retriableDocumentStorageService.d.ts.map +1 -1
- package/lib/retriableDocumentStorageService.js +1 -1
- package/lib/retriableDocumentStorageService.js.map +1 -1
- package/package.json +13 -15
- package/src/connectionManager.ts +8 -3
- package/src/container.ts +77 -43
- package/src/contracts.ts +1 -2
- package/src/deltaManager.ts +12 -10
- package/src/disposal.ts +2 -2
- package/src/error.ts +44 -0
- package/src/loader.ts +30 -5
- package/src/noopHeuristic.ts +1 -1
- package/src/packageVersion.ts +1 -1
- package/src/retriableDocumentStorageService.ts +1 -3
package/dist/container.js
CHANGED
|
@@ -13,7 +13,6 @@ const merge_1 = __importDefault(require("lodash/merge"));
|
|
|
13
13
|
const uuid_1 = require("uuid");
|
|
14
14
|
const common_utils_1 = require("@fluidframework/common-utils");
|
|
15
15
|
const container_definitions_1 = require("@fluidframework/container-definitions");
|
|
16
|
-
const container_utils_1 = require("@fluidframework/container-utils");
|
|
17
16
|
const driver_utils_1 = require("@fluidframework/driver-utils");
|
|
18
17
|
const protocol_definitions_1 = require("@fluidframework/protocol-definitions");
|
|
19
18
|
const telemetry_utils_1 = require("@fluidframework/telemetry-utils");
|
|
@@ -54,7 +53,7 @@ const packageNotFactoryError = "Code package does not implement IRuntimeFactory"
|
|
|
54
53
|
async function waitContainerToCatchUp(container) {
|
|
55
54
|
// Make sure we stop waiting if container is closed.
|
|
56
55
|
if (container.closed) {
|
|
57
|
-
throw new
|
|
56
|
+
throw new telemetry_utils_1.UsageError("waitContainerToCatchUp: Container closed");
|
|
58
57
|
}
|
|
59
58
|
return new Promise((resolve, reject) => {
|
|
60
59
|
const deltaManager = container.deltaManager;
|
|
@@ -62,8 +61,8 @@ async function waitContainerToCatchUp(container) {
|
|
|
62
61
|
container.off("closed", closedCallback);
|
|
63
62
|
const baseMessage = "Container closed while waiting to catch up";
|
|
64
63
|
reject(err !== undefined
|
|
65
|
-
? (0, telemetry_utils_1.wrapError)(err, (innerMessage) => new
|
|
66
|
-
: new
|
|
64
|
+
? (0, telemetry_utils_1.wrapError)(err, (innerMessage) => new telemetry_utils_1.GenericError(`${baseMessage}: ${innerMessage}`))
|
|
65
|
+
: new telemetry_utils_1.GenericError(baseMessage));
|
|
67
66
|
};
|
|
68
67
|
container.on("closed", closedCallback);
|
|
69
68
|
// Depending on config, transition to "connected" state may include the guarantee
|
|
@@ -182,6 +181,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
182
181
|
const { canReconnect, clientDetailsOverride, urlResolver, documentServiceFactory, codeLoader, options, scope, subLogger, detachedBlobStorage, protocolHandlerBuilder, } = createProps;
|
|
183
182
|
this.connectionTransitionTimes[connectionState_1.ConnectionState.Disconnected] = common_utils_1.performance.now();
|
|
184
183
|
const pendingLocalState = loadProps?.pendingLocalState;
|
|
184
|
+
this._clientId = pendingLocalState?.clientId;
|
|
185
185
|
this._canReconnect = canReconnect ?? true;
|
|
186
186
|
this.clientDetailsOverride = clientDetailsOverride;
|
|
187
187
|
this.urlResolver = urlResolver;
|
|
@@ -346,7 +346,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
346
346
|
: loadMode ?? defaultMode;
|
|
347
347
|
const onClosed = (err) => {
|
|
348
348
|
// pre-0.58 error message: containerClosedWithoutErrorDuringLoad
|
|
349
|
-
reject(err ?? new
|
|
349
|
+
reject(err ?? new telemetry_utils_1.GenericError("Container closed without error during load"));
|
|
350
350
|
};
|
|
351
351
|
container.on("closed", onClosed);
|
|
352
352
|
container
|
|
@@ -362,7 +362,11 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
362
362
|
// Depending where error happens, we can be attempting to connect to web socket
|
|
363
363
|
// and continuously retrying (consider offline mode)
|
|
364
364
|
// Host has no container to close, so it's prudent to do it here
|
|
365
|
+
// Note: We could only dispose the container instead of just close but that would
|
|
366
|
+
// the telemetry where users sometimes search for ContainerClose event to look
|
|
367
|
+
// for load failures. So not removing this at this time.
|
|
365
368
|
container.close(err);
|
|
369
|
+
container.dispose(err);
|
|
366
370
|
onClosed(err);
|
|
367
371
|
});
|
|
368
372
|
}), { start: true, end: true, cancel: "generic" }, disableRecordHeapSize !== true /* recordHeapSize */);
|
|
@@ -501,7 +505,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
501
505
|
*/
|
|
502
506
|
async getEntryPoint() {
|
|
503
507
|
if (this._disposed) {
|
|
504
|
-
throw new
|
|
508
|
+
throw new telemetry_utils_1.UsageError("The context is already disposed");
|
|
505
509
|
}
|
|
506
510
|
if (this._runtime !== undefined) {
|
|
507
511
|
return this._runtime.getEntryPoint?.();
|
|
@@ -632,10 +636,10 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
632
636
|
}
|
|
633
637
|
async getPendingLocalStateCore(props) {
|
|
634
638
|
if (!this.offlineLoadEnabled) {
|
|
635
|
-
throw new
|
|
639
|
+
throw new telemetry_utils_1.UsageError("Can't get pending local state unless offline load is enabled");
|
|
636
640
|
}
|
|
637
641
|
if (this.closed || this._disposed) {
|
|
638
|
-
throw new
|
|
642
|
+
throw new telemetry_utils_1.UsageError("Pending state cannot be retried if the container is closed or disposed");
|
|
639
643
|
}
|
|
640
644
|
(0, common_utils_1.assert)(this.attachState === container_definitions_1.AttachState.Attached, 0x0d1 /* "Container should be attached before close" */);
|
|
641
645
|
(0, common_utils_1.assert)(this.resolvedUrl !== undefined && this.resolvedUrl.type === "fluid", 0x0d2 /* "resolved url should be valid Fluid url" */);
|
|
@@ -649,7 +653,8 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
649
653
|
savedOps: this.savedOps,
|
|
650
654
|
url: this.resolvedUrl.url,
|
|
651
655
|
term: protocol_1.OnlyValidTermValue,
|
|
652
|
-
|
|
656
|
+
// no need to save this if there is no pending runtime state
|
|
657
|
+
clientId: pendingRuntimeState !== undefined ? this.clientId : undefined,
|
|
653
658
|
};
|
|
654
659
|
this.mc.logger.sendTelemetryEvent({ eventName: "GetPendingLocalState" });
|
|
655
660
|
return JSON.stringify(pendingState);
|
|
@@ -670,11 +675,11 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
670
675
|
}
|
|
671
676
|
return JSON.stringify(combinedSummary);
|
|
672
677
|
}
|
|
673
|
-
async attach(request) {
|
|
678
|
+
async attach(request, attachProps) {
|
|
674
679
|
await telemetry_utils_1.PerformanceEvent.timedExecAsync(this.mc.logger, { eventName: "Attach" }, async () => {
|
|
675
680
|
if (this._lifecycleState !== "loaded") {
|
|
676
681
|
// pre-0.58 error message: containerNotValidForAttach
|
|
677
|
-
throw new
|
|
682
|
+
throw new telemetry_utils_1.UsageError(`The Container is not in a valid state for attach [${this._lifecycleState}]`);
|
|
678
683
|
}
|
|
679
684
|
// If container is already attached or attach is in progress, throw an error.
|
|
680
685
|
(0, common_utils_1.assert)(this._attachState === container_definitions_1.AttachState.Detached && !this.attachStarted, 0x205 /* "attach() called more than once" */);
|
|
@@ -754,10 +759,10 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
754
759
|
this.runtime.setAttachState(container_definitions_1.AttachState.Attached);
|
|
755
760
|
this.emit("attached");
|
|
756
761
|
if (!this.closed) {
|
|
757
|
-
this.
|
|
762
|
+
this.handleDeltaConnectionArg({
|
|
758
763
|
fetchOpsFromStorage: false,
|
|
759
764
|
reason: { text: "createDetached" },
|
|
760
|
-
});
|
|
765
|
+
}, attachProps?.deltaConnection);
|
|
761
766
|
}
|
|
762
767
|
}
|
|
763
768
|
catch (error) {
|
|
@@ -790,10 +795,10 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
790
795
|
}
|
|
791
796
|
connect() {
|
|
792
797
|
if (this.closed) {
|
|
793
|
-
throw new
|
|
798
|
+
throw new telemetry_utils_1.UsageError(`The Container is closed and cannot be connected`);
|
|
794
799
|
}
|
|
795
800
|
else if (this._attachState !== container_definitions_1.AttachState.Attached) {
|
|
796
|
-
throw new
|
|
801
|
+
throw new telemetry_utils_1.UsageError(`The Container is not attached and cannot be connected`);
|
|
797
802
|
}
|
|
798
803
|
else if (!this.connected) {
|
|
799
804
|
// Note: no need to fetch ops as we do it preemptively as part of DeltaManager.attachOpHandler().
|
|
@@ -816,7 +821,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
816
821
|
}
|
|
817
822
|
disconnect() {
|
|
818
823
|
if (this.closed) {
|
|
819
|
-
throw new
|
|
824
|
+
throw new telemetry_utils_1.UsageError(`The Container is closed and cannot be disconnected`);
|
|
820
825
|
}
|
|
821
826
|
else {
|
|
822
827
|
this.disconnectInternal({ text: "DocumentDisconnect" });
|
|
@@ -866,7 +871,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
866
871
|
return;
|
|
867
872
|
}
|
|
868
873
|
// pre-0.58 error message: existingContextDoesNotSatisfyIncomingProposal
|
|
869
|
-
const error = new
|
|
874
|
+
const error = new telemetry_utils_1.GenericError("Existing context does not satisfy incoming proposal");
|
|
870
875
|
this.close(error);
|
|
871
876
|
}
|
|
872
877
|
/**
|
|
@@ -917,6 +922,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
917
922
|
* @param specifiedVersion - Version SHA to load snapshot. If not specified, will fetch the latest snapshot.
|
|
918
923
|
*/
|
|
919
924
|
async load(specifiedVersion, loadMode, resolvedUrl, pendingLocalState, loadToSequenceNumber) {
|
|
925
|
+
const timings = { phase1: common_utils_1.performance.now() };
|
|
920
926
|
this.service = await this.serviceFactory.createDocumentService(resolvedUrl, this.subLogger, this.client.details.type === summarizerClientType);
|
|
921
927
|
// Ideally we always connect as "read" by default.
|
|
922
928
|
// Currently that works with SPO & r11s, because we get "write" connection when connecting to non-existing file.
|
|
@@ -947,6 +953,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
947
953
|
});
|
|
948
954
|
}
|
|
949
955
|
this._attachState = container_definitions_1.AttachState.Attached;
|
|
956
|
+
timings.phase2 = common_utils_1.performance.now();
|
|
950
957
|
// Fetch specified snapshot.
|
|
951
958
|
const { snapshot, versionId } = pendingLocalState === undefined
|
|
952
959
|
? await this.fetchSnapshotTree(specifiedVersion)
|
|
@@ -1019,13 +1026,9 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
1019
1026
|
this.attachDeltaManagerOpHandler(dmAttributes, loadMode.deltaConnection !== "none" ? "all" : "none");
|
|
1020
1027
|
break;
|
|
1021
1028
|
case "sequenceNumber":
|
|
1022
|
-
opsBeforeReturnP = this.attachDeltaManagerOpHandler(dmAttributes, "sequenceNumber");
|
|
1023
|
-
break;
|
|
1024
1029
|
case "cached":
|
|
1025
|
-
opsBeforeReturnP = this.attachDeltaManagerOpHandler(dmAttributes, "cached");
|
|
1026
|
-
break;
|
|
1027
1030
|
case "all":
|
|
1028
|
-
opsBeforeReturnP = this.attachDeltaManagerOpHandler(dmAttributes,
|
|
1031
|
+
opsBeforeReturnP = this.attachDeltaManagerOpHandler(dmAttributes, loadMode.opsBeforeReturn);
|
|
1029
1032
|
break;
|
|
1030
1033
|
default:
|
|
1031
1034
|
(0, common_utils_1.unreachableCase)(loadMode.opsBeforeReturn);
|
|
@@ -1033,8 +1036,11 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
1033
1036
|
// ...load in the existing quorum
|
|
1034
1037
|
// Initialize the protocol handler
|
|
1035
1038
|
await this.initializeProtocolStateFromSnapshot(attributes, this.storageAdapter, snapshot);
|
|
1039
|
+
timings.phase3 = common_utils_1.performance.now();
|
|
1036
1040
|
const codeDetails = this.getCodeDetailsFromQuorum();
|
|
1037
|
-
await this.instantiateRuntime(codeDetails, snapshot,
|
|
1041
|
+
await this.instantiateRuntime(codeDetails, snapshot,
|
|
1042
|
+
// give runtime a dummy value so it knows we're loading from a stash blob
|
|
1043
|
+
pendingLocalState ? pendingLocalState?.pendingRuntimeState ?? {} : undefined);
|
|
1038
1044
|
// replay saved ops
|
|
1039
1045
|
if (pendingLocalState) {
|
|
1040
1046
|
for (const message of pendingLocalState.savedOps) {
|
|
@@ -1043,9 +1049,6 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
1043
1049
|
await this.runtime.notifyOpReplay?.(message);
|
|
1044
1050
|
}
|
|
1045
1051
|
pendingLocalState.savedOps = [];
|
|
1046
|
-
// now set clientId to stashed clientId so live ops are correctly processed as local
|
|
1047
|
-
(0, common_utils_1.assert)(this.clientId === undefined, 0x5d6 /* Unexpected clientId when setting stashed clientId */);
|
|
1048
|
-
this._clientId = pendingLocalState?.clientId;
|
|
1049
1052
|
}
|
|
1050
1053
|
// We might have hit some failure that did not manifest itself in exception in this flow,
|
|
1051
1054
|
// do not start op processing in such case - static version of Container.load() will handle it correctly.
|
|
@@ -1057,24 +1060,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
1057
1060
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
1058
1061
|
this._deltaManager.inbound.pause();
|
|
1059
1062
|
}
|
|
1060
|
-
|
|
1061
|
-
case undefined:
|
|
1062
|
-
if (pendingLocalState) {
|
|
1063
|
-
// connect to delta stream now since we did not before
|
|
1064
|
-
this.connectToDeltaStream(connectionArgs);
|
|
1065
|
-
}
|
|
1066
|
-
// intentional fallthrough
|
|
1067
|
-
case "delayed":
|
|
1068
|
-
(0, common_utils_1.assert)(this.inboundQueuePausedFromInit, 0x346 /* inboundQueuePausedFromInit should be true */);
|
|
1069
|
-
this.inboundQueuePausedFromInit = false;
|
|
1070
|
-
this._deltaManager.inbound.resume();
|
|
1071
|
-
this._deltaManager.inboundSignal.resume();
|
|
1072
|
-
break;
|
|
1073
|
-
case "none":
|
|
1074
|
-
break;
|
|
1075
|
-
default:
|
|
1076
|
-
(0, common_utils_1.unreachableCase)(loadMode.deltaConnection);
|
|
1077
|
-
}
|
|
1063
|
+
this.handleDeltaConnectionArg(connectionArgs, loadMode.deltaConnection, pendingLocalState !== undefined);
|
|
1078
1064
|
}
|
|
1079
1065
|
// If we have not yet reached `loadToSequenceNumber`, we will wait for ops to arrive until we reach it
|
|
1080
1066
|
if (loadToSequenceNumber !== undefined &&
|
|
@@ -1099,6 +1085,11 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
1099
1085
|
}
|
|
1100
1086
|
// Internal context is fully loaded at this point
|
|
1101
1087
|
this.setLoaded();
|
|
1088
|
+
timings.end = common_utils_1.performance.now();
|
|
1089
|
+
this.subLogger.sendTelemetryEvent({
|
|
1090
|
+
eventName: "LoadStagesTimings",
|
|
1091
|
+
details: JSON.stringify(timings),
|
|
1092
|
+
}, undefined, 0 /* verbose */);
|
|
1102
1093
|
return {
|
|
1103
1094
|
sequenceNumber: attributes.sequenceNumber,
|
|
1104
1095
|
version: versionId,
|
|
@@ -1402,7 +1393,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
1402
1393
|
case protocol_definitions_1.MessageType.Summarize:
|
|
1403
1394
|
return this.submitSummaryMessage(contents);
|
|
1404
1395
|
default: {
|
|
1405
|
-
const newError = new
|
|
1396
|
+
const newError = new telemetry_utils_1.GenericError("invalidContainerSubmitOpType", undefined /* error */, { messageType: type });
|
|
1406
1397
|
this.close(newError);
|
|
1407
1398
|
return -1;
|
|
1408
1399
|
}
|
|
@@ -1551,6 +1542,26 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
1551
1542
|
this.runtime.setConnectionState(state && !readonly, this.clientId);
|
|
1552
1543
|
}
|
|
1553
1544
|
}
|
|
1545
|
+
handleDeltaConnectionArg(connectionArgs, deltaConnectionArg, canConnect = true) {
|
|
1546
|
+
switch (deltaConnectionArg) {
|
|
1547
|
+
case undefined:
|
|
1548
|
+
if (canConnect) {
|
|
1549
|
+
// connect to delta stream now since we did not before
|
|
1550
|
+
this.connectToDeltaStream(connectionArgs);
|
|
1551
|
+
}
|
|
1552
|
+
// intentional fallthrough
|
|
1553
|
+
case "delayed":
|
|
1554
|
+
(0, common_utils_1.assert)(this.inboundQueuePausedFromInit, 0x346 /* inboundQueuePausedFromInit should be true */);
|
|
1555
|
+
this.inboundQueuePausedFromInit = false;
|
|
1556
|
+
this._deltaManager.inbound.resume();
|
|
1557
|
+
this._deltaManager.inboundSignal.resume();
|
|
1558
|
+
break;
|
|
1559
|
+
case "none":
|
|
1560
|
+
break;
|
|
1561
|
+
default:
|
|
1562
|
+
(0, common_utils_1.unreachableCase)(deltaConnectionArg);
|
|
1563
|
+
}
|
|
1564
|
+
}
|
|
1554
1565
|
}
|
|
1555
1566
|
exports.Container = Container;
|
|
1556
1567
|
//# sourceMappingURL=container.js.map
|