@fluidframework/container-runtime 2.0.0-dev-rc.5.0.0.271262 → 2.0.0-dev-rc.5.0.0.272251

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 (212) hide show
  1. package/api-extractor/api-extractor-lint-bundle.json +5 -0
  2. package/api-extractor/api-extractor-lint-legacy.cjs.json +5 -0
  3. package/api-extractor/api-extractor-lint-legacy.esm.json +5 -0
  4. package/api-extractor/api-extractor-lint-public.cjs.json +5 -0
  5. package/api-extractor/api-extractor-lint-public.esm.json +5 -0
  6. package/api-report/container-runtime.alpha.api.md +1 -1
  7. package/container-runtime.test-files.tar +0 -0
  8. package/dist/batchTracker.js +1 -5
  9. package/dist/batchTracker.js.map +1 -1
  10. package/dist/blobManager.js +14 -39
  11. package/dist/blobManager.js.map +1 -1
  12. package/dist/channelCollection.d.ts +12 -2
  13. package/dist/channelCollection.d.ts.map +1 -1
  14. package/dist/channelCollection.js +95 -110
  15. package/dist/channelCollection.js.map +1 -1
  16. package/dist/connectionTelemetry.js +14 -32
  17. package/dist/connectionTelemetry.js.map +1 -1
  18. package/dist/containerHandleContext.js +0 -4
  19. package/dist/containerHandleContext.js.map +1 -1
  20. package/dist/containerRuntime.d.ts +2 -1
  21. package/dist/containerRuntime.d.ts.map +1 -1
  22. package/dist/containerRuntime.js +51 -142
  23. package/dist/containerRuntime.js.map +1 -1
  24. package/dist/dataStore.js +1 -9
  25. package/dist/dataStore.js.map +1 -1
  26. package/dist/dataStoreContext.d.ts +2 -1
  27. package/dist/dataStoreContext.d.ts.map +1 -1
  28. package/dist/dataStoreContext.js +102 -143
  29. package/dist/dataStoreContext.js.map +1 -1
  30. package/dist/dataStoreContexts.js +28 -29
  31. package/dist/dataStoreContexts.js.map +1 -1
  32. package/dist/dataStoreRegistry.js +0 -1
  33. package/dist/dataStoreRegistry.js.map +1 -1
  34. package/dist/deltaManagerProxies.js +28 -33
  35. package/dist/deltaManagerProxies.js.map +1 -1
  36. package/dist/deltaScheduler.js +9 -13
  37. package/dist/deltaScheduler.js.map +1 -1
  38. package/dist/error.js +1 -2
  39. package/dist/error.js.map +1 -1
  40. package/dist/gc/garbageCollection.d.ts +4 -2
  41. package/dist/gc/garbageCollection.d.ts.map +1 -1
  42. package/dist/gc/garbageCollection.js +25 -43
  43. package/dist/gc/garbageCollection.js.map +1 -1
  44. package/dist/gc/gcDefinitions.d.ts +7 -4
  45. package/dist/gc/gcDefinitions.d.ts.map +1 -1
  46. package/dist/gc/gcDefinitions.js.map +1 -1
  47. package/dist/gc/gcSummaryStateTracker.js +14 -19
  48. package/dist/gc/gcSummaryStateTracker.js.map +1 -1
  49. package/dist/gc/gcTelemetry.d.ts +1 -1
  50. package/dist/gc/gcTelemetry.d.ts.map +1 -1
  51. package/dist/gc/gcTelemetry.js +5 -17
  52. package/dist/gc/gcTelemetry.js.map +1 -1
  53. package/dist/gc/gcUnreferencedStateTracker.js +1 -12
  54. package/dist/gc/gcUnreferencedStateTracker.js.map +1 -1
  55. package/dist/opLifecycle/batchManager.js +3 -5
  56. package/dist/opLifecycle/batchManager.js.map +1 -1
  57. package/dist/opLifecycle/opCompressor.js +0 -1
  58. package/dist/opLifecycle/opCompressor.js.map +1 -1
  59. package/dist/opLifecycle/opDecompressor.js +4 -6
  60. package/dist/opLifecycle/opDecompressor.js.map +1 -1
  61. package/dist/opLifecycle/opGroupingManager.js +1 -3
  62. package/dist/opLifecycle/opGroupingManager.js.map +1 -1
  63. package/dist/opLifecycle/opSplitter.js +0 -6
  64. package/dist/opLifecycle/opSplitter.js.map +1 -1
  65. package/dist/opLifecycle/outbox.js +10 -15
  66. package/dist/opLifecycle/outbox.js.map +1 -1
  67. package/dist/opLifecycle/remoteMessageProcessor.js +0 -3
  68. package/dist/opLifecycle/remoteMessageProcessor.js.map +1 -1
  69. package/dist/packageVersion.d.ts +1 -1
  70. package/dist/packageVersion.js +1 -1
  71. package/dist/packageVersion.js.map +1 -1
  72. package/dist/pendingStateManager.js +14 -20
  73. package/dist/pendingStateManager.js.map +1 -1
  74. package/dist/scheduleManager.js +4 -15
  75. package/dist/scheduleManager.js.map +1 -1
  76. package/dist/storageServiceWithAttachBlobs.js +0 -1
  77. package/dist/storageServiceWithAttachBlobs.js.map +1 -1
  78. package/dist/summary/documentSchema.js +1 -17
  79. package/dist/summary/documentSchema.js.map +1 -1
  80. package/dist/summary/orderedClientElection.js +11 -19
  81. package/dist/summary/orderedClientElection.js.map +1 -1
  82. package/dist/summary/runWhileConnectedCoordinator.js +2 -4
  83. package/dist/summary/runWhileConnectedCoordinator.js.map +1 -1
  84. package/dist/summary/runningSummarizer.js +38 -56
  85. package/dist/summary/runningSummarizer.js.map +1 -1
  86. package/dist/summary/summarizer.js +8 -17
  87. package/dist/summary/summarizer.js.map +1 -1
  88. package/dist/summary/summarizerClientElection.js +7 -18
  89. package/dist/summary/summarizerClientElection.js.map +1 -1
  90. package/dist/summary/summarizerHeuristics.js +25 -30
  91. package/dist/summary/summarizerHeuristics.js.map +1 -1
  92. package/dist/summary/summarizerNode/summarizerNode.js +3 -12
  93. package/dist/summary/summarizerNode/summarizerNode.js.map +1 -1
  94. package/dist/summary/summarizerNode/summarizerNodeUtils.js +0 -2
  95. package/dist/summary/summarizerNode/summarizerNodeUtils.js.map +1 -1
  96. package/dist/summary/summarizerNode/summarizerNodeWithGc.js +6 -20
  97. package/dist/summary/summarizerNode/summarizerNodeWithGc.js.map +1 -1
  98. package/dist/summary/summaryCollection.js +11 -23
  99. package/dist/summary/summaryCollection.js.map +1 -1
  100. package/dist/summary/summaryGenerator.js +5 -12
  101. package/dist/summary/summaryGenerator.js.map +1 -1
  102. package/dist/summary/summaryManager.js +48 -58
  103. package/dist/summary/summaryManager.js.map +1 -1
  104. package/dist/throttler.js +1 -4
  105. package/dist/throttler.js.map +1 -1
  106. package/lib/batchTracker.js +1 -5
  107. package/lib/batchTracker.js.map +1 -1
  108. package/lib/blobManager.js +14 -39
  109. package/lib/blobManager.js.map +1 -1
  110. package/lib/channelCollection.d.ts +12 -2
  111. package/lib/channelCollection.d.ts.map +1 -1
  112. package/lib/channelCollection.js +95 -110
  113. package/lib/channelCollection.js.map +1 -1
  114. package/lib/connectionTelemetry.js +14 -32
  115. package/lib/connectionTelemetry.js.map +1 -1
  116. package/lib/containerHandleContext.js +0 -4
  117. package/lib/containerHandleContext.js.map +1 -1
  118. package/lib/containerRuntime.d.ts +2 -1
  119. package/lib/containerRuntime.d.ts.map +1 -1
  120. package/lib/containerRuntime.js +52 -143
  121. package/lib/containerRuntime.js.map +1 -1
  122. package/lib/dataStore.js +1 -9
  123. package/lib/dataStore.js.map +1 -1
  124. package/lib/dataStoreContext.d.ts +2 -1
  125. package/lib/dataStoreContext.d.ts.map +1 -1
  126. package/lib/dataStoreContext.js +102 -143
  127. package/lib/dataStoreContext.js.map +1 -1
  128. package/lib/dataStoreContexts.js +28 -29
  129. package/lib/dataStoreContexts.js.map +1 -1
  130. package/lib/dataStoreRegistry.js +0 -1
  131. package/lib/dataStoreRegistry.js.map +1 -1
  132. package/lib/deltaManagerProxies.js +28 -33
  133. package/lib/deltaManagerProxies.js.map +1 -1
  134. package/lib/deltaScheduler.js +9 -13
  135. package/lib/deltaScheduler.js.map +1 -1
  136. package/lib/error.js +1 -2
  137. package/lib/error.js.map +1 -1
  138. package/lib/gc/garbageCollection.d.ts +4 -2
  139. package/lib/gc/garbageCollection.d.ts.map +1 -1
  140. package/lib/gc/garbageCollection.js +25 -43
  141. package/lib/gc/garbageCollection.js.map +1 -1
  142. package/lib/gc/gcDefinitions.d.ts +7 -4
  143. package/lib/gc/gcDefinitions.d.ts.map +1 -1
  144. package/lib/gc/gcDefinitions.js.map +1 -1
  145. package/lib/gc/gcSummaryStateTracker.js +14 -19
  146. package/lib/gc/gcSummaryStateTracker.js.map +1 -1
  147. package/lib/gc/gcTelemetry.d.ts +1 -1
  148. package/lib/gc/gcTelemetry.d.ts.map +1 -1
  149. package/lib/gc/gcTelemetry.js +5 -17
  150. package/lib/gc/gcTelemetry.js.map +1 -1
  151. package/lib/gc/gcUnreferencedStateTracker.js +1 -12
  152. package/lib/gc/gcUnreferencedStateTracker.js.map +1 -1
  153. package/lib/opLifecycle/batchManager.js +3 -5
  154. package/lib/opLifecycle/batchManager.js.map +1 -1
  155. package/lib/opLifecycle/opCompressor.js +0 -1
  156. package/lib/opLifecycle/opCompressor.js.map +1 -1
  157. package/lib/opLifecycle/opDecompressor.js +4 -6
  158. package/lib/opLifecycle/opDecompressor.js.map +1 -1
  159. package/lib/opLifecycle/opGroupingManager.js +1 -3
  160. package/lib/opLifecycle/opGroupingManager.js.map +1 -1
  161. package/lib/opLifecycle/opSplitter.js +0 -6
  162. package/lib/opLifecycle/opSplitter.js.map +1 -1
  163. package/lib/opLifecycle/outbox.js +10 -15
  164. package/lib/opLifecycle/outbox.js.map +1 -1
  165. package/lib/opLifecycle/remoteMessageProcessor.js +0 -3
  166. package/lib/opLifecycle/remoteMessageProcessor.js.map +1 -1
  167. package/lib/packageVersion.d.ts +1 -1
  168. package/lib/packageVersion.js +1 -1
  169. package/lib/packageVersion.js.map +1 -1
  170. package/lib/pendingStateManager.js +14 -20
  171. package/lib/pendingStateManager.js.map +1 -1
  172. package/lib/scheduleManager.js +4 -15
  173. package/lib/scheduleManager.js.map +1 -1
  174. package/lib/storageServiceWithAttachBlobs.js +0 -1
  175. package/lib/storageServiceWithAttachBlobs.js.map +1 -1
  176. package/lib/summary/documentSchema.js +1 -17
  177. package/lib/summary/documentSchema.js.map +1 -1
  178. package/lib/summary/orderedClientElection.js +11 -19
  179. package/lib/summary/orderedClientElection.js.map +1 -1
  180. package/lib/summary/runWhileConnectedCoordinator.js +2 -4
  181. package/lib/summary/runWhileConnectedCoordinator.js.map +1 -1
  182. package/lib/summary/runningSummarizer.js +38 -56
  183. package/lib/summary/runningSummarizer.js.map +1 -1
  184. package/lib/summary/summarizer.js +8 -17
  185. package/lib/summary/summarizer.js.map +1 -1
  186. package/lib/summary/summarizerClientElection.js +7 -18
  187. package/lib/summary/summarizerClientElection.js.map +1 -1
  188. package/lib/summary/summarizerHeuristics.js +25 -30
  189. package/lib/summary/summarizerHeuristics.js.map +1 -1
  190. package/lib/summary/summarizerNode/summarizerNode.js +3 -12
  191. package/lib/summary/summarizerNode/summarizerNode.js.map +1 -1
  192. package/lib/summary/summarizerNode/summarizerNodeUtils.js +0 -2
  193. package/lib/summary/summarizerNode/summarizerNodeUtils.js.map +1 -1
  194. package/lib/summary/summarizerNode/summarizerNodeWithGc.js +6 -20
  195. package/lib/summary/summarizerNode/summarizerNodeWithGc.js.map +1 -1
  196. package/lib/summary/summaryCollection.js +11 -23
  197. package/lib/summary/summaryCollection.js.map +1 -1
  198. package/lib/summary/summaryGenerator.js +5 -12
  199. package/lib/summary/summaryGenerator.js.map +1 -1
  200. package/lib/summary/summaryManager.js +48 -58
  201. package/lib/summary/summaryManager.js.map +1 -1
  202. package/lib/throttler.js +1 -4
  203. package/lib/throttler.js.map +1 -1
  204. package/package.json +27 -18
  205. package/src/channelCollection.ts +133 -123
  206. package/src/containerRuntime.ts +31 -4
  207. package/src/dataStoreContext.ts +3 -2
  208. package/src/gc/garbageCollection.ts +24 -7
  209. package/src/gc/gcDefinitions.ts +16 -4
  210. package/src/gc/gcTelemetry.ts +1 -7
  211. package/src/packageVersion.ts +1 -1
  212. package/tsdoc.json +4 -0
@@ -158,28 +158,21 @@ exports.getLocalDataStoreType = getLocalDataStoreType;
158
158
  * @internal
159
159
  */
160
160
  class ChannelCollection {
161
- baseSnapshot;
162
- parentContext;
163
- gcNodeUpdated;
164
- isDataStoreDeleted;
165
- aliasMap;
166
- // Stores tracked by the Domain
167
- pendingAttach = new Map();
168
- // 0.24 back-compat attachingBeforeSummary
169
- attachOpFiredForDataStore = new Set();
170
- mc;
171
- disposeOnce = new internal_1.Lazy(() => this.contexts.dispose());
172
- entryPoint;
173
- containerLoadStats;
174
- pendingAliasMap = new Map();
175
- contexts;
176
- aliasedDataStores;
177
161
  constructor(baseSnapshot, parentContext, baseLogger, gcNodeUpdated, isDataStoreDeleted, aliasMap, provideEntryPoint) {
178
162
  this.baseSnapshot = baseSnapshot;
179
163
  this.parentContext = parentContext;
180
164
  this.gcNodeUpdated = gcNodeUpdated;
181
165
  this.isDataStoreDeleted = isDataStoreDeleted;
182
166
  this.aliasMap = aliasMap;
167
+ // Stores tracked by the Domain
168
+ this.pendingAttach = new Map();
169
+ // 0.24 back-compat attachingBeforeSummary
170
+ this.attachOpFiredForDataStore = new Set();
171
+ this.disposeOnce = new internal_1.Lazy(() => this.contexts.dispose());
172
+ this.pendingAliasMap = new Map();
173
+ /** For sampling. Only log once per container */
174
+ this.shouldSendAttachLog = true;
175
+ this.dispose = () => this.disposeOnce.value;
183
176
  this.mc = (0, internal_6.createChildMonitoringContext)({ logger: baseLogger });
184
177
  this.contexts = new dataStoreContexts_js_1.DataStoreContexts(baseLogger);
185
178
  this.entryPoint = new internal_2.FluidObjectHandle(new internal_1.LazyPromise(async () => provideEntryPoint(this)), "", this.parentContext.IFluidHandleContext);
@@ -256,8 +249,6 @@ class ChannelCollection {
256
249
  const pendingAliasPromise = this.pendingAliases.get(maybeAlias);
257
250
  return pendingAliasPromise ?? "Success";
258
251
  }
259
- /** For sampling. Only log once per container */
260
- shouldSendAttachLog = true;
261
252
  wrapContextForInnerChannel(id) {
262
253
  return wrapContextForInnerChannel(id, this.parentContext);
263
254
  }
@@ -275,7 +266,7 @@ class ChannelCollection {
275
266
  const foundGCData = (0, internal_5.processAttachMessageGCData)(attachMessage.snapshot, (nodeId, toPath) => {
276
267
  // nodeId is the relative path under the node being attached. Always starts with "/", but no trailing "/" after an id
277
268
  const fromPath = `/${attachMessage.id}${nodeId === "/" ? "" : nodeId}`;
278
- this.parentContext.addedGCOutboundRoute(fromPath, toPath);
269
+ this.parentContext.addedGCOutboundRoute(fromPath, toPath, message.timestamp);
279
270
  });
280
271
  // Only log once per container to avoid noise/cost.
281
272
  // Allows longitudinal tracking of various state (e.g. foundGCData), and some sampled details
@@ -347,12 +338,12 @@ class ChannelCollection {
347
338
  });
348
339
  }
349
340
  const resolve = localOpMetadata;
350
- const aliasResult = this.processAliasMessageCore(aliasMessage.internalId, aliasMessage.alias);
341
+ const aliasResult = this.processAliasMessageCore(aliasMessage.internalId, aliasMessage.alias, message.timestamp);
351
342
  if (local) {
352
343
  resolve(aliasResult);
353
344
  }
354
345
  }
355
- processAliasMessageCore(internalId, alias) {
346
+ processAliasMessageCore(internalId, alias, messageTimestampMs) {
356
347
  if (this.alreadyProcessed(alias)) {
357
348
  return false;
358
349
  }
@@ -369,7 +360,11 @@ class ChannelCollection {
369
360
  });
370
361
  return false;
371
362
  }
372
- this.parentContext.addedGCOutboundRoute("/", `/${internalId}`);
363
+ // If message timestamp doesn't exist, this is called in a detached container. Don't notify GC in that case
364
+ // because it doesn't run in detached container and doesn't need to know about this route.
365
+ if (messageTimestampMs) {
366
+ this.parentContext.addedGCOutboundRoute("/", `/${internalId}`, messageTimestampMs);
367
+ }
373
368
  this.aliasMap.set(alias, context.id);
374
369
  this.aliasedDataStores.add(context.id);
375
370
  context.setInMemoryRoot();
@@ -480,7 +475,6 @@ class ChannelCollection {
480
475
  get disposed() {
481
476
  return this.disposeOnce.evaluated;
482
477
  }
483
- dispose = () => this.disposeOnce.value;
484
478
  reSubmit(type, content, localOpMetadata) {
485
479
  switch (type) {
486
480
  case messageTypes_js_1.ContainerMessageType.Attach:
@@ -603,7 +597,7 @@ class ChannelCollection {
603
597
  };
604
598
  this.processChannelOp(envelope.address, transformed, local, localMessageMetadata);
605
599
  // Notify GC of any outbound references that were added by this op.
606
- detectOutboundReferences(envelope.address, transformed.contents, (fromPath, toPath) => this.parentContext.addedGCOutboundRoute(fromPath, toPath));
600
+ detectOutboundReferences(envelope.address, transformed.contents, (fromPath, toPath) => this.parentContext.addedGCOutboundRoute(fromPath, toPath, message.timestamp));
607
601
  break;
608
602
  }
609
603
  default:
@@ -776,61 +770,24 @@ class ChannelCollection {
776
770
  get size() {
777
771
  return this.contexts.size;
778
772
  }
779
- async summarize(fullTree, trackState, telemetryContext) {
780
- const summaryBuilder = new internal_5.SummaryTreeBuilder();
781
- // Iterate over each store and ask it to snapshot
782
- await Promise.all(Array.from(this.contexts)
783
- .filter(([_, context]) => {
784
- // Summarizer works only with clients with no local changes. A data store in attaching
785
- // state indicates an op was sent to attach a local data store, and the the attach op
786
- // had not yet round tripped back to the client.
787
- if (context.attachState === container_definitions_1.AttachState.Attaching) {
788
- // Formerly assert 0x588
789
- const error = internal_6.DataProcessingError.create("Local data store detected in attaching state during summarize", "summarize");
790
- throw error;
791
- }
792
- return context.attachState === container_definitions_1.AttachState.Attached;
793
- })
794
- .map(async ([contextId, context]) => {
795
- const contextSummary = await context.summarize(fullTree, trackState, telemetryContext);
796
- summaryBuilder.addWithStats(contextId, contextSummary);
797
- }));
798
- return summaryBuilder.getSummaryTree();
799
- }
800
773
  /**
801
774
  * Create a summary. Used when attaching or serializing a detached container.
802
775
  */
803
776
  getAttachSummary(telemetryContext) {
804
777
  const builder = new internal_5.SummaryTreeBuilder();
805
- // Attaching graph of some stores can cause other stores to get bound too.
806
- // So keep taking summary until no new stores get bound.
807
- let notBoundContextsLength;
808
- do {
809
- const builderTree = builder.summary.tree;
810
- notBoundContextsLength = this.contexts.notBoundLength();
811
- // Iterate over each data store and ask it to snapshot
812
- Array.from(this.contexts)
813
- .filter(([key, _]) =>
814
- // Take summary of bounded data stores only, make sure we haven't summarized them already
815
- // and no attach op has been fired for that data store because for loader versions <= 0.24
816
- // we set attach state as "attaching" before taking createNew summary.
817
- !(this.contexts.isNotBound(key) ||
818
- builderTree[key] ||
819
- this.attachOpFiredForDataStore.has(key)))
820
- .map(([key, value]) => {
821
- let dataStoreSummary;
822
- if (value.isLoaded) {
823
- dataStoreSummary = value.getAttachSummary(telemetryContext);
824
- }
825
- else {
826
- // If this data store is not yet loaded, then there should be no changes in the snapshot from
827
- // which it was created as it is detached container. So just use the previous snapshot.
828
- (0, internal_1.assert)(!!this.baseSnapshot, 0x166 /* "BaseSnapshot should be there as detached container loaded from snapshot" */);
829
- dataStoreSummary = (0, internal_5.convertSnapshotTreeToSummaryTree)((0, internal_3.getSnapshotTree)(this.baseSnapshot).trees[key]);
830
- }
831
- builder.addWithStats(key, dataStoreSummary);
832
- });
833
- } while (notBoundContextsLength !== this.contexts.notBoundLength());
778
+ this.visitLocalBoundContextsDuringAttach((contextId, context) => {
779
+ let dataStoreSummary;
780
+ if (context.isLoaded) {
781
+ dataStoreSummary = context.getAttachSummary(telemetryContext);
782
+ }
783
+ else {
784
+ // If this data store is not yet loaded, then there should be no changes in the snapshot from
785
+ // which it was created as it is detached container. So just use the previous snapshot.
786
+ (0, internal_1.assert)(!!this.baseSnapshot, 0x166 /* "BaseSnapshot should be there as detached container loaded from snapshot" */);
787
+ dataStoreSummary = (0, internal_5.convertSnapshotTreeToSummaryTree)((0, internal_3.getSnapshotTree)(this.baseSnapshot).trees[contextId]);
788
+ }
789
+ builder.addWithStats(contextId, dataStoreSummary);
790
+ });
834
791
  return builder.getSummaryTree();
835
792
  }
836
793
  /**
@@ -838,27 +795,70 @@ class ChannelCollection {
838
795
  */
839
796
  getAttachGCData(telemetryContext) {
840
797
  const builder = new internal_5.GCDataBuilder();
841
- // Attaching graph of some stores can cause other stores to get bound too.
842
- // So keep taking summary until no new stores get bound.
843
- let notBoundContextsLength;
844
- do {
845
- notBoundContextsLength = this.contexts.notBoundLength();
846
- // Iterate over each data store and ask for its GC data.
847
- Array.from(this.contexts)
848
- .filter(([key, _]) =>
849
- // Take GC data of bounded data stores only.
850
- !this.contexts.isNotBound(key))
851
- .map(([key, value]) => {
852
- const contextGCData = value.getAttachGCData(telemetryContext);
853
- // Prefix the child's id to the ids of its GC nodes so they can be identified as belonging to the child.
854
- // This also gradually builds the id of each node to be a path from the root.
855
- builder.prefixAndAddNodes(key, contextGCData.gcNodes);
856
- });
857
- } while (notBoundContextsLength !== this.contexts.notBoundLength());
798
+ this.visitLocalBoundContextsDuringAttach((contextId, context) => {
799
+ const contextGCData = context.getAttachGCData(telemetryContext);
800
+ // Prefix the child's id to the ids of its GC nodes so they can be identified as belonging to the child.
801
+ // This also gradually builds the id of each node to be a path from the root.
802
+ builder.prefixAndAddNodes(contextId, contextGCData.gcNodes);
803
+ });
858
804
  // Get the outbound routes (aliased data stores) and add a GC node for this channel.
859
805
  builder.addNode("/", Array.from(this.aliasedDataStores));
860
806
  return builder.getGCData();
861
807
  }
808
+ /**
809
+ * Helper method for preparing to attach this channel.
810
+ * Runs the callback for each bound context to incorporate its data however the caller specifies
811
+ */
812
+ visitLocalBoundContextsDuringAttach(visitor) {
813
+ const visitedContexts = new Set();
814
+ let visitedLength = -1;
815
+ let notBoundContextsLength = -1;
816
+ while (visitedLength !== visitedContexts.size &&
817
+ notBoundContextsLength !== this.contexts.notBoundLength()) {
818
+ // detect changes in the visitedContexts set, as on visiting a context
819
+ // it could could make contexts available by removing other contexts
820
+ // from the not bound context list, so we need to ensure those get processed as well.
821
+ // only once the loop can run with no new contexts added to the visitedContexts set do we
822
+ // know for sure all possible contexts have been visited.
823
+ visitedLength = visitedContexts.size;
824
+ notBoundContextsLength = this.contexts.notBoundLength();
825
+ for (const [contextId, context] of this.contexts) {
826
+ if (!(visitedContexts.has(contextId) ||
827
+ this.contexts.isNotBound(contextId) ||
828
+ this.attachOpFiredForDataStore.has(contextId))) {
829
+ visitor(contextId, context);
830
+ visitedContexts.add(contextId);
831
+ }
832
+ }
833
+ }
834
+ }
835
+ /**
836
+ * Helper method for preparing to summarize this channel.
837
+ * Runs the callback for each bound context to incorporate its data however the caller specifies
838
+ */
839
+ async visitContextsDuringSummary(visitor) {
840
+ for (const [contextId, context] of this.contexts) {
841
+ // Summarizer client and hence GC works only with clients with no local changes. A data store in
842
+ // attaching state indicates an op was sent to attach a local data store, and the the attach op
843
+ // had not yet round tripped back to the client.
844
+ // Formerly assert 0x589
845
+ if (context.attachState === container_definitions_1.AttachState.Attaching) {
846
+ const error = internal_6.DataProcessingError.create("Local data store detected in attaching state", "summarize/getGCData");
847
+ throw error;
848
+ }
849
+ if (context.attachState === container_definitions_1.AttachState.Attached) {
850
+ await visitor(contextId, context);
851
+ }
852
+ }
853
+ }
854
+ async summarize(fullTree, trackState, telemetryContext) {
855
+ const summaryBuilder = new internal_5.SummaryTreeBuilder();
856
+ await this.visitContextsDuringSummary(async (contextId, context) => {
857
+ const contextSummary = await context.summarize(fullTree, trackState, telemetryContext);
858
+ summaryBuilder.addWithStats(contextId, contextSummary);
859
+ });
860
+ return summaryBuilder.getSummaryTree();
861
+ }
862
862
  /**
863
863
  * Generates data used for garbage collection. It does the following:
864
864
  *
@@ -874,25 +874,12 @@ class ChannelCollection {
874
874
  */
875
875
  async getGCData(fullGC = false) {
876
876
  const builder = new internal_5.GCDataBuilder();
877
- // Iterate over each store and get their GC data.
878
- await Promise.all(Array.from(this.contexts)
879
- .filter(([_, context]) => {
880
- // Summarizer client and hence GC works only with clients with no local changes. A data store in
881
- // attaching state indicates an op was sent to attach a local data store, and the the attach op
882
- // had not yet round tripped back to the client.
883
- // Formerly assert 0x589
884
- if (context.attachState === container_definitions_1.AttachState.Attaching) {
885
- const error = internal_6.DataProcessingError.create("Local data store detected in attaching state while running GC", "getGCData");
886
- throw error;
887
- }
888
- return context.attachState === container_definitions_1.AttachState.Attached;
889
- })
890
- .map(async ([contextId, context]) => {
877
+ await this.visitContextsDuringSummary(async (contextId, context) => {
891
878
  const contextGCData = await context.getGCData(fullGC);
892
879
  // Prefix the child's id to the ids of its GC nodes so they can be identified as belonging to the child.
893
880
  // This also gradually builds the id of each node to be a path from the root.
894
881
  builder.prefixAndAddNodes(contextId, contextGCData.gcNodes);
895
- }));
882
+ });
896
883
  // Get the outbound routes and add a GC node for this channel.
897
884
  builder.addNode("/", await this.getOutboundRoutes());
898
885
  return builder.getGCData();
@@ -1069,6 +1056,7 @@ class ChannelCollection {
1069
1056
  packagePath: details.pkg,
1070
1057
  request,
1071
1058
  headerData,
1059
+ timestampMs: undefined, // This will be added by the parent context if needed.
1072
1060
  });
1073
1061
  const dataStore = await dataStoreContext.realize();
1074
1062
  const subRequest = requestParser.createSubRequest(1);
@@ -1138,15 +1126,12 @@ function detectOutboundReferences(address, contents, addedOutboundReference) {
1138
1126
  exports.detectOutboundReferences = detectOutboundReferences;
1139
1127
  /** @internal */
1140
1128
  class ChannelCollectionFactory {
1141
- provideEntryPoint;
1142
- ctor;
1143
- type = "ChannelCollectionChannel";
1144
- IFluidDataStoreRegistry;
1145
1129
  constructor(registryEntries,
1146
1130
  // ADO:7302 We need a better type here
1147
1131
  provideEntryPoint, ctor) {
1148
1132
  this.provideEntryPoint = provideEntryPoint;
1149
1133
  this.ctor = ctor;
1134
+ this.type = "ChannelCollectionChannel";
1150
1135
  this.IFluidDataStoreRegistry = new dataStoreRegistry_js_1.FluidDataStoreRegistry(registryEntries);
1151
1136
  }
1152
1137
  get IFluidDataStoreFactory() {