@fluidframework/container-loader 0.59.4001 → 1.0.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 (100) hide show
  1. package/.eslintrc.js +1 -1
  2. package/README.md +1 -1
  3. package/dist/connectionState.d.ts +15 -3
  4. package/dist/connectionState.d.ts.map +1 -1
  5. package/dist/connectionState.js +15 -3
  6. package/dist/connectionState.js.map +1 -1
  7. package/dist/connectionStateHandler.d.ts +6 -4
  8. package/dist/connectionStateHandler.d.ts.map +1 -1
  9. package/dist/connectionStateHandler.js +21 -6
  10. package/dist/connectionStateHandler.js.map +1 -1
  11. package/dist/container.d.ts +18 -26
  12. package/dist/container.d.ts.map +1 -1
  13. package/dist/container.js +54 -88
  14. package/dist/container.js.map +1 -1
  15. package/dist/containerContext.d.ts +6 -4
  16. package/dist/containerContext.d.ts.map +1 -1
  17. package/dist/containerContext.js +8 -7
  18. package/dist/containerContext.js.map +1 -1
  19. package/dist/containerStorageAdapter.d.ts +2 -3
  20. package/dist/containerStorageAdapter.d.ts.map +1 -1
  21. package/dist/containerStorageAdapter.js +0 -3
  22. package/dist/containerStorageAdapter.js.map +1 -1
  23. package/dist/deltaManagerProxy.d.ts +0 -1
  24. package/dist/deltaManagerProxy.d.ts.map +1 -1
  25. package/dist/deltaManagerProxy.js +0 -3
  26. package/dist/deltaManagerProxy.js.map +1 -1
  27. package/dist/index.d.ts +1 -1
  28. package/dist/index.d.ts.map +1 -1
  29. package/dist/index.js.map +1 -1
  30. package/dist/loader.d.ts +1 -13
  31. package/dist/loader.d.ts.map +1 -1
  32. package/dist/loader.js +2 -3
  33. package/dist/loader.js.map +1 -1
  34. package/dist/packageVersion.d.ts +1 -1
  35. package/dist/packageVersion.d.ts.map +1 -1
  36. package/dist/packageVersion.js +1 -1
  37. package/dist/packageVersion.js.map +1 -1
  38. package/dist/protocolTreeDocumentStorageService.d.ts +0 -1
  39. package/dist/protocolTreeDocumentStorageService.d.ts.map +1 -1
  40. package/dist/protocolTreeDocumentStorageService.js +0 -1
  41. package/dist/protocolTreeDocumentStorageService.js.map +1 -1
  42. package/dist/retriableDocumentStorageService.d.ts +1 -2
  43. package/dist/retriableDocumentStorageService.d.ts.map +1 -1
  44. package/dist/retriableDocumentStorageService.js +0 -3
  45. package/dist/retriableDocumentStorageService.js.map +1 -1
  46. package/lib/connectionState.d.ts +15 -3
  47. package/lib/connectionState.d.ts.map +1 -1
  48. package/lib/connectionState.js +15 -3
  49. package/lib/connectionState.js.map +1 -1
  50. package/lib/connectionStateHandler.d.ts +6 -4
  51. package/lib/connectionStateHandler.d.ts.map +1 -1
  52. package/lib/connectionStateHandler.js +21 -6
  53. package/lib/connectionStateHandler.js.map +1 -1
  54. package/lib/container.d.ts +18 -26
  55. package/lib/container.d.ts.map +1 -1
  56. package/lib/container.js +54 -88
  57. package/lib/container.js.map +1 -1
  58. package/lib/containerContext.d.ts +6 -4
  59. package/lib/containerContext.d.ts.map +1 -1
  60. package/lib/containerContext.js +8 -7
  61. package/lib/containerContext.js.map +1 -1
  62. package/lib/containerStorageAdapter.d.ts +2 -3
  63. package/lib/containerStorageAdapter.d.ts.map +1 -1
  64. package/lib/containerStorageAdapter.js +0 -3
  65. package/lib/containerStorageAdapter.js.map +1 -1
  66. package/lib/deltaManagerProxy.d.ts +0 -1
  67. package/lib/deltaManagerProxy.d.ts.map +1 -1
  68. package/lib/deltaManagerProxy.js +0 -3
  69. package/lib/deltaManagerProxy.js.map +1 -1
  70. package/lib/index.d.ts +1 -1
  71. package/lib/index.d.ts.map +1 -1
  72. package/lib/index.js.map +1 -1
  73. package/lib/loader.d.ts +1 -13
  74. package/lib/loader.d.ts.map +1 -1
  75. package/lib/loader.js +2 -3
  76. package/lib/loader.js.map +1 -1
  77. package/lib/packageVersion.d.ts +1 -1
  78. package/lib/packageVersion.d.ts.map +1 -1
  79. package/lib/packageVersion.js +1 -1
  80. package/lib/packageVersion.js.map +1 -1
  81. package/lib/protocolTreeDocumentStorageService.d.ts +0 -1
  82. package/lib/protocolTreeDocumentStorageService.d.ts.map +1 -1
  83. package/lib/protocolTreeDocumentStorageService.js +0 -1
  84. package/lib/protocolTreeDocumentStorageService.js.map +1 -1
  85. package/lib/retriableDocumentStorageService.d.ts +1 -2
  86. package/lib/retriableDocumentStorageService.d.ts.map +1 -1
  87. package/lib/retriableDocumentStorageService.js +0 -3
  88. package/lib/retriableDocumentStorageService.js.map +1 -1
  89. package/package.json +26 -26
  90. package/src/connectionState.ts +20 -6
  91. package/src/connectionStateHandler.ts +29 -8
  92. package/src/container.ts +77 -100
  93. package/src/containerContext.ts +10 -10
  94. package/src/containerStorageAdapter.ts +1 -6
  95. package/src/deltaManagerProxy.ts +0 -4
  96. package/src/index.ts +1 -0
  97. package/src/loader.ts +4 -21
  98. package/src/packageVersion.ts +1 -1
  99. package/src/protocolTreeDocumentStorageService.ts +0 -1
  100. package/src/retriableDocumentStorageService.ts +0 -8
package/src/container.ts CHANGED
@@ -25,7 +25,6 @@ import {
25
25
  ContainerWarning,
26
26
  AttachState,
27
27
  IThrottlingWarning,
28
- IPendingLocalState,
29
28
  ReadOnlyInfo,
30
29
  IContainerLoadMode,
31
30
  IFluidCodeDetails,
@@ -64,6 +63,7 @@ import {
64
63
  IDocumentAttributes,
65
64
  IDocumentMessage,
66
65
  IProcessMessageResult,
66
+ IProtocolState,
67
67
  IQuorumClients,
68
68
  IQuorumProposals,
69
69
  ISequencedClient,
@@ -140,6 +140,10 @@ export interface IContainerConfig {
140
140
  * Client details provided in the override will be merged over the default client.
141
141
  */
142
142
  clientDetailsOverride?: IClientDetails;
143
+ /**
144
+ * Serialized state from a previous instance of this container
145
+ */
146
+ serializedContainerState?: IPendingContainerState;
143
147
  }
144
148
 
145
149
  /**
@@ -147,7 +151,7 @@ export interface IContainerConfig {
147
151
  * Useful when resolving URIs and hitting 404, due to container being loaded from (stale) snapshot and not being
148
152
  * up to date. Host may chose to wait in such case and retry resolving URI.
149
153
  * Warning: Will wait infinitely for connection to establish if there is no connection.
150
- * May result in deadlock if Container.setAutoReconnect(false) is called and never switched back to auto-reconnect.
154
+ * May result in deadlock if Container.disconnect() is called and never followed by a call to Container.connect().
151
155
  * @returns true: container is up to date, it processed all the ops that were know at the time of first connection
152
156
  * false: storage does not provide indication of how far the client is. Container processed
153
157
  * all the ops known to it, but it maybe still behind.
@@ -174,7 +178,8 @@ export async function waitContainerToCatchUp(container: IContainer) {
174
178
  container.on("closed", closedCallback);
175
179
 
176
180
  const waitForOps = () => {
177
- assert(container.connectionState !== ConnectionState.Disconnected,
181
+ assert(container.connectionState === ConnectionState.CatchingUp
182
+ || container.connectionState === ConnectionState.Connected,
178
183
  0x0cd /* "Container disconnected while waiting for ops!" */);
179
184
  const hasCheckpointSequenceNumber = deltaManager.hasCheckpointSequenceNumber;
180
185
 
@@ -211,9 +216,7 @@ export async function waitContainerToCatchUp(container: IContainer) {
211
216
  };
212
217
  container.on(connectedEventName, callback);
213
218
 
214
- // TODO: Remove null check after next release #8523
215
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
216
- container.resume!();
219
+ container.connect();
217
220
  });
218
221
  }
219
222
 
@@ -221,6 +224,18 @@ const getCodeProposal =
221
224
  // eslint-disable-next-line @typescript-eslint/no-unsafe-return
222
225
  (quorum: IQuorumProposals) => quorum.get("code") ?? quorum.get("code2");
223
226
 
227
+ /**
228
+ * State saved by a container at close time, to be used to load a new instance
229
+ * of the container to the same state
230
+ */
231
+ export interface IPendingContainerState {
232
+ pendingRuntimeState: unknown;
233
+ url: string;
234
+ protocol: IProtocolState;
235
+ term: number;
236
+ clientId?: string;
237
+ }
238
+
224
239
  const summarizerClientType = "summarizer";
225
240
 
226
241
  export class Container extends EventEmitterWithErrorHandling<IContainerEvents> implements IContainer {
@@ -232,7 +247,7 @@ export class Container extends EventEmitterWithErrorHandling<IContainerEvents> i
232
247
  public static async load(
233
248
  loader: Loader,
234
249
  loadOptions: IContainerLoadOptions,
235
- pendingLocalState?: unknown,
250
+ pendingLocalState?: IPendingContainerState,
236
251
  ): Promise<Container> {
237
252
  const container = new Container(
238
253
  loader,
@@ -240,6 +255,7 @@ export class Container extends EventEmitterWithErrorHandling<IContainerEvents> i
240
255
  clientDetailsOverride: loadOptions.clientDetailsOverride,
241
256
  resolvedUrl: loadOptions.resolvedUrl,
242
257
  canReconnect: loadOptions.canReconnect,
258
+ serializedContainerState: pendingLocalState,
243
259
  });
244
260
 
245
261
  return PerformanceEvent.timedExecAsync(
@@ -249,12 +265,12 @@ export class Container extends EventEmitterWithErrorHandling<IContainerEvents> i
249
265
  container._lifecycleState = "loading";
250
266
  const version = loadOptions.version;
251
267
 
252
- // always load unpaused with pending ops!
253
- // It is also default mode in general.
254
268
  const defaultMode: IContainerLoadMode = { opsBeforeReturn: "cached" };
255
- assert(pendingLocalState === undefined || loadOptions.loadMode === undefined,
256
- 0x1e1 /* "pending state requires immediate connection!" */);
257
- const mode: IContainerLoadMode = loadOptions.loadMode ?? defaultMode;
269
+ // if we have pendingLocalState, anything we cached is not useful and we shouldn't wait for connection
270
+ // to return container, so ignore this value and use undefined for opsBeforeReturn
271
+ const mode: IContainerLoadMode = pendingLocalState
272
+ ? { ...(loadOptions.loadMode ?? defaultMode), opsBeforeReturn: undefined }
273
+ : loadOptions.loadMode ?? defaultMode;
258
274
 
259
275
  const onClosed = (err?: ICriticalContainerError) => {
260
276
  // pre-0.58 error message: containerClosedWithoutErrorDuringLoad
@@ -597,7 +613,7 @@ export class Container extends EventEmitterWithErrorHandling<IContainerEvents> i
597
613
  // its own join op. Attempt recovery option.
598
614
  this._deltaManager.logConnectionIssue({
599
615
  eventName,
600
- duration: performance.now() - this.connectionTransitionTimes[ConnectionState.Connecting],
616
+ duration: performance.now() - this.connectionTransitionTimes[ConnectionState.CatchingUp],
601
617
  });
602
618
  },
603
619
  connectionStateChanged: () => {
@@ -607,6 +623,7 @@ export class Container extends EventEmitterWithErrorHandling<IContainerEvents> i
607
623
  },
608
624
  },
609
625
  this.mc.logger,
626
+ config.serializedContainerState?.clientId,
610
627
  );
611
628
 
612
629
  this.on(savedContainerEvent, () => {
@@ -748,9 +765,13 @@ export class Container extends EventEmitterWithErrorHandling<IContainerEvents> i
748
765
  assert(this.attachState === AttachState.Attached, 0x0d1 /* "Container should be attached before close" */);
749
766
  assert(this.resolvedUrl !== undefined && this.resolvedUrl.type === "fluid",
750
767
  0x0d2 /* "resolved url should be valid Fluid url" */);
751
- const pendingState: IPendingLocalState = {
768
+ assert(!!this._protocolHandler, 0x2e3 /* "Must have a valid protocol handler instance" */);
769
+ const pendingState: IPendingContainerState = {
752
770
  pendingRuntimeState: this.context.getPendingLocalState(),
753
771
  url: this.resolvedUrl.url,
772
+ protocol: this._protocolHandler.getProtocolState(),
773
+ term: this._protocolHandler.term,
774
+ clientId: this.clientId,
754
775
  };
755
776
 
756
777
  this.close();
@@ -808,7 +829,7 @@ export class Container extends EventEmitterWithErrorHandling<IContainerEvents> i
808
829
  // starting to attach the container to storage.
809
830
  // Also, this should only be fired in detached container.
810
831
  this._attachState = AttachState.Attaching;
811
- this.context.notifyAttaching();
832
+ this.context.notifyAttaching(getSnapshotTreeFromSerializedContainer(summary));
812
833
  }
813
834
 
814
835
  // Actually go and create the resolved document
@@ -860,7 +881,7 @@ export class Container extends EventEmitterWithErrorHandling<IContainerEvents> i
860
881
  summary = combineAppAndProtocolSummary(appSummary, protocolSummary);
861
882
 
862
883
  this._attachState = AttachState.Attaching;
863
- this.context.notifyAttaching();
884
+ this.context.notifyAttaching(getSnapshotTreeFromSerializedContainer(summary));
864
885
 
865
886
  await this.storageService.uploadSummaryWithContext(summary, {
866
887
  referenceSequenceNumber: 0,
@@ -900,30 +921,6 @@ export class Container extends EventEmitterWithErrorHandling<IContainerEvents> i
900
921
  );
901
922
  }
902
923
 
903
- /**
904
- * Dictates whether or not the current container will automatically attempt to reconnect to the delta stream
905
- * after receiving a disconnect event
906
- * @param reconnect - Boolean indicating if reconnect should automatically occur
907
- * @deprecated - 0.58, This API will be removed in 1.0
908
- * Use `connect()` and `disconnect()` instead of `setAutoReconnect(true)` and `setAutoReconnect(false)` respectively
909
- * See https://github.com/microsoft/FluidFramework/issues/9167 for context
910
- */
911
- public setAutoReconnect(reconnect: boolean) {
912
- if (this.closed) {
913
- throw new Error("Attempting to setAutoReconnect() a closed Container");
914
- }
915
-
916
- const mode = reconnect ? ReconnectMode.Enabled : ReconnectMode.Disabled;
917
- this.setAutoReconnectInternal(mode);
918
-
919
- // If container state is not attached and resumed, then don't connect to delta stream. Also don't set the
920
- // manual reconnection flag to true as we haven't made the initial connection yet.
921
- if (reconnect && this._attachState === AttachState.Attached && this.resumedOpProcessingAfterLoad) {
922
- // Ensure connection to web socket
923
- this.connectToDeltaStream({ reason: "autoReconnect" });
924
- }
925
- }
926
-
927
924
  private setAutoReconnectInternal(mode: ReconnectMode) {
928
925
  const currentMode = this._deltaManager.connectionManager.reconnectMode;
929
926
 
@@ -987,23 +984,8 @@ export class Container extends EventEmitterWithErrorHandling<IContainerEvents> i
987
984
  this.setAutoReconnectInternal(mode);
988
985
  }
989
986
 
990
- /**
991
- * Have the container attempt to resume processing ops
992
- * @deprecated - 0.58, This API will be removed in 1.0
993
- * Use `connect()` instead
994
- * See https://github.com/microsoft/FluidFramework/issues/9167 for context
995
- */
996
- public resume() {
997
- if (!this.closed) {
998
- // Note: no need to fetch ops as we do it preemptively as part of DeltaManager.attachOpHandler().
999
- // If there is gap, we will learn about it once connected, but the gap should be small (if any),
1000
- // assuming that resume() is called quickly after initial container boot.
1001
- this.resumeInternal({ reason: "DocumentOpenResume", fetchOpsFromStorage: false });
1002
- }
1003
- }
1004
-
1005
987
  private resumeInternal(args: IConnectionArgs) {
1006
- assert(!this.closed, 0x0d9 /* "Attempting to setAutoReconnect() a closed DeltaManager" */);
988
+ assert(!this.closed, 0x0d9 /* "Attempting to connect() a closed DeltaManager" */);
1007
989
 
1008
990
  // Resume processing ops
1009
991
  if (!this.resumedOpProcessingAfterLoad) {
@@ -1095,7 +1077,7 @@ export class Container extends EventEmitterWithErrorHandling<IContainerEvents> i
1095
1077
  private async load(
1096
1078
  specifiedVersion: string | undefined,
1097
1079
  loadMode: IContainerLoadMode,
1098
- pendingLocalState?: unknown,
1080
+ pendingLocalState?: IPendingContainerState,
1099
1081
  ) {
1100
1082
  if (this._resolvedUrl === undefined) {
1101
1083
  throw new Error("Attempting to load without a resolved url");
@@ -1123,14 +1105,28 @@ export class Container extends EventEmitterWithErrorHandling<IContainerEvents> i
1123
1105
  this.connectToDeltaStream(connectionArgs);
1124
1106
  }
1125
1107
 
1126
- await this.connectStorageService();
1108
+ if (!pendingLocalState) {
1109
+ await this.connectStorageService();
1110
+ } else {
1111
+ // if we have pendingLocalState we can load without storage; don't wait for connection
1112
+ this.connectStorageService().catch((error) => this.close(error));
1113
+ }
1114
+
1127
1115
  this._attachState = AttachState.Attached;
1128
1116
 
1129
1117
  // Fetch specified snapshot.
1130
- const { snapshot, versionId } = await this.fetchSnapshotTree(specifiedVersion);
1131
- assert(snapshot !== undefined, 0x237 /* "Snapshot should exist" */);
1118
+ const { snapshot, versionId } = pendingLocalState === undefined
1119
+ ? await this.fetchSnapshotTree(specifiedVersion)
1120
+ : { snapshot: undefined, versionId: undefined };
1121
+ assert(snapshot !== undefined || pendingLocalState !== undefined, 0x237 /* "Snapshot should exist" */);
1132
1122
 
1133
- const attributes = await this.getDocumentAttributes(this.storageService, snapshot);
1123
+ const attributes: IDocumentAttributes = pendingLocalState === undefined
1124
+ ? await this.getDocumentAttributes(this.storageService, snapshot)
1125
+ : {
1126
+ sequenceNumber: pendingLocalState.protocol.sequenceNumber,
1127
+ minimumSequenceNumber: pendingLocalState.protocol.minimumSequenceNumber,
1128
+ term: pendingLocalState.term,
1129
+ };
1134
1130
 
1135
1131
  let opsBeforeReturnP: Promise<void> | undefined;
1136
1132
 
@@ -1154,15 +1150,21 @@ export class Container extends EventEmitterWithErrorHandling<IContainerEvents> i
1154
1150
 
1155
1151
  // ...load in the existing quorum
1156
1152
  // Initialize the protocol handler
1157
- this._protocolHandler =
1158
- await this.initializeProtocolStateFromSnapshot(attributes, this.storageService, snapshot);
1153
+ this._protocolHandler = pendingLocalState === undefined
1154
+ ? await this.initializeProtocolStateFromSnapshot(attributes, this.storageService, snapshot)
1155
+ : await this.initializeProtocolState(
1156
+ attributes,
1157
+ pendingLocalState.protocol.members,
1158
+ pendingLocalState.protocol.proposals,
1159
+ pendingLocalState.protocol.values,
1160
+ );
1159
1161
 
1160
1162
  const codeDetails = this.getCodeDetailsFromQuorum();
1161
1163
  await this.instantiateContext(
1162
1164
  true, // existing
1163
1165
  codeDetails,
1164
1166
  snapshot,
1165
- pendingLocalState,
1167
+ pendingLocalState?.pendingRuntimeState,
1166
1168
  );
1167
1169
 
1168
1170
  // Propagate current connection state through the system.
@@ -1186,7 +1188,10 @@ export class Container extends EventEmitterWithErrorHandling<IContainerEvents> i
1186
1188
 
1187
1189
  switch (loadMode.deltaConnection) {
1188
1190
  case undefined:
1189
- this.resume();
1191
+ // Note: no need to fetch ops as we do it preemptively as part of DeltaManager.attachOpHandler().
1192
+ // If there is gap, we will learn about it once connected, but the gap should be small (if any),
1193
+ // assuming that resumeInternal() is called quickly after initial container boot.
1194
+ this.resumeInternal({ reason: "DocumentLoad", fetchOpsFromStorage: false });
1190
1195
  break;
1191
1196
  case "delayed":
1192
1197
  this.resumedOpProcessingAfterLoad = true;
@@ -1379,13 +1384,7 @@ export class Container extends EventEmitterWithErrorHandling<IContainerEvents> i
1379
1384
  });
1380
1385
 
1381
1386
  // Track membership changes and update connection state accordingly
1382
- protocol.quorum.on("addMember", (clientId, details) => {
1383
- this.connectionStateHandler.receivedAddMemberEvent(clientId);
1384
- });
1385
-
1386
- protocol.quorum.on("removeMember", (clientId) => {
1387
- this.connectionStateHandler.receivedRemoveMemberEvent(clientId);
1388
- });
1387
+ this.connectionStateHandler.initProtocol(protocol);
1389
1388
 
1390
1389
  protocol.quorum.on("addProposal", (proposal: ISequencedProposal) => {
1391
1390
  if (proposal.key === "code" || proposal.key === "code2") {
@@ -1611,6 +1610,7 @@ export class Container extends EventEmitterWithErrorHandling<IContainerEvents> i
1611
1610
  online: OnlineStatus[isOnline()],
1612
1611
  lastVisible: this.lastVisible !== undefined ? performance.now() - this.lastVisible : undefined,
1613
1612
  checkpointSequenceNumber,
1613
+ quorumSize: this._protocolHandler?.quorum.getMembers().size,
1614
1614
  ...this._deltaManager.connectionProps,
1615
1615
  });
1616
1616
 
@@ -1719,15 +1719,17 @@ export class Container extends EventEmitterWithErrorHandling<IContainerEvents> i
1719
1719
  // That means that if relay service changes settings, such changes will impact only newly booted
1720
1720
  // clients.
1721
1721
  // All existing will continue to use settings they got earlier.
1722
- const [noopTimeFrequency, noopCountFrequency] = this.getNoopConfig();
1722
+ assert(
1723
+ this.serviceConfiguration !== undefined,
1724
+ 0x2e4 /* "there should be service config for active connection" */);
1723
1725
  this.collabWindowTracker = new CollabWindowTracker(
1724
1726
  (type, contents) => {
1725
1727
  assert(this.activeConnection(),
1726
1728
  0x241 /* "disconnect should result in stopSequenceNumberUpdate() call" */);
1727
1729
  this.submitMessage(type, contents);
1728
1730
  },
1729
- noopTimeFrequency,
1730
- noopCountFrequency,
1731
+ this.serviceConfiguration?.noopTimeFrequency,
1732
+ this.serviceConfiguration?.noopCountFrequency,
1731
1733
  );
1732
1734
  }
1733
1735
  this.collabWindowTracker.scheduleSequenceNumberUpdate(message, result.immediateNoOp === true);
@@ -1738,29 +1740,6 @@ export class Container extends EventEmitterWithErrorHandling<IContainerEvents> i
1738
1740
  return result;
1739
1741
  }
1740
1742
 
1741
- /**
1742
- * #260 (ADO)
1743
- * back-compat: noopTimeFrequency & noopCountFrequency properties were added to
1744
- * IClientConfiguration in 0.59.3000. During the integration, we must read the
1745
- * available configuration from the loader options.
1746
- */
1747
- private getNoopConfig(): [number | undefined, number | undefined] {
1748
- assert(
1749
- this.serviceConfiguration !== undefined,
1750
- 0x2e2, /* "there should be service config for active connection" */
1751
- );
1752
-
1753
- if (this.serviceConfiguration.noopTimeFrequency !== undefined ||
1754
- this.serviceConfiguration.noopCountFrequency !== undefined) {
1755
- return [
1756
- this.serviceConfiguration.noopTimeFrequency as number,
1757
- this.serviceConfiguration.noopCountFrequency as number,
1758
- ];
1759
- }
1760
-
1761
- return [this.loader.services.options?.noopTimeFrequency, this.loader.services.options?.noopCountFrequency];
1762
- }
1763
-
1764
1743
  private submitSignal(message: any) {
1765
1744
  this._deltaManager.submitSignal(JSON.stringify(message));
1766
1745
  }
@@ -1807,7 +1786,6 @@ export class Container extends EventEmitterWithErrorHandling<IContainerEvents> i
1807
1786
  private async instantiateContextDetached(
1808
1787
  existing: boolean,
1809
1788
  snapshot?: ISnapshotTree,
1810
- pendingLocalState?: unknown,
1811
1789
  ) {
1812
1790
  const codeDetails = this.getCodeDetailsFromQuorum();
1813
1791
  if (codeDetails === undefined) {
@@ -1818,7 +1796,6 @@ export class Container extends EventEmitterWithErrorHandling<IContainerEvents> i
1818
1796
  existing,
1819
1797
  codeDetails,
1820
1798
  snapshot,
1821
- pendingLocalState,
1822
1799
  );
1823
1800
  }
1824
1801
 
@@ -21,7 +21,7 @@ import {
21
21
  IProvideFluidCodeDetailsComparer,
22
22
  ICodeDetailsLoader,
23
23
  IFluidModuleWithDetails,
24
- IFluidModule,
24
+ ISnapshotTreeWithBlobContents,
25
25
  } from "@fluidframework/container-definitions";
26
26
  import {
27
27
  IRequest,
@@ -92,7 +92,9 @@ export class ContainerContext implements IContainerContext {
92
92
  return this.container.clientId;
93
93
  }
94
94
 
95
- /** @deprecated Added back to unblock 0.56 integration */
95
+ /**
96
+ * DISCLAIMER: this id is only for telemetry purposes. Not suitable for any other usages.
97
+ */
96
98
  public get id(): string {
97
99
  const resolvedUrl = this.container.resolvedUrl;
98
100
  if (isFluidResolvedUrl(resolvedUrl)) {
@@ -159,7 +161,7 @@ export class ContainerContext implements IContainerContext {
159
161
  public readonly scope: FluidObject,
160
162
  private readonly codeLoader: ICodeDetailsLoader,
161
163
  private readonly _codeDetails: IFluidCodeDetails,
162
- private readonly _baseSnapshot: ISnapshotTree | undefined,
164
+ private _baseSnapshot: ISnapshotTree | undefined,
163
165
  public readonly deltaManager: IDeltaManager<ISequencedDocumentMessage, IDocumentMessage>,
164
166
  quorum: IQuorum,
165
167
  public readonly loader: ILoader,
@@ -287,7 +289,9 @@ export class ContainerContext implements IContainerContext {
287
289
  return true;
288
290
  }
289
291
 
290
- public notifyAttaching() {
292
+ public notifyAttaching(snapshot: ISnapshotTreeWithBlobContents) {
293
+ this._baseSnapshot = snapshot;
294
+ this.runtime.notifyAttaching?.(snapshot);
291
295
  this.runtime.setAttachState(AttachState.Attaching);
292
296
  }
293
297
 
@@ -316,11 +320,7 @@ export class ContainerContext implements IContainerContext {
316
320
  }
317
321
 
318
322
  private async loadCodeModule(codeDetails: IFluidCodeDetails): Promise<IFluidModuleWithDetails> {
319
- // load may actually produce a IFluidModule if using a legacy ICodeLoader.
320
- // Because the type system currently does not capture this in load,
321
- // explicitly declare the type here to support both cases.
322
- // See also comment about this below.
323
- const loadCodeResult: IFluidModuleWithDetails | IFluidModule = await PerformanceEvent.timedExecAsync(
323
+ const loadCodeResult = await PerformanceEvent.timedExecAsync(
324
324
  this.taggedLogger,
325
325
  { eventName: "CodeLoad" },
326
326
  async () => this.codeLoader.load(codeDetails),
@@ -336,7 +336,7 @@ export class ContainerContext implements IContainerContext {
336
336
  // If "module" is not in the result, we are using a legacy ICodeLoader. Fix the result up with details.
337
337
  // Once usage drops to 0 we can remove this compat path.
338
338
  this.taggedLogger.sendTelemetryEvent({ eventName: "LegacyCodeLoader" });
339
- return { module: loadCodeResult, details: codeDetails };
339
+ return loadCodeResult;
340
340
  }
341
341
  }
342
342
  // #endregion
@@ -4,6 +4,7 @@
4
4
  */
5
5
 
6
6
  import { ITelemetryLogger } from "@fluidframework/common-definitions";
7
+ import { ISnapshotTreeWithBlobContents } from "@fluidframework/container-definitions";
7
8
  import {
8
9
  IDocumentStorageService,
9
10
  IDocumentStorageServicePolicies,
@@ -14,11 +15,9 @@ import {
14
15
  ISnapshotTree,
15
16
  ISummaryHandle,
16
17
  ISummaryTree,
17
- ITree,
18
18
  IVersion,
19
19
  } from "@fluidframework/protocol-definitions";
20
20
  import { IDetachedBlobStorage } from "./loader";
21
- import { ISnapshotTreeWithBlobContents } from "./utils";
22
21
 
23
22
  /**
24
23
  * This class wraps the actual storage and make sure no wrong apis are called according to
@@ -70,10 +69,6 @@ export class ContainerStorageAdapter implements IDocumentStorageService {
70
69
  return this.storageGetter().getVersions(versionId, count);
71
70
  }
72
71
 
73
- public async write(tree: ITree, parents: string[], message: string, ref: string): Promise<IVersion> {
74
- return this.storageGetter().write(tree, parents, message, ref);
75
- }
76
-
77
72
  public async uploadSummaryWithContext(summary: ISummaryTree, context: ISummaryContext): Promise<string> {
78
73
  return this.storageGetter().uploadSummaryWithContext(summary, context);
79
74
  }
@@ -148,10 +148,6 @@ export class DeltaManagerProxy
148
148
  super.dispose();
149
149
  }
150
150
 
151
- public close(): void {
152
- return this.deltaManager.close();
153
- }
154
-
155
151
  public submitSignal(content: any): void {
156
152
  return this.deltaManager.submitSignal(content);
157
153
  }
package/src/index.ts CHANGED
@@ -8,6 +8,7 @@ export {
8
8
  Container,
9
9
  IContainerLoadOptions,
10
10
  IContainerConfig,
11
+ IPendingContainerState,
11
12
  waitContainerToCatchUp,
12
13
  } from "./container";
13
14
  export {
package/src/loader.ts CHANGED
@@ -17,9 +17,7 @@ import {
17
17
  IFluidModule,
18
18
  IHostLoader,
19
19
  ILoader,
20
- IPendingLocalState,
21
20
  ILoaderOptions as ILoaderOptions1,
22
- IProxyLoaderFactory,
23
21
  LoaderHeader,
24
22
  IProvideFluidCodeDetailsComparer,
25
23
  IFluidCodeDetails,
@@ -47,7 +45,7 @@ import {
47
45
  MultiUrlResolver,
48
46
  MultiDocumentServiceFactory,
49
47
  } from "@fluidframework/driver-utils";
50
- import { Container } from "./container";
48
+ import { Container, IPendingContainerState } from "./container";
51
49
  import { IParsedUrl, parseUrl } from "./utils";
52
50
  import { pkgVersion } from "./packageVersion";
53
51
 
@@ -200,13 +198,6 @@ export interface ILoaderProps {
200
198
  */
201
199
  readonly scope?: FluidObject;
202
200
 
203
- /**
204
- * Proxy loader factories for loading containers via proxy in other contexts,
205
- * like web workers, or worker threads.
206
- * @deprecated Not recommended for general use and will be removed in an upcoming release.
207
- */
208
- readonly proxyLoaderFactories?: Map<string, IProxyLoaderFactory>;
209
-
210
201
  /**
211
202
  * The logger that all telemetry should be pushed to.
212
203
  */
@@ -257,13 +248,6 @@ export interface ILoaderServices {
257
248
  */
258
249
  readonly scope: FluidObject;
259
250
 
260
- /**
261
- * Proxy loader factories for loading containers via proxy in other contexts,
262
- * like web workers, or worker threads.
263
- * @deprecated Not recommended for general use and will be removed in an upcoming release.
264
- */
265
- readonly proxyLoaderFactories: Map<string, IProxyLoaderFactory>;
266
-
267
251
  /**
268
252
  * The logger downstream consumers should construct their loggers from
269
253
  */
@@ -318,7 +302,6 @@ export class Loader implements IHostLoader {
318
302
  options: loaderProps.options ?? {},
319
303
  scope,
320
304
  subLogger: subMc.logger,
321
- proxyLoaderFactories: loaderProps.proxyLoaderFactories ?? new Map<string, IProxyLoaderFactory>(),
322
305
  detachedBlobStorage: loaderProps.detachedBlobStorage,
323
306
  };
324
307
  this.mc = loggerToMonitoringContext(
@@ -394,7 +377,7 @@ export class Loader implements IHostLoader {
394
377
 
395
378
  private async resolveCore(
396
379
  request: IRequest,
397
- pendingLocalState?: IPendingLocalState,
380
+ pendingLocalState?: IPendingContainerState,
398
381
  ): Promise<{ container: Container; parsed: IParsedUrl; }> {
399
382
  const resolvedAsFluid = await this.services.urlResolver.resolve(request);
400
383
  ensureFluidResolvedUrl(resolvedAsFluid);
@@ -436,7 +419,7 @@ export class Loader implements IHostLoader {
436
419
  await this.loadContainer(
437
420
  request,
438
421
  resolvedAsFluid,
439
- pendingLocalState?.pendingRuntimeState);
422
+ pendingLocalState);
440
423
  }
441
424
 
442
425
  if (container.deltaManager.lastSequenceNumber <= fromSequenceNumber) {
@@ -487,7 +470,7 @@ export class Loader implements IHostLoader {
487
470
  private async loadContainer(
488
471
  request: IRequest,
489
472
  resolved: IFluidResolvedUrl,
490
- pendingLocalState?: unknown,
473
+ pendingLocalState?: IPendingContainerState,
491
474
  ): Promise<Container> {
492
475
  return Container.load(
493
476
  this,
@@ -6,4 +6,4 @@
6
6
  */
7
7
 
8
8
  export const pkgName = "@fluidframework/container-loader";
9
- export const pkgVersion = "0.59.4001";
9
+ export const pkgVersion = "1.0.0";
@@ -31,7 +31,6 @@ export class ProtocolTreeStorageService implements IDocumentStorageService, IDis
31
31
 
32
32
  getSnapshotTree = this.internalStorageService.getSnapshotTree.bind(this.internalStorageService);
33
33
  getVersions = this.internalStorageService.getVersions.bind(this.internalStorageService);
34
- write = this.internalStorageService.write.bind(this.internalStorageService);
35
34
  createBlob = this.internalStorageService.createBlob.bind(this.internalStorageService);
36
35
  readBlob = this.internalStorageService.readBlob.bind(this.internalStorageService);
37
36
  downloadSummary = this.internalStorageService.downloadSummary.bind(this.internalStorageService);
@@ -15,7 +15,6 @@ import {
15
15
  ISnapshotTree,
16
16
  ISummaryHandle,
17
17
  ISummaryTree,
18
- ITree,
19
18
  IVersion,
20
19
  } from "@fluidframework/protocol-definitions";
21
20
  import { IDisposable, ITelemetryLogger } from "@fluidframework/common-definitions";
@@ -62,13 +61,6 @@ export class RetriableDocumentStorageService implements IDocumentStorageService,
62
61
  );
63
62
  }
64
63
 
65
- public async write(tree: ITree, parents: string[], message: string, ref: string): Promise<IVersion> {
66
- return this.runWithRetry(
67
- async () => this.internalStorageService.write(tree, parents, message, ref),
68
- "storage_write",
69
- );
70
- }
71
-
72
64
  public async uploadSummaryWithContext(summary: ISummaryTree, context: ISummaryContext): Promise<string> {
73
65
  // Not using retry loop here. Couple reasons:
74
66
  // 1. If client lost connectivity, then retry loop will result in uploading stale summary