@fluidframework/container-runtime 2.0.0-dev-rc.3.0.0.254674 → 2.0.0-dev-rc.4.0.0.261659

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 (293) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/api-report/container-runtime.api.md +33 -19
  3. package/dist/batchTracker.d.ts +1 -1
  4. package/dist/batchTracker.d.ts.map +1 -1
  5. package/dist/batchTracker.js.map +1 -1
  6. package/dist/channelCollection.d.ts +5 -3
  7. package/dist/channelCollection.d.ts.map +1 -1
  8. package/dist/channelCollection.js +67 -15
  9. package/dist/channelCollection.js.map +1 -1
  10. package/dist/connectionTelemetry.d.ts +1 -1
  11. package/dist/connectionTelemetry.d.ts.map +1 -1
  12. package/dist/connectionTelemetry.js +54 -5
  13. package/dist/connectionTelemetry.js.map +1 -1
  14. package/dist/containerRuntime.d.ts +17 -27
  15. package/dist/containerRuntime.d.ts.map +1 -1
  16. package/dist/containerRuntime.js +174 -143
  17. package/dist/containerRuntime.js.map +1 -1
  18. package/dist/dataStore.d.ts +1 -1
  19. package/dist/dataStore.d.ts.map +1 -1
  20. package/dist/dataStore.js.map +1 -1
  21. package/dist/dataStoreContext.d.ts.map +1 -1
  22. package/dist/dataStoreContext.js +1 -0
  23. package/dist/dataStoreContext.js.map +1 -1
  24. package/dist/dataStoreContexts.d.ts +2 -0
  25. package/dist/dataStoreContexts.d.ts.map +1 -1
  26. package/dist/dataStoreContexts.js +7 -0
  27. package/dist/dataStoreContexts.js.map +1 -1
  28. package/dist/deltaManagerSummarizerProxy.d.ts +18 -6
  29. package/dist/deltaManagerSummarizerProxy.d.ts.map +1 -1
  30. package/dist/deltaManagerSummarizerProxy.js +38 -19
  31. package/dist/deltaManagerSummarizerProxy.js.map +1 -1
  32. package/dist/deltaScheduler.d.ts +1 -1
  33. package/dist/deltaScheduler.d.ts.map +1 -1
  34. package/dist/deltaScheduler.js.map +1 -1
  35. package/dist/gc/garbageCollection.d.ts +5 -12
  36. package/dist/gc/garbageCollection.d.ts.map +1 -1
  37. package/dist/gc/garbageCollection.js +45 -29
  38. package/dist/gc/garbageCollection.js.map +1 -1
  39. package/dist/gc/gcDefinitions.d.ts +27 -6
  40. package/dist/gc/gcDefinitions.d.ts.map +1 -1
  41. package/dist/gc/gcDefinitions.js.map +1 -1
  42. package/dist/gc/gcHelpers.d.ts +5 -4
  43. package/dist/gc/gcHelpers.d.ts.map +1 -1
  44. package/dist/gc/gcHelpers.js +14 -2
  45. package/dist/gc/gcHelpers.js.map +1 -1
  46. package/dist/gc/gcTelemetry.d.ts +14 -4
  47. package/dist/gc/gcTelemetry.d.ts.map +1 -1
  48. package/dist/gc/gcTelemetry.js +24 -21
  49. package/dist/gc/gcTelemetry.js.map +1 -1
  50. package/dist/gc/index.d.ts +2 -2
  51. package/dist/gc/index.d.ts.map +1 -1
  52. package/dist/gc/index.js +2 -2
  53. package/dist/gc/index.js.map +1 -1
  54. package/dist/index.d.ts +2 -2
  55. package/dist/index.d.ts.map +1 -1
  56. package/dist/index.js +2 -1
  57. package/dist/index.js.map +1 -1
  58. package/dist/{alpha.d.ts → legacy.d.ts} +3 -1
  59. package/dist/metadata.d.ts +2 -2
  60. package/dist/metadata.d.ts.map +1 -1
  61. package/dist/metadata.js.map +1 -1
  62. package/dist/opLifecycle/batchManager.d.ts +0 -1
  63. package/dist/opLifecycle/batchManager.d.ts.map +1 -1
  64. package/dist/opLifecycle/batchManager.js +0 -10
  65. package/dist/opLifecycle/batchManager.js.map +1 -1
  66. package/dist/opLifecycle/opDecompressor.d.ts.map +1 -1
  67. package/dist/opLifecycle/opDecompressor.js +6 -6
  68. package/dist/opLifecycle/opDecompressor.js.map +1 -1
  69. package/dist/opLifecycle/opGroupingManager.js +2 -2
  70. package/dist/opLifecycle/opGroupingManager.js.map +1 -1
  71. package/dist/opLifecycle/opSplitter.js +1 -1
  72. package/dist/opLifecycle/opSplitter.js.map +1 -1
  73. package/dist/opLifecycle/outbox.d.ts +0 -4
  74. package/dist/opLifecycle/outbox.d.ts.map +1 -1
  75. package/dist/opLifecycle/outbox.js +2 -34
  76. package/dist/opLifecycle/outbox.js.map +1 -1
  77. package/dist/packageVersion.d.ts +1 -1
  78. package/dist/packageVersion.js +1 -1
  79. package/dist/packageVersion.js.map +1 -1
  80. package/dist/pendingStateManager.d.ts +3 -2
  81. package/dist/pendingStateManager.d.ts.map +1 -1
  82. package/dist/pendingStateManager.js +17 -10
  83. package/dist/pendingStateManager.js.map +1 -1
  84. package/dist/public.d.ts +3 -0
  85. package/dist/scheduleManager.d.ts +1 -1
  86. package/dist/scheduleManager.d.ts.map +1 -1
  87. package/dist/scheduleManager.js.map +1 -1
  88. package/dist/summary/documentSchema.d.ts +3 -1
  89. package/dist/summary/documentSchema.d.ts.map +1 -1
  90. package/dist/summary/documentSchema.js +34 -16
  91. package/dist/summary/documentSchema.js.map +1 -1
  92. package/dist/summary/orderedClientElection.d.ts +1 -1
  93. package/dist/summary/orderedClientElection.d.ts.map +1 -1
  94. package/dist/summary/orderedClientElection.js.map +1 -1
  95. package/dist/summary/summarizer.d.ts +1 -2
  96. package/dist/summary/summarizer.d.ts.map +1 -1
  97. package/dist/summary/summarizer.js.map +1 -1
  98. package/dist/summary/summarizerClientElection.d.ts +1 -1
  99. package/dist/summary/summarizerClientElection.d.ts.map +1 -1
  100. package/dist/summary/summarizerClientElection.js.map +1 -1
  101. package/dist/summary/summarizerHeuristics.d.ts +1 -1
  102. package/dist/summary/summarizerHeuristics.d.ts.map +1 -1
  103. package/dist/summary/summarizerHeuristics.js.map +1 -1
  104. package/dist/summary/summarizerNode/summarizerNode.d.ts +4 -3
  105. package/dist/summary/summarizerNode/summarizerNode.d.ts.map +1 -1
  106. package/dist/summary/summarizerNode/summarizerNode.js +4 -10
  107. package/dist/summary/summarizerNode/summarizerNode.js.map +1 -1
  108. package/dist/summary/summarizerNode/summarizerNodeUtils.d.ts +2 -3
  109. package/dist/summary/summarizerNode/summarizerNodeUtils.d.ts.map +1 -1
  110. package/dist/summary/summarizerNode/summarizerNodeUtils.js.map +1 -1
  111. package/dist/summary/summarizerNode/summarizerNodeWithGc.d.ts +1 -2
  112. package/dist/summary/summarizerNode/summarizerNodeWithGc.d.ts.map +1 -1
  113. package/dist/summary/summarizerNode/summarizerNodeWithGc.js +2 -9
  114. package/dist/summary/summarizerNode/summarizerNodeWithGc.js.map +1 -1
  115. package/dist/summary/summarizerTypes.d.ts +2 -3
  116. package/dist/summary/summarizerTypes.d.ts.map +1 -1
  117. package/dist/summary/summarizerTypes.js.map +1 -1
  118. package/dist/summary/summaryCollection.d.ts +1 -1
  119. package/dist/summary/summaryCollection.d.ts.map +1 -1
  120. package/dist/summary/summaryCollection.js.map +1 -1
  121. package/dist/summary/summaryGenerator.d.ts +1 -2
  122. package/dist/summary/summaryGenerator.d.ts.map +1 -1
  123. package/dist/summary/summaryGenerator.js +3 -2
  124. package/dist/summary/summaryGenerator.js.map +1 -1
  125. package/dist/summary/summaryManager.d.ts.map +1 -1
  126. package/dist/summary/summaryManager.js.map +1 -1
  127. package/{dist/beta.d.ts → internal.d.ts} +2 -0
  128. package/{lib/beta.d.ts → legacy.d.ts} +2 -0
  129. package/lib/batchTracker.d.ts +1 -1
  130. package/lib/batchTracker.d.ts.map +1 -1
  131. package/lib/batchTracker.js.map +1 -1
  132. package/lib/channelCollection.d.ts +5 -3
  133. package/lib/channelCollection.d.ts.map +1 -1
  134. package/lib/channelCollection.js +69 -17
  135. package/lib/channelCollection.js.map +1 -1
  136. package/lib/connectionTelemetry.d.ts +1 -1
  137. package/lib/connectionTelemetry.d.ts.map +1 -1
  138. package/lib/connectionTelemetry.js +49 -0
  139. package/lib/connectionTelemetry.js.map +1 -1
  140. package/lib/containerRuntime.d.ts +17 -27
  141. package/lib/containerRuntime.d.ts.map +1 -1
  142. package/lib/containerRuntime.js +174 -143
  143. package/lib/containerRuntime.js.map +1 -1
  144. package/lib/dataStore.d.ts +1 -1
  145. package/lib/dataStore.d.ts.map +1 -1
  146. package/lib/dataStore.js +1 -1
  147. package/lib/dataStore.js.map +1 -1
  148. package/lib/dataStoreContext.d.ts.map +1 -1
  149. package/lib/dataStoreContext.js +1 -0
  150. package/lib/dataStoreContext.js.map +1 -1
  151. package/lib/dataStoreContexts.d.ts +2 -0
  152. package/lib/dataStoreContexts.d.ts.map +1 -1
  153. package/lib/dataStoreContexts.js +7 -0
  154. package/lib/dataStoreContexts.js.map +1 -1
  155. package/lib/deltaManagerSummarizerProxy.d.ts +18 -6
  156. package/lib/deltaManagerSummarizerProxy.d.ts.map +1 -1
  157. package/lib/deltaManagerSummarizerProxy.js +36 -18
  158. package/lib/deltaManagerSummarizerProxy.js.map +1 -1
  159. package/lib/deltaScheduler.d.ts +1 -1
  160. package/lib/deltaScheduler.d.ts.map +1 -1
  161. package/lib/deltaScheduler.js.map +1 -1
  162. package/lib/gc/garbageCollection.d.ts +5 -12
  163. package/lib/gc/garbageCollection.d.ts.map +1 -1
  164. package/lib/gc/garbageCollection.js +47 -31
  165. package/lib/gc/garbageCollection.js.map +1 -1
  166. package/lib/gc/gcDefinitions.d.ts +27 -6
  167. package/lib/gc/gcDefinitions.d.ts.map +1 -1
  168. package/lib/gc/gcDefinitions.js.map +1 -1
  169. package/lib/gc/gcHelpers.d.ts +5 -4
  170. package/lib/gc/gcHelpers.d.ts.map +1 -1
  171. package/lib/gc/gcHelpers.js +12 -1
  172. package/lib/gc/gcHelpers.js.map +1 -1
  173. package/lib/gc/gcTelemetry.d.ts +14 -4
  174. package/lib/gc/gcTelemetry.d.ts.map +1 -1
  175. package/lib/gc/gcTelemetry.js +24 -21
  176. package/lib/gc/gcTelemetry.js.map +1 -1
  177. package/lib/gc/index.d.ts +2 -2
  178. package/lib/gc/index.d.ts.map +1 -1
  179. package/lib/gc/index.js +1 -1
  180. package/lib/gc/index.js.map +1 -1
  181. package/lib/index.d.ts +2 -2
  182. package/lib/index.d.ts.map +1 -1
  183. package/lib/index.js +1 -1
  184. package/lib/index.js.map +1 -1
  185. package/lib/{alpha.d.ts → legacy.d.ts} +3 -1
  186. package/lib/metadata.d.ts +2 -2
  187. package/lib/metadata.d.ts.map +1 -1
  188. package/lib/metadata.js.map +1 -1
  189. package/lib/opLifecycle/batchManager.d.ts +0 -1
  190. package/lib/opLifecycle/batchManager.d.ts.map +1 -1
  191. package/lib/opLifecycle/batchManager.js +0 -10
  192. package/lib/opLifecycle/batchManager.js.map +1 -1
  193. package/lib/opLifecycle/opDecompressor.d.ts.map +1 -1
  194. package/lib/opLifecycle/opDecompressor.js +6 -6
  195. package/lib/opLifecycle/opDecompressor.js.map +1 -1
  196. package/lib/opLifecycle/opGroupingManager.js +2 -2
  197. package/lib/opLifecycle/opGroupingManager.js.map +1 -1
  198. package/lib/opLifecycle/opSplitter.js +1 -1
  199. package/lib/opLifecycle/opSplitter.js.map +1 -1
  200. package/lib/opLifecycle/outbox.d.ts +0 -4
  201. package/lib/opLifecycle/outbox.d.ts.map +1 -1
  202. package/lib/opLifecycle/outbox.js +2 -34
  203. package/lib/opLifecycle/outbox.js.map +1 -1
  204. package/lib/packageVersion.d.ts +1 -1
  205. package/lib/packageVersion.js +1 -1
  206. package/lib/packageVersion.js.map +1 -1
  207. package/lib/pendingStateManager.d.ts +3 -2
  208. package/lib/pendingStateManager.d.ts.map +1 -1
  209. package/lib/pendingStateManager.js +18 -11
  210. package/lib/pendingStateManager.js.map +1 -1
  211. package/lib/public.d.ts +3 -0
  212. package/lib/scheduleManager.d.ts +1 -1
  213. package/lib/scheduleManager.d.ts.map +1 -1
  214. package/lib/scheduleManager.js.map +1 -1
  215. package/lib/summary/documentSchema.d.ts +3 -1
  216. package/lib/summary/documentSchema.d.ts.map +1 -1
  217. package/lib/summary/documentSchema.js +34 -16
  218. package/lib/summary/documentSchema.js.map +1 -1
  219. package/lib/summary/orderedClientElection.d.ts +1 -1
  220. package/lib/summary/orderedClientElection.d.ts.map +1 -1
  221. package/lib/summary/orderedClientElection.js +1 -1
  222. package/lib/summary/orderedClientElection.js.map +1 -1
  223. package/lib/summary/summarizer.d.ts +1 -2
  224. package/lib/summary/summarizer.d.ts.map +1 -1
  225. package/lib/summary/summarizer.js.map +1 -1
  226. package/lib/summary/summarizerClientElection.d.ts +1 -1
  227. package/lib/summary/summarizerClientElection.d.ts.map +1 -1
  228. package/lib/summary/summarizerClientElection.js.map +1 -1
  229. package/lib/summary/summarizerHeuristics.d.ts +1 -1
  230. package/lib/summary/summarizerHeuristics.d.ts.map +1 -1
  231. package/lib/summary/summarizerHeuristics.js.map +1 -1
  232. package/lib/summary/summarizerNode/summarizerNode.d.ts +4 -3
  233. package/lib/summary/summarizerNode/summarizerNode.d.ts.map +1 -1
  234. package/lib/summary/summarizerNode/summarizerNode.js +4 -10
  235. package/lib/summary/summarizerNode/summarizerNode.js.map +1 -1
  236. package/lib/summary/summarizerNode/summarizerNodeUtils.d.ts +2 -3
  237. package/lib/summary/summarizerNode/summarizerNodeUtils.d.ts.map +1 -1
  238. package/lib/summary/summarizerNode/summarizerNodeUtils.js.map +1 -1
  239. package/lib/summary/summarizerNode/summarizerNodeWithGc.d.ts +1 -2
  240. package/lib/summary/summarizerNode/summarizerNodeWithGc.d.ts.map +1 -1
  241. package/lib/summary/summarizerNode/summarizerNodeWithGc.js +2 -9
  242. package/lib/summary/summarizerNode/summarizerNodeWithGc.js.map +1 -1
  243. package/lib/summary/summarizerTypes.d.ts +2 -3
  244. package/lib/summary/summarizerTypes.d.ts.map +1 -1
  245. package/lib/summary/summarizerTypes.js.map +1 -1
  246. package/lib/summary/summaryCollection.d.ts +1 -1
  247. package/lib/summary/summaryCollection.d.ts.map +1 -1
  248. package/lib/summary/summaryCollection.js.map +1 -1
  249. package/lib/summary/summaryGenerator.d.ts +1 -2
  250. package/lib/summary/summaryGenerator.d.ts.map +1 -1
  251. package/lib/summary/summaryGenerator.js +4 -3
  252. package/lib/summary/summaryGenerator.js.map +1 -1
  253. package/lib/summary/summaryManager.d.ts.map +1 -1
  254. package/lib/summary/summaryManager.js +1 -1
  255. package/lib/summary/summaryManager.js.map +1 -1
  256. package/package.json +33 -57
  257. package/src/batchTracker.ts +1 -2
  258. package/src/channelCollection.ts +87 -35
  259. package/src/connectionTelemetry.ts +58 -3
  260. package/src/containerRuntime.ts +214 -222
  261. package/src/dataStore.ts +5 -2
  262. package/src/dataStoreContext.ts +1 -0
  263. package/src/dataStoreContexts.ts +13 -2
  264. package/src/deltaManagerSummarizerProxy.ts +43 -21
  265. package/src/deltaScheduler.ts +1 -2
  266. package/src/gc/garbageCollection.ts +64 -42
  267. package/src/gc/gcDefinitions.ts +22 -10
  268. package/src/gc/gcHelpers.ts +14 -1
  269. package/src/gc/gcTelemetry.ts +57 -50
  270. package/src/gc/index.ts +2 -1
  271. package/src/index.ts +2 -0
  272. package/src/metadata.ts +2 -2
  273. package/src/opLifecycle/README.md +4 -4
  274. package/src/opLifecycle/batchManager.ts +0 -14
  275. package/src/opLifecycle/opDecompressor.ts +12 -6
  276. package/src/opLifecycle/opGroupingManager.ts +2 -2
  277. package/src/opLifecycle/opSplitter.ts +1 -1
  278. package/src/opLifecycle/outbox.ts +2 -49
  279. package/src/packageVersion.ts +1 -1
  280. package/src/pendingStateManager.ts +28 -15
  281. package/src/scheduleManager.ts +1 -1
  282. package/src/summary/documentSchema.ts +52 -18
  283. package/src/summary/orderedClientElection.ts +5 -2
  284. package/src/summary/summarizer.ts +1 -1
  285. package/src/summary/summarizerClientElection.ts +1 -1
  286. package/src/summary/summarizerHeuristics.ts +1 -1
  287. package/src/summary/summarizerNode/summarizerNode.ts +3 -12
  288. package/src/summary/summarizerNode/summarizerNodeUtils.ts +2 -3
  289. package/src/summary/summarizerNode/summarizerNodeWithGc.ts +1 -10
  290. package/src/summary/summarizerTypes.ts +5 -3
  291. package/src/summary/summaryCollection.ts +1 -1
  292. package/src/summary/summaryGenerator.ts +19 -8
  293. package/src/summary/summaryManager.ts +5 -2
package/src/dataStore.ts CHANGED
@@ -11,8 +11,11 @@ import {
11
11
  IDataStore,
12
12
  IFluidDataStoreChannel,
13
13
  } from "@fluidframework/runtime-definitions/internal";
14
- import { ITelemetryLoggerExt } from "@fluidframework/telemetry-utils";
15
- import { TelemetryDataTag, UsageError } from "@fluidframework/telemetry-utils/internal";
14
+ import {
15
+ ITelemetryLoggerExt,
16
+ TelemetryDataTag,
17
+ UsageError,
18
+ } from "@fluidframework/telemetry-utils/internal";
16
19
 
17
20
  import { ChannelCollection } from "./channelCollection.js";
18
21
  import { ContainerMessageType } from "./messageTypes.js";
@@ -219,6 +219,7 @@ export abstract class FluidDataStoreContext
219
219
  return this._containerRuntime;
220
220
  }
221
221
 
222
+ // back-compat, to be removed in 2.0
222
223
  public ensureNoDataModelChanges<T>(callback: () => T): T {
223
224
  return this.parentContext.ensureNoDataModelChanges(callback);
224
225
  }
@@ -5,8 +5,7 @@
5
5
 
6
6
  import { IDisposable, ITelemetryBaseLogger } from "@fluidframework/core-interfaces";
7
7
  import { assert, Deferred, Lazy } from "@fluidframework/core-utils/internal";
8
- import { ITelemetryLoggerExt } from "@fluidframework/telemetry-utils";
9
- import { createChildLogger } from "@fluidframework/telemetry-utils/internal";
8
+ import { ITelemetryLoggerExt, createChildLogger } from "@fluidframework/telemetry-utils/internal";
10
9
 
11
10
  import { FluidDataStoreContext, LocalFluidDataStoreContext } from "./dataStoreContext.js";
12
11
 
@@ -83,9 +82,21 @@ export class DataStoreContexts implements Iterable<[string, FluidDataStoreContex
83
82
  public delete(id: string): boolean {
84
83
  this.deferredContexts.delete(id);
85
84
  this.notBoundContexts.delete(id);
85
+
86
+ // Stash the context here in case it's requested in this session, we can log some details about it
87
+ const context = this._contexts.get(id);
88
+ this._recentlyDeletedContexts.set(id, context);
89
+
86
90
  return this._contexts.delete(id);
87
91
  }
88
92
 
93
+ private readonly _recentlyDeletedContexts: Map<string, FluidDataStoreContext | undefined> =
94
+ new Map();
95
+
96
+ public getRecentlyDeletedContext(id: string) {
97
+ return this._recentlyDeletedContexts.get(id);
98
+ }
99
+
89
100
  /**
90
101
  * Return the unbound local context with the given id,
91
102
  * or undefined if it's not found or not unbound.
@@ -25,11 +25,12 @@ import {
25
25
  import { summarizerClientType } from "./summary/index.js";
26
26
 
27
27
  /**
28
- * Proxy to the real IDeltaManager for restricting certain access to layers below container runtime in summarizer clients:
29
- * - Summarizer client should be read-only to layers below the container runtime to restrict local changes.
30
- * - Summarizer client should not be active to layers below the container runtime to restrict local changes.
28
+ * Base class for DeltaManager proxy that proxy's access to the real DeltaManager.
29
+ *
30
+ * This class allows us to build proxy functionality without actually having to implement all the methods
31
+ * of the DeltaManager.
31
32
  */
32
- export class DeltaManagerSummarizerProxy
33
+ export abstract class BaseDeltaManagerProxy
33
34
  extends TypedEventEmitter<IDeltaManagerEvents>
34
35
  implements IDeltaManager<ISequencedDocumentMessage, IDocumentMessage>
35
36
  {
@@ -90,35 +91,20 @@ export class DeltaManagerSummarizerProxy
90
91
  }
91
92
 
92
93
  public get active(): boolean {
93
- // Summarize clients should not be active. There shouldn't be any local changes (writes) in the summarizer
94
- // except for the SummarizeOp which is generated by the runtime.
95
- return !this.isSummarizerClient && this.deltaManager.active;
94
+ return this.deltaManager.active;
96
95
  }
97
96
 
98
97
  public get readOnlyInfo(): ReadOnlyInfo {
99
- // Summarizer clients should be read-only as far as the runtime and layers below are concerned. There shouldn't
100
- // be any local changes (writes) in the summarizer except for the summarize op which is generated by the runtime.
101
- if (this.isSummarizerClient) {
102
- return {
103
- readonly: true,
104
- forced: false,
105
- permissions: undefined,
106
- storageOnly: false,
107
- };
108
- }
109
98
  return this.deltaManager.readOnlyInfo;
110
99
  }
111
100
 
112
- private readonly isSummarizerClient: boolean;
113
-
114
101
  constructor(
115
- private readonly deltaManager: IDeltaManager<ISequencedDocumentMessage, IDocumentMessage>,
102
+ protected readonly deltaManager: IDeltaManager<ISequencedDocumentMessage, IDocumentMessage>,
116
103
  ) {
117
104
  super();
118
105
 
119
106
  // We are expecting this class to have many listeners, so we suppress noisy "MaxListenersExceededWarning" logging.
120
107
  super.setMaxListeners(0);
121
- this.isSummarizerClient = this.deltaManager.clientDetails.type === summarizerClientType;
122
108
 
123
109
  this.deltaManager.on("prepareSend", this.onPrepareSend);
124
110
  this.deltaManager.on("submitOp", this.onSubmitOp);
@@ -172,3 +158,39 @@ export class DeltaManagerSummarizerProxy
172
158
  this.emit("readonly", readonly, readonlyConnectionReason);
173
159
  };
174
160
  }
161
+
162
+ /**
163
+ * Proxy to the real IDeltaManager for restricting certain access to layers below container runtime in summarizer clients:
164
+ * - Summarizer client should be read-only to layers below the container runtime to restrict local changes.
165
+ * - Summarizer client should not be active to layers below the container runtime to restrict local changes.
166
+ */
167
+ export class DeltaManagerSummarizerProxy extends BaseDeltaManagerProxy {
168
+ public get active(): boolean {
169
+ // Summarize clients should not be active. There shouldn't be any local changes (writes) in the summarizer
170
+ // except for the SummarizeOp which is generated by the runtime.
171
+ return !this.isSummarizerClient && this.deltaManager.active;
172
+ }
173
+
174
+ public get readOnlyInfo(): ReadOnlyInfo {
175
+ // Summarizer clients should be read-only as far as the runtime and layers below are concerned. There shouldn't
176
+ // be any local changes (writes) in the summarizer except for the summarize op which is generated by the runtime.
177
+ if (this.isSummarizerClient) {
178
+ return {
179
+ readonly: true,
180
+ forced: false,
181
+ permissions: undefined,
182
+ storageOnly: false,
183
+ };
184
+ }
185
+ return this.deltaManager.readOnlyInfo;
186
+ }
187
+
188
+ private readonly isSummarizerClient: boolean;
189
+
190
+ constructor(
191
+ protected readonly deltaManager: IDeltaManager<ISequencedDocumentMessage, IDocumentMessage>,
192
+ ) {
193
+ super(deltaManager);
194
+ this.isSummarizerClient = this.deltaManager.clientDetails.type === summarizerClientType;
195
+ }
196
+ }
@@ -6,8 +6,7 @@
6
6
  import { performance } from "@fluid-internal/client-utils";
7
7
  import { IDeltaManager } from "@fluidframework/container-definitions";
8
8
  import { IDocumentMessage, ISequencedDocumentMessage } from "@fluidframework/protocol-definitions";
9
- import { ITelemetryLoggerExt } from "@fluidframework/telemetry-utils";
10
- import { formatTick } from "@fluidframework/telemetry-utils/internal";
9
+ import { ITelemetryLoggerExt, formatTick } from "@fluidframework/telemetry-utils/internal";
11
10
 
12
11
  /**
13
12
  * DeltaScheduler is responsible for the scheduling of inbound delta queue in cases where there
@@ -12,8 +12,8 @@ import {
12
12
  gcTreeKey,
13
13
  } from "@fluidframework/runtime-definitions/internal";
14
14
  import { createResponseError, responseToException } from "@fluidframework/runtime-utils/internal";
15
- import { ITelemetryLoggerExt } from "@fluidframework/telemetry-utils";
16
15
  import {
16
+ ITelemetryLoggerExt,
17
17
  DataProcessingError,
18
18
  MonitoringContext,
19
19
  PerformanceEvent,
@@ -23,11 +23,7 @@ import {
23
23
  } from "@fluidframework/telemetry-utils/internal";
24
24
 
25
25
  import { BlobManager } from "../blobManager.js";
26
- import {
27
- InactiveResponseHeaderKey,
28
- RuntimeHeaderData,
29
- TombstoneResponseHeaderKey,
30
- } from "../containerRuntime.js";
26
+ import { InactiveResponseHeaderKey, TombstoneResponseHeaderKey } from "../containerRuntime.js";
31
27
  import { ClientSessionExpiredError } from "../error.js";
32
28
  import { ContainerMessageType, ContainerRuntimeGCMessage } from "../messageTypes.js";
33
29
  import { IRefreshSummaryResult } from "../summary/index.js";
@@ -48,12 +44,15 @@ import {
48
44
  ISweepPhaseStats,
49
45
  UnreferencedState,
50
46
  disableAutoRecoveryKey,
47
+ type IGCNodeUpdatedProps,
51
48
  } from "./gcDefinitions.js";
52
49
  import {
53
50
  cloneGCData,
54
51
  compatBehaviorAllowsGCMessageType,
55
52
  concatGarbageCollectionData,
53
+ dataStoreNodePathOnly,
56
54
  getGCDataFromSnapshot,
55
+ urlToGCNodePath,
57
56
  } from "./gcHelpers.js";
58
57
  import { runGarbageCollection } from "./gcReferenceGraphAlgorithm.js";
59
58
  import { IGarbageCollectionSnapshotData, IGarbageCollectionState } from "./gcSummaryDefinitions.js";
@@ -401,17 +400,27 @@ export class GarbageCollector implements IGarbageCollector {
401
400
  return;
402
401
  }
403
402
 
404
- // If the GC state hasn't been initialized yet, initialize it and return.
405
- if (this.gcDataFromLastRun === undefined) {
406
- await this.initializeGCStateFromBaseSnapshotP;
407
- return;
408
- }
403
+ const initialized = this.gcDataFromLastRun !== undefined;
404
+ await PerformanceEvent.timedExecAsync(
405
+ this.mc.logger,
406
+ {
407
+ eventName: "InitializeOrUpdateGCState",
408
+ details: { initialized, unrefNodeCount: this.unreferencedNodesState.size },
409
+ },
410
+ async () => {
411
+ // If the GC state hasn't been initialized yet, initialize it and return.
412
+ if (!initialized) {
413
+ await this.initializeGCStateFromBaseSnapshotP;
414
+ return;
415
+ }
409
416
 
410
- // If the GC state has been initialized, update the tracking of unreferenced nodes as per the current
411
- // reference timestamp.
412
- for (const [, nodeStateTracker] of this.unreferencedNodesState) {
413
- nodeStateTracker.updateTracking(currentReferenceTimestampMs);
414
- }
417
+ // If the GC state has been initialized, update the tracking of unreferenced nodes as per the current
418
+ // reference timestamp.
419
+ for (const [, nodeStateTracker] of this.unreferencedNodesState) {
420
+ nodeStateTracker.updateTracking(currentReferenceTimestampMs);
421
+ }
422
+ },
423
+ );
415
424
  }
416
425
 
417
426
  /**
@@ -978,30 +987,30 @@ export class GarbageCollector implements IGarbageCollector {
978
987
  /**
979
988
  * Called when a node with the given id is updated. If the node is inactive or tombstoned, this will log an error
980
989
  * or throw an error if failing on incorrect usage is configured.
981
- * @param nodePath - The path of the node that changed.
982
- * @param reason - Whether the node was loaded or changed.
983
- * @param timestampMs - The timestamp when the node changed.
984
- * @param packagePath - The package path of the node. This may not be available if the node hasn't been loaded yet.
985
- * @param request - The original request for loads to preserve it in telemetry.
986
- * @param requestHeaders - If the node was loaded via request path, the headers in the request.
990
+ * @param IGCNodeUpdatedProps - Details about the node and how it was updated
987
991
  */
988
- public nodeUpdated(
989
- nodePath: string,
990
- reason: "Loaded" | "Changed",
991
- timestampMs?: number,
992
- packagePath?: readonly string[],
993
- request?: IRequest,
994
- headerData?: RuntimeHeaderData,
995
- ) {
992
+ public nodeUpdated({
993
+ node,
994
+ reason,
995
+ timestampMs,
996
+ packagePath,
997
+ request,
998
+ headerData,
999
+ }: IGCNodeUpdatedProps) {
996
1000
  if (!this.configs.shouldRunGC) {
997
1001
  return;
998
1002
  }
999
1003
 
1000
- const isTombstoned = this.tombstones.includes(nodePath);
1004
+ // trackedId will be either DataStore or Blob ID (not sub-DataStore ID, since some of those are unrecognized by GC)
1005
+ const trackedId = node.path;
1006
+ const isTombstoned = this.tombstones.includes(trackedId);
1007
+ const isInactive = this.unreferencedNodesState.get(trackedId)?.state === "Inactive";
1008
+
1009
+ const fullPath = request !== undefined ? urlToGCNodePath(request.url) : trackedId;
1001
1010
 
1002
1011
  // This will log if appropriate
1003
- this.telemetryTracker.nodeUsed({
1004
- id: nodePath,
1012
+ this.telemetryTracker.nodeUsed(trackedId, {
1013
+ id: fullPath,
1005
1014
  usageType: reason,
1006
1015
  currentReferenceTimestampMs:
1007
1016
  timestampMs ?? this.runtime.getCurrentReferenceTimestampMs(),
@@ -1010,6 +1019,8 @@ export class GarbageCollector implements IGarbageCollector {
1010
1019
  isTombstoned,
1011
1020
  lastSummaryTime: this.getLastSummaryTimestampMs(),
1012
1021
  headers: headerData,
1022
+ requestUrl: request?.url,
1023
+ requestHeaders: JSON.stringify(request?.headers),
1013
1024
  });
1014
1025
 
1015
1026
  // Any time we log a Tombstone Loaded error (via Telemetry Tracker),
@@ -1018,17 +1029,20 @@ export class GarbageCollector implements IGarbageCollector {
1018
1029
  // to be loaded by the Summarizer, and auto-recovery will be triggered then.
1019
1030
  if (isTombstoned && reason === "Loaded") {
1020
1031
  // Note that when a DataStore and its DDS are all loaded, each will trigger AutoRecovery for itself.
1021
- this.triggerAutoRecovery(nodePath);
1032
+ this.triggerAutoRecovery(fullPath);
1022
1033
  }
1023
1034
 
1024
- const nodeType = this.runtime.getNodeType(nodePath);
1035
+ const nodeType = this.runtime.getNodeType(fullPath);
1025
1036
 
1026
1037
  // Unless this is a Loaded event for a Blob or DataStore, we're done after telemetry tracking
1027
- if (reason !== "Loaded" || ![GCNodeType.Blob, GCNodeType.DataStore].includes(nodeType)) {
1038
+ const loadedBlobOrDataStore =
1039
+ reason === "Loaded" &&
1040
+ (nodeType === GCNodeType.Blob || nodeType === GCNodeType.DataStore);
1041
+ if (!loadedBlobOrDataStore) {
1028
1042
  return;
1029
1043
  }
1030
1044
 
1031
- const errorRequest: IRequest = request ?? { url: nodePath };
1045
+ const errorRequest: IRequest = request ?? { url: fullPath };
1032
1046
  if (isTombstoned && this.throwOnTombstoneLoad && headerData?.allowTombstone !== true) {
1033
1047
  // The requested data store is removed by gc. Create a 404 gc response exception.
1034
1048
  throw responseToException(
@@ -1040,7 +1054,7 @@ export class GarbageCollector implements IGarbageCollector {
1040
1054
  }
1041
1055
 
1042
1056
  // If the object is inactive and inactive enforcement is configured, throw an error.
1043
- if (this.unreferencedNodesState.get(nodePath)?.state === "Inactive") {
1057
+ if (isInactive) {
1044
1058
  const shouldThrowOnInactiveLoad =
1045
1059
  !this.isSummarizerClient &&
1046
1060
  this.configs.throwOnInactiveLoad === true &&
@@ -1112,22 +1126,30 @@ export class GarbageCollector implements IGarbageCollector {
1112
1126
  outboundRoutes.push(toNodePath);
1113
1127
  this.newReferencesSinceLastRun.set(fromNodePath, outboundRoutes);
1114
1128
 
1115
- this.telemetryTracker.nodeUsed({
1129
+ // GC won't recognize some subDataStore paths that we encounter (e.g. a path suited for a custom request handler)
1130
+ // So for subDataStore paths we need to check the parent dataStore for current tombstone/inactive status.
1131
+ const trackedId =
1132
+ this.runtime.getNodeType(toNodePath) === "SubDataStore"
1133
+ ? dataStoreNodePathOnly(toNodePath)
1134
+ : toNodePath;
1135
+ this.telemetryTracker.nodeUsed(trackedId, {
1116
1136
  id: toNodePath,
1137
+ fromId: fromNodePath,
1117
1138
  usageType: "Revived",
1118
1139
  currentReferenceTimestampMs: this.runtime.getCurrentReferenceTimestampMs(),
1119
1140
  packagePath: undefined,
1120
1141
  completedGCRuns: this.completedRuns,
1121
- isTombstoned: this.tombstones.includes(toNodePath),
1142
+ isTombstoned: this.tombstones.includes(trackedId),
1122
1143
  lastSummaryTime: this.getLastSummaryTimestampMs(),
1123
- fromId: fromNodePath,
1124
1144
  autorecovery,
1125
1145
  });
1126
1146
 
1127
- // This node is referenced - Clear its unreferenced state
1147
+ // This node is referenced - Clear its unreferenced state if present
1128
1148
  // But don't delete the node id from the map yet.
1129
1149
  // When generating GC stats, the set of nodes in here is used as the baseline for
1130
1150
  // what was unreferenced in the last GC run.
1151
+ // NOTE: We use toNodePath not trackedId even though it may be an unrecognized subDataStore route (hence no-op),
1152
+ // because a reference to such a path is not sufficient to consider the DataStore referenced.
1131
1153
  this.unreferencedNodesState.get(toNodePath)?.stopTracking();
1132
1154
  }
1133
1155
 
@@ -12,7 +12,7 @@ import {
12
12
  ISummarizeResult,
13
13
  } from "@fluidframework/runtime-definitions/internal";
14
14
  import { ReadAndParseBlob } from "@fluidframework/runtime-utils/internal";
15
- import { ITelemetryLoggerExt } from "@fluidframework/telemetry-utils";
15
+ import { ITelemetryLoggerExt } from "@fluidframework/telemetry-utils/internal";
16
16
 
17
17
  import { RuntimeHeaderData } from "../containerRuntime.js";
18
18
  import { ContainerRuntimeGCMessage } from "../messageTypes.js";
@@ -245,7 +245,7 @@ export const GCNodeType = {
245
245
  Blob: "Blob",
246
246
  // Nodes that are neither of the above. For example, root node.
247
247
  Other: "Other",
248
- };
248
+ } as const;
249
249
 
250
250
  /**
251
251
  * @alpha
@@ -370,14 +370,7 @@ export interface IGarbageCollector {
370
370
  * Called when a node with the given path is updated. If the node is inactive or tombstoned, this will log an error
371
371
  * or throw an error if failing on incorrect usage is configured.
372
372
  */
373
- nodeUpdated(
374
- nodePath: string,
375
- reason: "Loaded" | "Changed",
376
- timestampMs?: number,
377
- packagePath?: readonly string[],
378
- request?: IRequest,
379
- headerData?: RuntimeHeaderData,
380
- ): void;
373
+ nodeUpdated(props: IGCNodeUpdatedProps): void;
381
374
  /** Called when a reference is added to a node. Used to identify nodes that were referenced between summaries. */
382
375
  addedOutboundReference(fromNodePath: string, toNodePath: string, autorecovery?: true): void;
383
376
  /** Called to process a garbage collection message. */
@@ -388,6 +381,25 @@ export interface IGarbageCollector {
388
381
  dispose(): void;
389
382
  }
390
383
 
384
+ /**
385
+ * Info needed by GC when notified that a node was updated (loaded or changed)
386
+ * @internal
387
+ */
388
+ export interface IGCNodeUpdatedProps {
389
+ /** Type and path of the updated node */
390
+ node: { type: (typeof GCNodeType)["DataStore" | "Blob"]; path: string };
391
+ /** Whether the node (or a subpath) was loaded or changed. */
392
+ reason: "Loaded" | "Changed";
393
+ /** The op-based timestamp when the node changed, if applicable */
394
+ timestampMs?: number;
395
+ /** The package path of the node. This may not be available if the node hasn't been loaded yet */
396
+ packagePath?: readonly string[];
397
+ /** The original request for loads to preserve it in telemetry */
398
+ request?: IRequest;
399
+ /** If the node was loaded via request path, the header data. May be modified from the original request */
400
+ headerData?: RuntimeHeaderData;
401
+ }
402
+
391
403
  /** Parameters necessary for creating a GarbageCollector. */
392
404
  export interface IGarbageCollectorCreateParams {
393
405
  readonly runtime: IGarbageCollectionRuntime;
@@ -280,10 +280,23 @@ export function unpackChildNodesGCDetails(gcDetails: IGarbageCollectionDetailsBa
280
280
  * @param str - A string that may contain leading and / or trailing slashes.
281
281
  * @returns A new string without leading and trailing slashes.
282
282
  */
283
- export function trimLeadingAndTrailingSlashes(str: string) {
283
+ function trimLeadingAndTrailingSlashes(str: string) {
284
284
  return str.replace(/^\/+|\/+$/g, "");
285
285
  }
286
286
 
287
+ /** Reformats a request URL to match expected format for a GC node path */
288
+ export function urlToGCNodePath(url: string): string {
289
+ return `/${trimLeadingAndTrailingSlashes(url.split("?")[0])}`;
290
+ }
291
+
292
+ /**
293
+ * Pulls out the first path segment and formats it as a GC Node path
294
+ * e.g. "/dataStoreId/ddsId" yields "/dataStoreId"
295
+ */
296
+ export function dataStoreNodePathOnly(subDataStorePath: string): string {
297
+ return `/${subDataStorePath.split("/")[1]}`;
298
+ }
299
+
287
300
  /**
288
301
  * Utility to implement compat behaviors given an unknown message type
289
302
  * The parameters are typed to support compile-time enforcement of handling all known types/behaviors