@fluidframework/container-loader 2.0.0-internal.6.1.1 → 2.0.0-internal.6.2.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.
Files changed (85) hide show
  1. package/CHANGELOG.md +38 -0
  2. package/README.md +4 -3
  3. package/dist/connectionManager.d.ts +1 -1
  4. package/dist/connectionManager.d.ts.map +1 -1
  5. package/dist/connectionManager.js +2 -3
  6. package/dist/connectionManager.js.map +1 -1
  7. package/dist/container.d.ts +8 -1
  8. package/dist/container.d.ts.map +1 -1
  9. package/dist/container.js +56 -45
  10. package/dist/container.js.map +1 -1
  11. package/dist/contracts.d.ts +2 -2
  12. package/dist/contracts.d.ts.map +1 -1
  13. package/dist/contracts.js.map +1 -1
  14. package/dist/deltaManager.d.ts +2 -3
  15. package/dist/deltaManager.d.ts.map +1 -1
  16. package/dist/deltaManager.js +11 -11
  17. package/dist/deltaManager.js.map +1 -1
  18. package/dist/disposal.d.ts +2 -2
  19. package/dist/disposal.d.ts.map +1 -1
  20. package/dist/disposal.js +1 -1
  21. package/dist/disposal.js.map +1 -1
  22. package/dist/error.d.ts +23 -0
  23. package/dist/error.d.ts.map +1 -0
  24. package/dist/error.js +32 -0
  25. package/dist/error.js.map +1 -0
  26. package/dist/loader.d.ts +9 -2
  27. package/dist/loader.d.ts.map +1 -1
  28. package/dist/loader.js +12 -7
  29. package/dist/loader.js.map +1 -1
  30. package/dist/noopHeuristic.d.ts +1 -1
  31. package/dist/noopHeuristic.d.ts.map +1 -1
  32. package/dist/noopHeuristic.js.map +1 -1
  33. package/dist/packageVersion.d.ts +1 -1
  34. package/dist/packageVersion.js +1 -1
  35. package/dist/packageVersion.js.map +1 -1
  36. package/dist/retriableDocumentStorageService.d.ts.map +1 -1
  37. package/dist/retriableDocumentStorageService.js +2 -2
  38. package/dist/retriableDocumentStorageService.js.map +1 -1
  39. package/lib/connectionManager.d.ts +1 -1
  40. package/lib/connectionManager.d.ts.map +1 -1
  41. package/lib/connectionManager.js +1 -2
  42. package/lib/connectionManager.js.map +1 -1
  43. package/lib/container.d.ts +8 -1
  44. package/lib/container.d.ts.map +1 -1
  45. package/lib/container.js +44 -33
  46. package/lib/container.js.map +1 -1
  47. package/lib/contracts.d.ts +2 -2
  48. package/lib/contracts.d.ts.map +1 -1
  49. package/lib/contracts.js.map +1 -1
  50. package/lib/deltaManager.d.ts +2 -3
  51. package/lib/deltaManager.d.ts.map +1 -1
  52. package/lib/deltaManager.js +2 -2
  53. package/lib/deltaManager.js.map +1 -1
  54. package/lib/disposal.d.ts +2 -2
  55. package/lib/disposal.d.ts.map +1 -1
  56. package/lib/disposal.js +1 -1
  57. package/lib/disposal.js.map +1 -1
  58. package/lib/error.d.ts +23 -0
  59. package/lib/error.d.ts.map +1 -0
  60. package/lib/error.js +28 -0
  61. package/lib/error.js.map +1 -0
  62. package/lib/loader.d.ts +9 -2
  63. package/lib/loader.d.ts.map +1 -1
  64. package/lib/loader.js +11 -6
  65. package/lib/loader.js.map +1 -1
  66. package/lib/noopHeuristic.d.ts +1 -1
  67. package/lib/noopHeuristic.d.ts.map +1 -1
  68. package/lib/noopHeuristic.js.map +1 -1
  69. package/lib/packageVersion.d.ts +1 -1
  70. package/lib/packageVersion.js +1 -1
  71. package/lib/packageVersion.js.map +1 -1
  72. package/lib/retriableDocumentStorageService.d.ts.map +1 -1
  73. package/lib/retriableDocumentStorageService.js +1 -1
  74. package/lib/retriableDocumentStorageService.js.map +1 -1
  75. package/package.json +15 -21
  76. package/src/connectionManager.ts +8 -3
  77. package/src/container.ts +77 -43
  78. package/src/contracts.ts +1 -2
  79. package/src/deltaManager.ts +12 -10
  80. package/src/disposal.ts +2 -2
  81. package/src/error.ts +44 -0
  82. package/src/loader.ts +30 -5
  83. package/src/noopHeuristic.ts +1 -1
  84. package/src/packageVersion.ts +1 -1
  85. 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 container_utils_1.UsageError("waitContainerToCatchUp: Container closed");
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 container_utils_1.GenericError(`${baseMessage}: ${innerMessage}`))
66
- : new container_utils_1.GenericError(baseMessage));
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 container_utils_1.GenericError("Container closed without error during load"));
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 container_utils_1.UsageError("The context is already disposed");
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 container_utils_1.UsageError("Can't get pending local state unless offline load is enabled");
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 container_utils_1.UsageError("Pending state cannot be retried if the container is closed or disposed");
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
- clientId: this.clientId,
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 container_utils_1.UsageError(`The Container is not in a valid state for attach [${this._lifecycleState}]`);
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.resumeInternal({
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 container_utils_1.UsageError(`The Container is closed and cannot be connected`);
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 container_utils_1.UsageError(`The Container is not attached and cannot be connected`);
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 container_utils_1.UsageError(`The Container is closed and cannot be disconnected`);
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 container_utils_1.GenericError("Existing context does not satisfy incoming proposal");
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, "all");
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, pendingLocalState?.pendingRuntimeState);
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
- switch (loadMode.deltaConnection) {
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 container_utils_1.GenericError("invalidContainerSubmitOpType", undefined /* error */, { messageType: type });
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