@fluidframework/container-runtime 2.0.0-internal.5.4.0 → 2.0.0-internal.6.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.
Files changed (223) hide show
  1. package/CHANGELOG.md +75 -0
  2. package/dist/batchTracker.d.ts +2 -1
  3. package/dist/batchTracker.d.ts.map +1 -1
  4. package/dist/batchTracker.js.map +1 -1
  5. package/dist/blobManager.d.ts +4 -1
  6. package/dist/blobManager.d.ts.map +1 -1
  7. package/dist/blobManager.js +61 -26
  8. package/dist/blobManager.js.map +1 -1
  9. package/dist/connectionTelemetry.js +10 -2
  10. package/dist/connectionTelemetry.js.map +1 -1
  11. package/dist/containerRuntime.d.ts +26 -11
  12. package/dist/containerRuntime.d.ts.map +1 -1
  13. package/dist/containerRuntime.js +189 -131
  14. package/dist/containerRuntime.js.map +1 -1
  15. package/dist/dataStore.js +8 -2
  16. package/dist/dataStore.js.map +1 -1
  17. package/dist/dataStoreContext.d.ts.map +1 -1
  18. package/dist/dataStoreContext.js +24 -26
  19. package/dist/dataStoreContext.js.map +1 -1
  20. package/dist/dataStores.d.ts +20 -4
  21. package/dist/dataStores.d.ts.map +1 -1
  22. package/dist/dataStores.js +107 -53
  23. package/dist/dataStores.js.map +1 -1
  24. package/dist/deltaManagerProxyBase.d.ts +35 -0
  25. package/dist/deltaManagerProxyBase.d.ts.map +1 -0
  26. package/dist/deltaManagerProxyBase.js +77 -0
  27. package/dist/deltaManagerProxyBase.js.map +1 -0
  28. package/dist/deltaManagerSummarizerProxy.d.ts +1 -1
  29. package/dist/deltaManagerSummarizerProxy.d.ts.map +1 -1
  30. package/dist/deltaManagerSummarizerProxy.js +2 -2
  31. package/dist/deltaManagerSummarizerProxy.js.map +1 -1
  32. package/dist/gc/garbageCollection.js +17 -20
  33. package/dist/gc/garbageCollection.js.map +1 -1
  34. package/dist/gc/gcConfigs.js +13 -11
  35. package/dist/gc/gcConfigs.js.map +1 -1
  36. package/dist/gc/gcHelpers.js +4 -6
  37. package/dist/gc/gcHelpers.js.map +1 -1
  38. package/dist/gc/gcSummaryStateTracker.js +4 -6
  39. package/dist/gc/gcSummaryStateTracker.js.map +1 -1
  40. package/dist/gc/gcTelemetry.d.ts.map +1 -1
  41. package/dist/gc/gcTelemetry.js +55 -37
  42. package/dist/gc/gcTelemetry.js.map +1 -1
  43. package/dist/id-compressor/idCompressor.js +49 -51
  44. package/dist/id-compressor/idCompressor.js.map +1 -1
  45. package/dist/id-compressor/idRange.js +2 -2
  46. package/dist/id-compressor/idRange.js.map +1 -1
  47. package/dist/id-compressor/sessionIdNormalizer.js +11 -16
  48. package/dist/id-compressor/sessionIdNormalizer.js.map +1 -1
  49. package/dist/index.d.ts +1 -1
  50. package/dist/index.d.ts.map +1 -1
  51. package/dist/index.js.map +1 -1
  52. package/dist/opLifecycle/batchManager.js +10 -6
  53. package/dist/opLifecycle/batchManager.js.map +1 -1
  54. package/dist/opLifecycle/opCompressor.js +6 -1
  55. package/dist/opLifecycle/opCompressor.js.map +1 -1
  56. package/dist/opLifecycle/opDecompressor.js +11 -9
  57. package/dist/opLifecycle/opDecompressor.js.map +1 -1
  58. package/dist/opLifecycle/opGroupingManager.js +13 -5
  59. package/dist/opLifecycle/opGroupingManager.js.map +1 -1
  60. package/dist/opLifecycle/opSplitter.js +10 -6
  61. package/dist/opLifecycle/opSplitter.js.map +1 -1
  62. package/dist/opLifecycle/outbox.js +1 -2
  63. package/dist/opLifecycle/outbox.js.map +1 -1
  64. package/dist/opLifecycle/remoteMessageProcessor.js +1 -1
  65. package/dist/opLifecycle/remoteMessageProcessor.js.map +1 -1
  66. package/dist/opProperties.js +1 -2
  67. package/dist/opProperties.js.map +1 -1
  68. package/dist/packageVersion.d.ts +1 -1
  69. package/dist/packageVersion.js +1 -1
  70. package/dist/packageVersion.js.map +1 -1
  71. package/dist/pendingStateManager.d.ts +2 -2
  72. package/dist/pendingStateManager.d.ts.map +1 -1
  73. package/dist/pendingStateManager.js +22 -22
  74. package/dist/pendingStateManager.js.map +1 -1
  75. package/dist/scheduleManager.js +14 -10
  76. package/dist/scheduleManager.js.map +1 -1
  77. package/dist/summary/orderedClientElection.d.ts +2 -1
  78. package/dist/summary/orderedClientElection.d.ts.map +1 -1
  79. package/dist/summary/orderedClientElection.js +17 -18
  80. package/dist/summary/orderedClientElection.js.map +1 -1
  81. package/dist/summary/runningSummarizer.d.ts.map +1 -1
  82. package/dist/summary/runningSummarizer.js +35 -57
  83. package/dist/summary/runningSummarizer.js.map +1 -1
  84. package/dist/summary/summarizer.js +4 -7
  85. package/dist/summary/summarizer.js.map +1 -1
  86. package/dist/summary/summarizerClientElection.js +5 -9
  87. package/dist/summary/summarizerClientElection.js.map +1 -1
  88. package/dist/summary/summarizerHeuristics.js +8 -12
  89. package/dist/summary/summarizerHeuristics.js.map +1 -1
  90. package/dist/summary/summarizerNode/summarizerNode.js +22 -15
  91. package/dist/summary/summarizerNode/summarizerNode.js.map +1 -1
  92. package/dist/summary/summarizerNode/summarizerNodeUtils.js +2 -4
  93. package/dist/summary/summarizerNode/summarizerNodeUtils.js.map +1 -1
  94. package/dist/summary/summarizerNode/summarizerNodeWithGc.js +17 -16
  95. package/dist/summary/summarizerNode/summarizerNodeWithGc.js.map +1 -1
  96. package/dist/summary/summaryCollection.js +3 -5
  97. package/dist/summary/summaryCollection.js.map +1 -1
  98. package/dist/summary/summaryFormat.js +1 -2
  99. package/dist/summary/summaryFormat.js.map +1 -1
  100. package/dist/summary/summaryGenerator.d.ts.map +1 -1
  101. package/dist/summary/summaryGenerator.js +62 -21
  102. package/dist/summary/summaryGenerator.js.map +1 -1
  103. package/dist/summary/summaryManager.js +3 -5
  104. package/dist/summary/summaryManager.js.map +1 -1
  105. package/lib/batchTracker.d.ts +2 -1
  106. package/lib/batchTracker.d.ts.map +1 -1
  107. package/lib/batchTracker.js.map +1 -1
  108. package/lib/blobManager.d.ts +4 -1
  109. package/lib/blobManager.d.ts.map +1 -1
  110. package/lib/blobManager.js +61 -26
  111. package/lib/blobManager.js.map +1 -1
  112. package/lib/connectionTelemetry.js +10 -2
  113. package/lib/connectionTelemetry.js.map +1 -1
  114. package/lib/containerRuntime.d.ts +26 -11
  115. package/lib/containerRuntime.d.ts.map +1 -1
  116. package/lib/containerRuntime.js +189 -131
  117. package/lib/containerRuntime.js.map +1 -1
  118. package/lib/dataStore.js +8 -2
  119. package/lib/dataStore.js.map +1 -1
  120. package/lib/dataStoreContext.d.ts.map +1 -1
  121. package/lib/dataStoreContext.js +24 -26
  122. package/lib/dataStoreContext.js.map +1 -1
  123. package/lib/dataStores.d.ts +20 -4
  124. package/lib/dataStores.d.ts.map +1 -1
  125. package/lib/dataStores.js +107 -53
  126. package/lib/dataStores.js.map +1 -1
  127. package/lib/deltaManagerProxyBase.d.ts +35 -0
  128. package/lib/deltaManagerProxyBase.d.ts.map +1 -0
  129. package/lib/deltaManagerProxyBase.js +73 -0
  130. package/lib/deltaManagerProxyBase.js.map +1 -0
  131. package/lib/deltaManagerSummarizerProxy.d.ts +1 -1
  132. package/lib/deltaManagerSummarizerProxy.d.ts.map +1 -1
  133. package/lib/deltaManagerSummarizerProxy.js +1 -1
  134. package/lib/deltaManagerSummarizerProxy.js.map +1 -1
  135. package/lib/gc/garbageCollection.js +17 -20
  136. package/lib/gc/garbageCollection.js.map +1 -1
  137. package/lib/gc/gcConfigs.js +13 -11
  138. package/lib/gc/gcConfigs.js.map +1 -1
  139. package/lib/gc/gcHelpers.js +4 -6
  140. package/lib/gc/gcHelpers.js.map +1 -1
  141. package/lib/gc/gcSummaryStateTracker.js +4 -6
  142. package/lib/gc/gcSummaryStateTracker.js.map +1 -1
  143. package/lib/gc/gcTelemetry.d.ts.map +1 -1
  144. package/lib/gc/gcTelemetry.js +55 -37
  145. package/lib/gc/gcTelemetry.js.map +1 -1
  146. package/lib/id-compressor/idCompressor.js +49 -51
  147. package/lib/id-compressor/idCompressor.js.map +1 -1
  148. package/lib/id-compressor/idRange.js +2 -2
  149. package/lib/id-compressor/idRange.js.map +1 -1
  150. package/lib/id-compressor/sessionIdNormalizer.js +11 -16
  151. package/lib/id-compressor/sessionIdNormalizer.js.map +1 -1
  152. package/lib/index.d.ts +1 -1
  153. package/lib/index.d.ts.map +1 -1
  154. package/lib/index.js.map +1 -1
  155. package/lib/opLifecycle/batchManager.js +10 -6
  156. package/lib/opLifecycle/batchManager.js.map +1 -1
  157. package/lib/opLifecycle/opCompressor.js +6 -1
  158. package/lib/opLifecycle/opCompressor.js.map +1 -1
  159. package/lib/opLifecycle/opDecompressor.js +11 -9
  160. package/lib/opLifecycle/opDecompressor.js.map +1 -1
  161. package/lib/opLifecycle/opGroupingManager.js +13 -5
  162. package/lib/opLifecycle/opGroupingManager.js.map +1 -1
  163. package/lib/opLifecycle/opSplitter.js +10 -6
  164. package/lib/opLifecycle/opSplitter.js.map +1 -1
  165. package/lib/opLifecycle/outbox.js +1 -2
  166. package/lib/opLifecycle/outbox.js.map +1 -1
  167. package/lib/opLifecycle/remoteMessageProcessor.js +1 -1
  168. package/lib/opLifecycle/remoteMessageProcessor.js.map +1 -1
  169. package/lib/opProperties.js +1 -2
  170. package/lib/opProperties.js.map +1 -1
  171. package/lib/packageVersion.d.ts +1 -1
  172. package/lib/packageVersion.js +1 -1
  173. package/lib/packageVersion.js.map +1 -1
  174. package/lib/pendingStateManager.d.ts +2 -2
  175. package/lib/pendingStateManager.d.ts.map +1 -1
  176. package/lib/pendingStateManager.js +22 -22
  177. package/lib/pendingStateManager.js.map +1 -1
  178. package/lib/scheduleManager.js +14 -10
  179. package/lib/scheduleManager.js.map +1 -1
  180. package/lib/summary/orderedClientElection.d.ts +2 -1
  181. package/lib/summary/orderedClientElection.d.ts.map +1 -1
  182. package/lib/summary/orderedClientElection.js +17 -18
  183. package/lib/summary/orderedClientElection.js.map +1 -1
  184. package/lib/summary/runningSummarizer.d.ts.map +1 -1
  185. package/lib/summary/runningSummarizer.js +35 -57
  186. package/lib/summary/runningSummarizer.js.map +1 -1
  187. package/lib/summary/summarizer.js +4 -7
  188. package/lib/summary/summarizer.js.map +1 -1
  189. package/lib/summary/summarizerClientElection.js +5 -9
  190. package/lib/summary/summarizerClientElection.js.map +1 -1
  191. package/lib/summary/summarizerHeuristics.js +8 -12
  192. package/lib/summary/summarizerHeuristics.js.map +1 -1
  193. package/lib/summary/summarizerNode/summarizerNode.js +22 -15
  194. package/lib/summary/summarizerNode/summarizerNode.js.map +1 -1
  195. package/lib/summary/summarizerNode/summarizerNodeUtils.js +2 -4
  196. package/lib/summary/summarizerNode/summarizerNodeUtils.js.map +1 -1
  197. package/lib/summary/summarizerNode/summarizerNodeWithGc.js +17 -16
  198. package/lib/summary/summarizerNode/summarizerNodeWithGc.js.map +1 -1
  199. package/lib/summary/summaryCollection.js +3 -5
  200. package/lib/summary/summaryCollection.js.map +1 -1
  201. package/lib/summary/summaryFormat.js +1 -2
  202. package/lib/summary/summaryFormat.js.map +1 -1
  203. package/lib/summary/summaryGenerator.d.ts.map +1 -1
  204. package/lib/summary/summaryGenerator.js +62 -21
  205. package/lib/summary/summaryGenerator.js.map +1 -1
  206. package/lib/summary/summaryManager.js +3 -5
  207. package/lib/summary/summaryManager.js.map +1 -1
  208. package/package.json +19 -19
  209. package/src/batchTracker.ts +2 -1
  210. package/src/blobManager.ts +43 -2
  211. package/src/containerRuntime.ts +95 -67
  212. package/src/dataStore.ts +7 -1
  213. package/src/dataStoreContext.ts +1 -2
  214. package/src/dataStores.ts +95 -55
  215. package/src/deltaManagerProxyBase.ts +111 -0
  216. package/src/deltaManagerSummarizerProxy.ts +2 -1
  217. package/src/gc/gcTelemetry.ts +1 -2
  218. package/src/index.ts +0 -1
  219. package/src/packageVersion.ts +1 -1
  220. package/src/pendingStateManager.ts +12 -15
  221. package/src/summary/orderedClientElection.ts +2 -1
  222. package/src/summary/runningSummarizer.ts +9 -31
  223. package/src/summary/summaryGenerator.ts +0 -1
@@ -445,14 +445,6 @@ export interface IContainerRuntimeOptions {
445
445
  readonly enableGroupedBatching?: boolean;
446
446
  }
447
447
 
448
- /**
449
- * The summary tree returned by the root node. It adds state relevant to the root of the tree.
450
- */
451
- export interface IRootSummaryTreeWithStats extends ISummaryTreeWithStats {
452
- /** The garbage collection stats if GC ran, undefined otherwise. */
453
- gcStats?: IGCStats;
454
- }
455
-
456
448
  /**
457
449
  * Accepted header keys for requests coming to the runtime.
458
450
  */
@@ -616,6 +608,9 @@ export class ContainerRuntime
616
608
  extends TypedEventEmitter<IContainerRuntimeEvents>
617
609
  implements IContainerRuntime, IRuntime, ISummarizerRuntime, ISummarizerInternalsProvider
618
610
  {
611
+ /**
612
+ * @deprecated - Will be removed in future major release. Migrate all usage of IFluidRouter to the "entryPoint" pattern. Refer to Removing-IFluidRouter.md
613
+ */
619
614
  public get IFluidRouter() {
620
615
  return this;
621
616
  }
@@ -743,8 +738,6 @@ export class ContainerRuntime
743
738
  tryFetchBlob<SerializedIdCompressorWithNoSession>(idCompressorBlobName),
744
739
  ]);
745
740
 
746
- const loadExisting = existing === true || context.existing === true;
747
-
748
741
  // read snapshot blobs needed for BlobManager to load
749
742
  const blobManagerSnapshot = await BlobManager.load(
750
743
  context.baseSnapshot?.trees[blobsTreeName],
@@ -779,9 +772,7 @@ export class ContainerRuntime
779
772
  if (loadSequenceNumberVerification === "log") {
780
773
  logger.sendErrorEvent({ eventName: "SequenceNumberMismatch" }, error);
781
774
  } else {
782
- // Call both close and dispose as closeFn implementation will no longer dispose runtime in future
783
775
  context.closeFn(error);
784
- context.disposeFn?.(error);
785
776
  }
786
777
  }
787
778
  }
@@ -818,7 +809,7 @@ export class ContainerRuntime
818
809
  },
819
810
  containerScope,
820
811
  logger,
821
- loadExisting,
812
+ existing,
822
813
  blobManagerSnapshot,
823
814
  context.storage,
824
815
  idCompressor,
@@ -1178,13 +1169,7 @@ export class ContainerRuntime
1178
1169
  // In old loaders without dispose functionality, closeFn is equivalent but will also switch container to readonly mode
1179
1170
  this.disposeFn = disposeFn ?? closeFn;
1180
1171
  // In cases of summarizer, we want to dispose instead since consumer doesn't interact with this container
1181
- this.closeFn = this.isSummarizerClient
1182
- ? this.disposeFn
1183
- : (error?: ICriticalContainerError) => {
1184
- closeFn(error);
1185
- // Also call disposeFn to retain functionality of runtime being disposed on close
1186
- disposeFn?.(error);
1187
- };
1172
+ this.closeFn = this.isSummarizerClient ? this.disposeFn : closeFn;
1188
1173
 
1189
1174
  this.mc = createChildMonitoringContext({
1190
1175
  logger: this.logger,
@@ -1693,6 +1678,7 @@ export class ContainerRuntime
1693
1678
  /**
1694
1679
  * Notifies this object about the request made to the container.
1695
1680
  * @param request - Request made to the handler.
1681
+ * @deprecated - Will be removed in future major release. Migrate all usage of IFluidRouter to the "entryPoint" pattern. Refer to Removing-IFluidRouter.md
1696
1682
  */
1697
1683
  public async request(request: IRequest): Promise<IResponse> {
1698
1684
  try {
@@ -2274,6 +2260,12 @@ export class ContainerRuntime
2274
2260
  this.dataStores.processSignal(envelope.address, transformed, local);
2275
2261
  }
2276
2262
 
2263
+ /**
2264
+ * Returns the runtime of the data store.
2265
+ * @param id - Id supplied during creating the data store.
2266
+ * @param wait - True if you want to wait for it.
2267
+ * @deprecated - Use getAliasedDataStoreEntryPoint instead to get an aliased data store's entry point.
2268
+ */
2277
2269
  public async getRootDataStore(id: string, wait = true): Promise<IFluidRouter> {
2278
2270
  return this.getRootDataStoreChannel(id, wait);
2279
2271
  }
@@ -2349,15 +2341,30 @@ export class ContainerRuntime
2349
2341
  return result;
2350
2342
  }
2351
2343
 
2352
- public async createDataStore(pkg: string | string[]): Promise<IDataStore> {
2353
- const internalId = uuid();
2354
- return channelToDataStore(
2355
- await this._createDataStore(pkg, internalId),
2356
- internalId,
2357
- this,
2358
- this.dataStores,
2359
- this.mc.logger,
2360
- );
2344
+ /**
2345
+ * Returns the aliased data store's entryPoint, given the alias.
2346
+ * @param alias - The alias for the data store.
2347
+ * @returns - The data store's entry point (IFluidHandle) if it exists and is aliased. Returns undefined if no
2348
+ * data store has been assigned the given alias.
2349
+ */
2350
+ public async getAliasedDataStoreEntryPoint(
2351
+ alias: string,
2352
+ ): Promise<IFluidHandle<FluidObject> | undefined> {
2353
+ await this.dataStores.waitIfPendingAlias(alias);
2354
+ const internalId = this.internalId(alias);
2355
+ const context = await this.dataStores.getDataStoreIfAvailable(internalId, { wait: false });
2356
+ // If the data store is not available or not an alias, return undefined.
2357
+ if (context === undefined || !(await context.isRoot())) {
2358
+ return undefined;
2359
+ }
2360
+
2361
+ const channel = await context.realize();
2362
+ if (channel.entryPoint === undefined) {
2363
+ throw new UsageError(
2364
+ "entryPoint must be defined on data store runtime for using getAliasedDataStoreEntryPoint",
2365
+ );
2366
+ }
2367
+ return channel.entryPoint;
2361
2368
  }
2362
2369
 
2363
2370
  public createDetachedRootDataStore(
@@ -2374,25 +2381,37 @@ export class ContainerRuntime
2374
2381
  return this.dataStores.createDetachedDataStoreCore(pkg, false);
2375
2382
  }
2376
2383
 
2384
+ public async createDataStore(pkg: string | string[]): Promise<IDataStore> {
2385
+ const id = uuid();
2386
+ return channelToDataStore(
2387
+ await this.dataStores
2388
+ ._createFluidDataStoreContext(Array.isArray(pkg) ? pkg : [pkg], id)
2389
+ .realize(),
2390
+ id,
2391
+ this,
2392
+ this.dataStores,
2393
+ this.mc.logger,
2394
+ );
2395
+ }
2396
+
2397
+ /**
2398
+ * @deprecated 0.16 Issue #1537, #3631
2399
+ * @internal
2400
+ */
2377
2401
  public async _createDataStoreWithProps(
2378
2402
  pkg: string | string[],
2379
2403
  props?: any,
2380
2404
  id = uuid(),
2381
2405
  ): Promise<IDataStore> {
2382
- const fluidDataStore = await this.dataStores
2383
- ._createFluidDataStoreContext(Array.isArray(pkg) ? pkg : [pkg], id, props)
2384
- .realize();
2385
- return channelToDataStore(fluidDataStore, id, this, this.dataStores, this.mc.logger);
2386
- }
2387
-
2388
- private async _createDataStore(
2389
- pkg: string | string[],
2390
- id = uuid(),
2391
- props?: any,
2392
- ): Promise<IFluidDataStoreChannel> {
2393
- return this.dataStores
2394
- ._createFluidDataStoreContext(Array.isArray(pkg) ? pkg : [pkg], id, props)
2395
- .realize();
2406
+ return channelToDataStore(
2407
+ await this.dataStores
2408
+ ._createFluidDataStoreContext(Array.isArray(pkg) ? pkg : [pkg], id, props)
2409
+ .realize(),
2410
+ id,
2411
+ this,
2412
+ this.dataStores,
2413
+ this.mc.logger,
2414
+ );
2396
2415
  }
2397
2416
 
2398
2417
  private canSendOps() {
@@ -2573,7 +2592,7 @@ export class ContainerRuntime
2573
2592
  fullGC?: boolean;
2574
2593
  /** True to run GC sweep phase after the mark phase */
2575
2594
  runSweep?: boolean;
2576
- }): Promise<IRootSummaryTreeWithStats> {
2595
+ }): Promise<ISummaryTreeWithStats> {
2577
2596
  this.verifyNotClosed();
2578
2597
 
2579
2598
  const {
@@ -2596,9 +2615,8 @@ export class ContainerRuntime
2596
2615
  });
2597
2616
 
2598
2617
  try {
2599
- let gcStats: IGCStats | undefined;
2600
2618
  if (runGC) {
2601
- gcStats = await this.collectGarbage(
2619
+ await this.collectGarbage(
2602
2620
  { logger: summaryLogger, runSweep, fullGC },
2603
2621
  telemetryContext,
2604
2622
  );
@@ -2615,7 +2633,7 @@ export class ContainerRuntime
2615
2633
  0x12f /* "Container Runtime's summarize should always return a tree" */,
2616
2634
  );
2617
2635
 
2618
- return { stats, summary, gcStats };
2636
+ return { stats, summary };
2619
2637
  } finally {
2620
2638
  this.mc.logger.sendTelemetryEvent({
2621
2639
  eventName: "SummarizeTelemetry",
@@ -2834,7 +2852,6 @@ export class ContainerRuntime
2834
2852
  const latestSnapshotInfo = await this.refreshLatestSummaryAckFromServer(
2835
2853
  createChildLogger({
2836
2854
  logger: summaryNumberLogger,
2837
- namespace: undefined,
2838
2855
  properties: { all: { safeSummary: true } },
2839
2856
  }),
2840
2857
  );
@@ -2915,7 +2932,7 @@ export class ContainerRuntime
2915
2932
  }
2916
2933
 
2917
2934
  const trace = Trace.start();
2918
- let summarizeResult: IRootSummaryTreeWithStats;
2935
+ let summarizeResult: ISummaryTreeWithStats;
2919
2936
  // If the GC state needs to be reset, we need to force a full tree summary and update the unreferenced
2920
2937
  // state of all the nodes.
2921
2938
  const forcedFullTree = this.garbageCollector.summaryStateNeedsReset;
@@ -2934,6 +2951,27 @@ export class ContainerRuntime
2934
2951
  error,
2935
2952
  };
2936
2953
  }
2954
+
2955
+ // If validateSummaryBeforeUpload is true, validate that the summary generated by the summarizer nodes is
2956
+ // correct before this summary is uploaded.
2957
+ if (this.validateSummaryBeforeUpload) {
2958
+ const validateResult = this.summarizerNode.validateSummary();
2959
+ if (!validateResult.success) {
2960
+ const { success, ...loggingProps } = validateResult;
2961
+ const error = new RetriableSummaryError(
2962
+ validateResult.reason,
2963
+ validateResult.retryAfterSeconds,
2964
+ { ...loggingProps },
2965
+ );
2966
+ return {
2967
+ stage: "base",
2968
+ referenceSequenceNumber: summaryRefSeqNum,
2969
+ minimumSequenceNumber,
2970
+ error,
2971
+ };
2972
+ }
2973
+ }
2974
+
2937
2975
  const { summary: summaryTree, stats: partialStats } = summarizeResult;
2938
2976
 
2939
2977
  // Now that we have generated the summary, update the message at last summary to the last message processed.
@@ -2970,21 +3008,6 @@ export class ContainerRuntime
2970
3008
  forcedFullTree,
2971
3009
  } as const;
2972
3010
 
2973
- // If validateSummaryBeforeUpload is true, validate that the summary generated by the summarizer nodes is
2974
- // correct before this summary is uploaded.
2975
- if (this.validateSummaryBeforeUpload) {
2976
- const validateResult = this.summarizerNode.validateSummary();
2977
- if (!validateResult.success) {
2978
- const { success, ...loggingProps } = validateResult;
2979
- const error = new RetriableSummaryError(
2980
- validateResult.reason,
2981
- validateResult.retryAfterSeconds,
2982
- { ...loggingProps },
2983
- );
2984
- return { stage: "base", ...generateSummaryData, error };
2985
- }
2986
- }
2987
-
2988
3011
  continueResult = checkContinue();
2989
3012
  if (!continueResult.continue) {
2990
3013
  return { stage: "generate", ...generateSummaryData, error: continueResult.error };
@@ -3516,7 +3539,7 @@ export class ContainerRuntime
3516
3539
  fetchedSnapshotRefSeq: fetchResult.latestSnapshotRefSeq,
3517
3540
  },
3518
3541
  );
3519
- this.closeFn(error);
3542
+ this.disposeFn(error);
3520
3543
  throw error;
3521
3544
  }
3522
3545
 
@@ -3678,10 +3701,15 @@ export class ContainerRuntime
3678
3701
 
3679
3702
  public notifyAttaching() {} // do nothing (deprecated method)
3680
3703
 
3681
- public getPendingLocalState(): unknown {
3704
+ public async getPendingLocalState(props?: {
3705
+ notifyImminentClosure: boolean;
3706
+ }): Promise<unknown> {
3707
+ this.verifyNotClosed();
3708
+ const waitBlobsToAttach = props?.notifyImminentClosure;
3682
3709
  if (this._orderSequentiallyCalls !== 0) {
3683
3710
  throw new UsageError("can't get state during orderSequentially");
3684
3711
  }
3712
+ const pendingAttachmentBlobs = await this.blobManager.getPendingBlobs(waitBlobsToAttach);
3685
3713
  // Flush pending batch.
3686
3714
  // getPendingLocalState() is only exposed through Container.closeAndGetPendingLocalState(), so it's safe
3687
3715
  // to close current batch.
@@ -3689,7 +3717,7 @@ export class ContainerRuntime
3689
3717
 
3690
3718
  return {
3691
3719
  pending: this.pendingStateManager.getLocalState(),
3692
- pendingAttachmentBlobs: this.blobManager.getPendingBlobs(),
3720
+ pendingAttachmentBlobs,
3693
3721
  };
3694
3722
  }
3695
3723
 
package/src/dataStore.ts CHANGED
@@ -161,7 +161,10 @@ class DataStore implements IDataStore {
161
161
  return "Success";
162
162
  }
163
163
 
164
- async request(request: IRequest): Promise<IResponse> {
164
+ /**
165
+ * @deprecated - Will be removed in future major release. Migrate all usage of IFluidRouter to the "entryPoint" pattern. Refer to Removing-IFluidRouter.md
166
+ */
167
+ public async request(request: IRequest): Promise<IResponse> {
165
168
  return this.fluidDataStoreChannel.request(request);
166
169
  }
167
170
 
@@ -182,6 +185,9 @@ class DataStore implements IDataStore {
182
185
  this.pendingAliases = datastores.pendingAliases;
183
186
  }
184
187
 
188
+ /**
189
+ * @deprecated - Will be removed in future major release. Migrate all usage of IFluidRouter to the "entryPoint" pattern. Refer to Removing-IFluidRouter.md
190
+ */
185
191
  public get IFluidRouter() {
186
192
  return this.fluidDataStoreChannel;
187
193
  }
@@ -849,8 +849,7 @@ export abstract class FluidDataStoreContext
849
849
  await this.realize();
850
850
  }
851
851
  assert(!!this.channel, 0x14c /* "Channel must exist when rebasing ops" */);
852
- const innerContents = contents as FluidDataStoreMessage;
853
- return this.channel.applyStashedOp(innerContents.content);
852
+ return this.channel.applyStashedOp(contents);
854
853
  }
855
854
 
856
855
  private verifyNotClosed(
package/src/dataStores.ts CHANGED
@@ -431,8 +431,7 @@ export class DataStores implements IDisposable {
431
431
  ) {
432
432
  const envelope = message.contents as IEnvelope;
433
433
  const transformed = { ...message, contents: envelope.contents };
434
- const request = { url: envelope.address };
435
- this.validateNotDeleted(envelope.address, request);
434
+ this.validateNotDeleted(envelope.address);
436
435
  const context = this.contexts.get(envelope.address);
437
436
  assert(!!context, 0x162 /* "There should be a store context for the op" */);
438
437
  context.process(transformed, local, localMessageMetadata);
@@ -451,104 +450,145 @@ export class DataStores implements IDisposable {
451
450
  requestHeaderData: RuntimeHeaderData,
452
451
  ): Promise<FluidDataStoreContext> {
453
452
  const headerData = { ...defaultRuntimeHeaderData, ...requestHeaderData };
454
- const request = { url: id };
455
-
456
- this.validateNotDeleted(id, request, headerData);
453
+ this.validateNotDeleted(id, headerData);
457
454
 
458
455
  const context = await this.contexts.getBoundOrRemoted(id, headerData.wait);
459
456
  if (context === undefined) {
460
457
  // The requested data store does not exits. Throw a 404 response exception.
458
+ const request: IRequest = { url: id };
461
459
  throw responseToException(create404Response(request), request);
462
460
  }
463
461
 
464
- this.validateNotTombstoned(context, request, requestHeaderData);
462
+ this.validateNotTombstoned(context, requestHeaderData);
465
463
 
466
464
  return context;
467
465
  }
468
466
 
469
467
  /**
470
- * Validate that the data store had not been deleted by GC.
471
- *
468
+ * Returns the data store requested with the given id if available. Otherwise, returns undefined.
469
+ */
470
+ public async getDataStoreIfAvailable(
471
+ id: string,
472
+ requestHeaderData: RuntimeHeaderData,
473
+ ): Promise<FluidDataStoreContext | undefined> {
474
+ // If the data store has been deleted, return undefined.
475
+ if (this.checkIfDeleted(id, requestHeaderData)) {
476
+ return undefined;
477
+ }
478
+ const headerData = { ...defaultRuntimeHeaderData, ...requestHeaderData };
479
+ const context = await this.contexts.getBoundOrRemoted(id, headerData.wait);
480
+ if (context === undefined) {
481
+ return undefined;
482
+ }
483
+ // Check if the data store is tombstoned. If so, we want to log a telemetry event.
484
+ this.checkIfTombstoned(context, requestHeaderData);
485
+ return context;
486
+ }
487
+
488
+ /**
489
+ * Checks if the data store has been deleted by GC.
472
490
  * @param id - data store id
473
491
  * @param request - the request information to log if the validation detects the data store has been deleted
474
492
  * @param requestHeaderData - the request header information to log if the validation detects the data store has been deleted
493
+ * @returns true if the data store is deleted. Otherwise, returns false.
475
494
  */
476
- private validateNotDeleted(
477
- id: string,
478
- request: IRequest,
479
- requestHeaderData?: RuntimeHeaderData,
480
- ) {
495
+ private checkIfDeleted(id: string, requestHeaderData?: RuntimeHeaderData) {
481
496
  const dataStoreNodePath = `/${id}`;
482
- if (this.isDataStoreDeleted(dataStoreNodePath)) {
483
- assert(
484
- !this.contexts.has(id),
485
- 0x570 /* Inconsistent state! GC says the data store is deleted, but the data store is not deleted from the runtime. */,
486
- );
497
+ if (!this.isDataStoreDeleted(dataStoreNodePath)) {
498
+ return false;
499
+ }
500
+ assert(
501
+ !this.contexts.has(id),
502
+ 0x570 /* Inconsistent state! GC says the data store is deleted, but the data store is not deleted from the runtime. */,
503
+ );
504
+ sendGCUnexpectedUsageEvent(
505
+ this.mc,
506
+ {
507
+ eventName: "GC_Deleted_DataStore_Requested",
508
+ category: "error",
509
+ isSummarizerClient: this.runtime.clientDetails.type === summarizerClientType,
510
+ id,
511
+ headers: JSON.stringify(requestHeaderData),
512
+ gcTombstoneEnforcementAllowed: this.runtime.gcTombstoneEnforcementAllowed,
513
+ },
514
+ undefined /* packagePath */,
515
+ );
516
+ return true;
517
+ }
518
+
519
+ /**
520
+ * Validate that the data store had not been deleted by GC.
521
+ * @param id - data store id
522
+ * @param requestHeaderData - the request header information to log if the validation detects the data store has been deleted
523
+ */
524
+ private validateNotDeleted(id: string, requestHeaderData?: RuntimeHeaderData) {
525
+ if (this.checkIfDeleted(id, requestHeaderData)) {
487
526
  // The requested data store is removed by gc. Create a 404 gc response exception.
488
- const error = responseToException(
527
+ const request: IRequest = { url: id };
528
+ throw responseToException(
489
529
  createResponseError(404, "DataStore was deleted", request),
490
530
  request,
491
531
  );
492
- sendGCUnexpectedUsageEvent(
493
- this.mc,
494
- {
495
- eventName: "GC_Deleted_DataStore_Requested",
496
- category: "error",
497
- isSummarizerClient: this.runtime.clientDetails.type === summarizerClientType,
498
- headers: JSON.stringify(requestHeaderData),
499
- gcTombstoneEnforcementAllowed: this.runtime.gcTombstoneEnforcementAllowed,
500
- },
501
- undefined /** packagePath */,
502
- error,
503
- );
504
- throw error;
505
532
  }
506
533
  }
507
534
 
535
+ /**
536
+ * Checks if the data store has not been marked as tombstone by GC or not.
537
+ * @param context - the data store context in question
538
+ * @param requestHeaderData - the request header information to log if the validation detects the data store has been tombstoned
539
+ * @returns true if the data store is tombstoned. Otherwise, returns false.
540
+ */
541
+ private checkIfTombstoned(
542
+ context: FluidDataStoreContext,
543
+ requestHeaderData: RuntimeHeaderData,
544
+ ) {
545
+ if (!context.tombstoned) {
546
+ return false;
547
+ }
548
+ const logErrorEvent = this.throwOnTombstoneLoad && !requestHeaderData.allowTombstone;
549
+ sendGCUnexpectedUsageEvent(
550
+ this.mc,
551
+ {
552
+ eventName: "GC_Tombstone_DataStore_Requested",
553
+ category: logErrorEvent ? "error" : "generic",
554
+ isSummarizerClient: this.runtime.clientDetails.type === summarizerClientType,
555
+ id: context.id,
556
+ headers: JSON.stringify(requestHeaderData),
557
+ gcTombstoneEnforcementAllowed: this.runtime.gcTombstoneEnforcementAllowed,
558
+ },
559
+ context.isLoaded ? context.packagePath : undefined,
560
+ );
561
+ return true;
562
+ }
563
+
508
564
  /**
509
565
  * Validates that the data store context requested has not been marked as tombstone by GC.
510
- *
511
566
  * @param context - the data store context in question
512
567
  * @param request - the request information to log if the validation detects the data store has been tombstoned
513
- * @param headerData - the request header information to log if the validation detects the data store has been tombstoned
568
+ * @param requestHeaderData - the request header information to log if the validation detects the data store has been tombstoned
514
569
  */
515
570
  private validateNotTombstoned(
516
571
  context: FluidDataStoreContext,
517
- request: IRequest,
518
- headerData: RuntimeHeaderData,
572
+ requestHeaderData: RuntimeHeaderData,
519
573
  ) {
520
- if (context.tombstoned) {
521
- const shouldFail = this.throwOnTombstoneLoad && !headerData.allowTombstone;
522
-
574
+ if (this.checkIfTombstoned(context, requestHeaderData)) {
523
575
  // The requested data store is removed by gc. Create a 404 gc response exception.
576
+ const request: IRequest = { url: context.id };
524
577
  const error = responseToException(
525
578
  createResponseError(404, "DataStore was deleted", request, {
526
579
  [TombstoneResponseHeaderKey]: true,
527
580
  }),
528
581
  request,
529
582
  );
530
- sendGCUnexpectedUsageEvent(
531
- this.mc,
532
- {
533
- eventName: "GC_Tombstone_DataStore_Requested",
534
- category: shouldFail ? "error" : "generic",
535
- isSummarizerClient: this.runtime.clientDetails.type === summarizerClientType,
536
- headers: JSON.stringify(headerData),
537
- gcTombstoneEnforcementAllowed: this.runtime.gcTombstoneEnforcementAllowed,
538
- },
539
- context.isLoaded ? context.packagePath : undefined,
540
- error,
541
- );
542
-
543
- if (shouldFail) {
583
+ // Throw an error if configured via options and via request headers.
584
+ if (this.throwOnTombstoneLoad && !requestHeaderData.allowTombstone) {
544
585
  throw error;
545
586
  }
546
587
  }
547
588
  }
548
589
 
549
590
  public processSignal(fluidDataStoreId: string, message: IInboundSignalMessage, local: boolean) {
550
- const request = { url: fluidDataStoreId };
551
- this.validateNotDeleted(fluidDataStoreId, request);
591
+ this.validateNotDeleted(fluidDataStoreId);
552
592
  const context = this.contexts.get(fluidDataStoreId);
553
593
  if (!context) {
554
594
  // Attach message may not have been processed yet
@@ -0,0 +1,111 @@
1
+ /*!
2
+ * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
+ * Licensed under the MIT License.
4
+ */
5
+
6
+ import { EventForwarder } from "@fluidframework/common-utils";
7
+ import {
8
+ IDeltaManager,
9
+ IDeltaManagerEvents,
10
+ IDeltaQueue,
11
+ IDeltaSender,
12
+ ReadOnlyInfo,
13
+ } from "@fluidframework/container-definitions";
14
+ import {
15
+ IClientConfiguration,
16
+ IClientDetails,
17
+ IDocumentMessage,
18
+ ISequencedDocumentMessage,
19
+ ISignalMessage,
20
+ } from "@fluidframework/protocol-definitions";
21
+
22
+ /**
23
+ * Base class for creating proxy to the real delta manager. It implements all required methods on IDeltaManager and
24
+ * proxy implementations can override specific methods.
25
+ */
26
+ export class DeltaManagerProxyBase
27
+ extends EventForwarder<IDeltaManagerEvents>
28
+ implements IDeltaManager<ISequencedDocumentMessage, IDocumentMessage>
29
+ {
30
+ public get IDeltaSender(): IDeltaSender {
31
+ return this;
32
+ }
33
+
34
+ public get inbound(): IDeltaQueue<ISequencedDocumentMessage> {
35
+ return this.deltaManager.inbound;
36
+ }
37
+
38
+ public get outbound(): IDeltaQueue<IDocumentMessage[]> {
39
+ return this.deltaManager.outbound;
40
+ }
41
+
42
+ public get inboundSignal(): IDeltaQueue<ISignalMessage> {
43
+ return this.deltaManager.inboundSignal;
44
+ }
45
+
46
+ public get minimumSequenceNumber(): number {
47
+ return this.deltaManager.minimumSequenceNumber;
48
+ }
49
+
50
+ public get lastSequenceNumber(): number {
51
+ return this.deltaManager.lastSequenceNumber;
52
+ }
53
+
54
+ public get lastMessage() {
55
+ return this.deltaManager.lastMessage;
56
+ }
57
+
58
+ public get lastKnownSeqNumber() {
59
+ return this.deltaManager.lastKnownSeqNumber;
60
+ }
61
+
62
+ public get initialSequenceNumber(): number {
63
+ return this.deltaManager.initialSequenceNumber;
64
+ }
65
+
66
+ public get hasCheckpointSequenceNumber() {
67
+ return this.deltaManager.hasCheckpointSequenceNumber;
68
+ }
69
+
70
+ public get clientDetails(): IClientDetails {
71
+ return this.deltaManager.clientDetails;
72
+ }
73
+
74
+ public get version(): string {
75
+ return this.deltaManager.version;
76
+ }
77
+
78
+ public get maxMessageSize(): number {
79
+ return this.deltaManager.maxMessageSize;
80
+ }
81
+
82
+ public get serviceConfiguration(): IClientConfiguration | undefined {
83
+ return this.deltaManager.serviceConfiguration;
84
+ }
85
+
86
+ public get active(): boolean {
87
+ return this.deltaManager.active;
88
+ }
89
+
90
+ public get readOnlyInfo(): ReadOnlyInfo {
91
+ return this.deltaManager.readOnlyInfo;
92
+ }
93
+
94
+ constructor(
95
+ protected readonly deltaManager: IDeltaManager<ISequencedDocumentMessage, IDocumentMessage>,
96
+ ) {
97
+ super(deltaManager);
98
+ }
99
+
100
+ public dispose(): void {
101
+ super.dispose();
102
+ }
103
+
104
+ public submitSignal(content: any): void {
105
+ return this.deltaManager.submitSignal(content);
106
+ }
107
+
108
+ public flush(): void {
109
+ return this.deltaManager.flush();
110
+ }
111
+ }
@@ -4,8 +4,9 @@
4
4
  */
5
5
 
6
6
  import { IDeltaManager, ReadOnlyInfo } from "@fluidframework/container-definitions";
7
- import { DeltaManagerProxyBase } from "@fluidframework/container-utils";
8
7
  import { IDocumentMessage, ISequencedDocumentMessage } from "@fluidframework/protocol-definitions";
8
+
9
+ import { DeltaManagerProxyBase } from "./deltaManagerProxyBase";
9
10
  import { summarizerClientType } from "./summary";
10
11
 
11
12
  /**
@@ -5,7 +5,6 @@
5
5
 
6
6
  import { ITelemetryGenericEvent } from "@fluidframework/core-interfaces";
7
7
  import { IGarbageCollectionData } from "@fluidframework/runtime-definitions";
8
- import { packagePathToTelemetryProperty } from "@fluidframework/runtime-utils";
9
8
  import {
10
9
  generateStack,
11
10
  ITelemetryLoggerExt,
@@ -211,7 +210,7 @@ export class GCTelemetryTracker {
211
210
  const { id: taggedId, fromId: taggedFromId, ...otherProps } = eventProps;
212
211
  const event = {
213
212
  eventName: `${state}Object_${nodeUsageProps.usageType}`,
214
- pkg: packagePathToTelemetryProperty(nodeUsageProps.packagePath),
213
+ pkg: tagCodeArtifacts({ pkg: nodeUsageProps.packagePath?.join("/") }).pkg,
215
214
  stack: generateStack(),
216
215
  id: taggedId,
217
216
  fromId: taggedFromId,