@fluidframework/container-runtime 2.0.0-dev.4.1.0.148229 → 2.0.0-dev.4.3.0.157531

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 (314) hide show
  1. package/CHANGELOG.md +58 -0
  2. package/README.md +69 -0
  3. package/dist/blobManager.d.ts +6 -14
  4. package/dist/blobManager.d.ts.map +1 -1
  5. package/dist/blobManager.js +50 -37
  6. package/dist/blobManager.js.map +1 -1
  7. package/dist/containerRuntime.d.ts +47 -4
  8. package/dist/containerRuntime.d.ts.map +1 -1
  9. package/dist/containerRuntime.js +203 -49
  10. package/dist/containerRuntime.js.map +1 -1
  11. package/dist/dataStoreContext.d.ts +2 -1
  12. package/dist/dataStoreContext.d.ts.map +1 -1
  13. package/dist/dataStoreContext.js +3 -0
  14. package/dist/dataStoreContext.js.map +1 -1
  15. package/dist/dataStores.d.ts +5 -5
  16. package/dist/dataStores.d.ts.map +1 -1
  17. package/dist/dataStores.js +3 -6
  18. package/dist/dataStores.js.map +1 -1
  19. package/dist/gc/garbageCollection.d.ts.map +1 -1
  20. package/dist/gc/garbageCollection.js +5 -5
  21. package/dist/gc/garbageCollection.js.map +1 -1
  22. package/dist/gc/gcConfigs.d.ts.map +1 -1
  23. package/dist/gc/gcConfigs.js +1 -3
  24. package/dist/gc/gcConfigs.js.map +1 -1
  25. package/dist/gc/gcDefinitions.js +1 -1
  26. package/dist/gc/gcDefinitions.js.map +1 -1
  27. package/dist/gc/gcHelpers.d.ts.map +1 -1
  28. package/dist/gc/gcHelpers.js +6 -6
  29. package/dist/gc/gcHelpers.js.map +1 -1
  30. package/dist/id-compressor/appendOnlySortedMap.d.ts +146 -0
  31. package/dist/id-compressor/appendOnlySortedMap.d.ts.map +1 -0
  32. package/dist/id-compressor/appendOnlySortedMap.js +360 -0
  33. package/dist/id-compressor/appendOnlySortedMap.js.map +1 -0
  34. package/dist/id-compressor/idCompressor.d.ts +279 -0
  35. package/dist/id-compressor/idCompressor.d.ts.map +1 -0
  36. package/dist/id-compressor/idCompressor.js +1258 -0
  37. package/dist/id-compressor/idCompressor.js.map +1 -0
  38. package/dist/id-compressor/idRange.d.ts +11 -0
  39. package/dist/id-compressor/idRange.d.ts.map +1 -0
  40. package/dist/id-compressor/idRange.js +29 -0
  41. package/dist/id-compressor/idRange.js.map +1 -0
  42. package/dist/id-compressor/index.d.ts +14 -0
  43. package/dist/id-compressor/index.d.ts.map +1 -0
  44. package/dist/id-compressor/index.js +38 -0
  45. package/dist/id-compressor/index.js.map +1 -0
  46. package/dist/id-compressor/numericUuid.d.ts +59 -0
  47. package/dist/id-compressor/numericUuid.d.ts.map +1 -0
  48. package/dist/id-compressor/numericUuid.js +325 -0
  49. package/dist/id-compressor/numericUuid.js.map +1 -0
  50. package/dist/id-compressor/sessionIdNormalizer.d.ts +138 -0
  51. package/dist/id-compressor/sessionIdNormalizer.d.ts.map +1 -0
  52. package/dist/id-compressor/sessionIdNormalizer.js +488 -0
  53. package/dist/id-compressor/sessionIdNormalizer.js.map +1 -0
  54. package/dist/id-compressor/utils.d.ts +57 -0
  55. package/dist/id-compressor/utils.d.ts.map +1 -0
  56. package/dist/id-compressor/utils.js +90 -0
  57. package/dist/id-compressor/utils.js.map +1 -0
  58. package/dist/id-compressor/uuidUtilities.d.ts +30 -0
  59. package/dist/id-compressor/uuidUtilities.d.ts.map +1 -0
  60. package/dist/id-compressor/uuidUtilities.js +106 -0
  61. package/dist/id-compressor/uuidUtilities.js.map +1 -0
  62. package/dist/index.d.ts +1 -0
  63. package/dist/index.d.ts.map +1 -1
  64. package/dist/index.js +5 -1
  65. package/dist/index.js.map +1 -1
  66. package/dist/opLifecycle/batchManager.d.ts +9 -2
  67. package/dist/opLifecycle/batchManager.d.ts.map +1 -1
  68. package/dist/opLifecycle/batchManager.js +21 -2
  69. package/dist/opLifecycle/batchManager.js.map +1 -1
  70. package/dist/opLifecycle/index.d.ts +2 -1
  71. package/dist/opLifecycle/index.d.ts.map +1 -1
  72. package/dist/opLifecycle/index.js +3 -1
  73. package/dist/opLifecycle/index.js.map +1 -1
  74. package/dist/opLifecycle/opDecompressor.d.ts.map +1 -1
  75. package/dist/opLifecycle/opDecompressor.js +2 -1
  76. package/dist/opLifecycle/opDecompressor.js.map +1 -1
  77. package/dist/opLifecycle/opGroupingManager.d.ts +14 -0
  78. package/dist/opLifecycle/opGroupingManager.d.ts.map +1 -0
  79. package/dist/opLifecycle/opGroupingManager.js +61 -0
  80. package/dist/opLifecycle/opGroupingManager.js.map +1 -0
  81. package/dist/opLifecycle/opSplitter.d.ts +1 -1
  82. package/dist/opLifecycle/opSplitter.d.ts.map +1 -1
  83. package/dist/opLifecycle/opSplitter.js +5 -6
  84. package/dist/opLifecycle/opSplitter.js.map +1 -1
  85. package/dist/opLifecycle/outbox.d.ts +4 -2
  86. package/dist/opLifecycle/outbox.d.ts.map +1 -1
  87. package/dist/opLifecycle/outbox.js +37 -25
  88. package/dist/opLifecycle/outbox.js.map +1 -1
  89. package/dist/opLifecycle/remoteMessageProcessor.d.ts +4 -2
  90. package/dist/opLifecycle/remoteMessageProcessor.d.ts.map +1 -1
  91. package/dist/opLifecycle/remoteMessageProcessor.js +30 -20
  92. package/dist/opLifecycle/remoteMessageProcessor.js.map +1 -1
  93. package/dist/packageVersion.d.ts +1 -1
  94. package/dist/packageVersion.js +1 -1
  95. package/dist/packageVersion.js.map +1 -1
  96. package/dist/pendingStateManager.d.ts +1 -1
  97. package/dist/pendingStateManager.d.ts.map +1 -1
  98. package/dist/pendingStateManager.js +11 -3
  99. package/dist/pendingStateManager.js.map +1 -1
  100. package/dist/summary/index.d.ts +2 -2
  101. package/dist/summary/index.d.ts.map +1 -1
  102. package/dist/summary/index.js +4 -1
  103. package/dist/summary/index.js.map +1 -1
  104. package/dist/summary/orderedClientElection.d.ts +1 -0
  105. package/dist/summary/orderedClientElection.d.ts.map +1 -1
  106. package/dist/summary/orderedClientElection.js +19 -0
  107. package/dist/summary/orderedClientElection.js.map +1 -1
  108. package/dist/summary/runningSummarizer.d.ts +4 -3
  109. package/dist/summary/runningSummarizer.d.ts.map +1 -1
  110. package/dist/summary/runningSummarizer.js +65 -66
  111. package/dist/summary/runningSummarizer.js.map +1 -1
  112. package/dist/summary/summarizer.d.ts.map +1 -1
  113. package/dist/summary/summarizer.js +1 -5
  114. package/dist/summary/summarizer.js.map +1 -1
  115. package/dist/summary/summarizerHeuristics.d.ts +1 -0
  116. package/dist/summary/summarizerHeuristics.d.ts.map +1 -1
  117. package/dist/summary/summarizerHeuristics.js +3 -0
  118. package/dist/summary/summarizerHeuristics.js.map +1 -1
  119. package/dist/summary/summarizerNode/summarizerNode.js +1 -1
  120. package/dist/summary/summarizerNode/summarizerNode.js.map +1 -1
  121. package/dist/summary/summarizerNode/summarizerNodeWithGc.d.ts +128 -2
  122. package/dist/summary/summarizerNode/summarizerNodeWithGc.d.ts.map +1 -1
  123. package/dist/summary/summarizerNode/summarizerNodeWithGc.js +4 -3
  124. package/dist/summary/summarizerNode/summarizerNodeWithGc.js.map +1 -1
  125. package/dist/summary/summarizerTypes.d.ts +14 -2
  126. package/dist/summary/summarizerTypes.d.ts.map +1 -1
  127. package/dist/summary/summarizerTypes.js.map +1 -1
  128. package/dist/summary/summaryFormat.d.ts +3 -0
  129. package/dist/summary/summaryFormat.d.ts.map +1 -1
  130. package/dist/summary/summaryFormat.js +3 -1
  131. package/dist/summary/summaryFormat.js.map +1 -1
  132. package/dist/summary/summaryGenerator.d.ts +28 -2
  133. package/dist/summary/summaryGenerator.d.ts.map +1 -1
  134. package/dist/summary/summaryGenerator.js +19 -16
  135. package/dist/summary/summaryGenerator.js.map +1 -1
  136. package/dist/summary/summaryManager.d.ts.map +1 -1
  137. package/dist/summary/summaryManager.js +2 -0
  138. package/dist/summary/summaryManager.js.map +1 -1
  139. package/lib/blobManager.d.ts +6 -14
  140. package/lib/blobManager.d.ts.map +1 -1
  141. package/lib/blobManager.js +50 -37
  142. package/lib/blobManager.js.map +1 -1
  143. package/lib/containerRuntime.d.ts +47 -4
  144. package/lib/containerRuntime.d.ts.map +1 -1
  145. package/lib/containerRuntime.js +187 -52
  146. package/lib/containerRuntime.js.map +1 -1
  147. package/lib/dataStoreContext.d.ts +2 -1
  148. package/lib/dataStoreContext.d.ts.map +1 -1
  149. package/lib/dataStoreContext.js +3 -0
  150. package/lib/dataStoreContext.js.map +1 -1
  151. package/lib/dataStores.d.ts +5 -5
  152. package/lib/dataStores.d.ts.map +1 -1
  153. package/lib/dataStores.js +3 -6
  154. package/lib/dataStores.js.map +1 -1
  155. package/lib/gc/garbageCollection.d.ts.map +1 -1
  156. package/lib/gc/garbageCollection.js +5 -5
  157. package/lib/gc/garbageCollection.js.map +1 -1
  158. package/lib/gc/gcConfigs.d.ts.map +1 -1
  159. package/lib/gc/gcConfigs.js +1 -3
  160. package/lib/gc/gcConfigs.js.map +1 -1
  161. package/lib/gc/gcDefinitions.js +1 -1
  162. package/lib/gc/gcDefinitions.js.map +1 -1
  163. package/lib/gc/gcHelpers.d.ts.map +1 -1
  164. package/lib/gc/gcHelpers.js +6 -6
  165. package/lib/gc/gcHelpers.js.map +1 -1
  166. package/lib/id-compressor/appendOnlySortedMap.d.ts +146 -0
  167. package/lib/id-compressor/appendOnlySortedMap.d.ts.map +1 -0
  168. package/lib/id-compressor/appendOnlySortedMap.js +355 -0
  169. package/lib/id-compressor/appendOnlySortedMap.js.map +1 -0
  170. package/lib/id-compressor/idCompressor.d.ts +279 -0
  171. package/lib/id-compressor/idCompressor.d.ts.map +1 -0
  172. package/lib/id-compressor/idCompressor.js +1248 -0
  173. package/lib/id-compressor/idCompressor.js.map +1 -0
  174. package/lib/id-compressor/idRange.d.ts +11 -0
  175. package/lib/id-compressor/idRange.d.ts.map +1 -0
  176. package/lib/id-compressor/idRange.js +25 -0
  177. package/lib/id-compressor/idRange.js.map +1 -0
  178. package/lib/id-compressor/index.d.ts +14 -0
  179. package/lib/id-compressor/index.d.ts.map +1 -0
  180. package/lib/id-compressor/index.js +14 -0
  181. package/lib/id-compressor/index.js.map +1 -0
  182. package/lib/id-compressor/numericUuid.d.ts +59 -0
  183. package/lib/id-compressor/numericUuid.d.ts.map +1 -0
  184. package/lib/id-compressor/numericUuid.js +315 -0
  185. package/lib/id-compressor/numericUuid.js.map +1 -0
  186. package/lib/id-compressor/sessionIdNormalizer.d.ts +138 -0
  187. package/lib/id-compressor/sessionIdNormalizer.d.ts.map +1 -0
  188. package/lib/id-compressor/sessionIdNormalizer.js +484 -0
  189. package/lib/id-compressor/sessionIdNormalizer.js.map +1 -0
  190. package/lib/id-compressor/utils.d.ts +57 -0
  191. package/lib/id-compressor/utils.d.ts.map +1 -0
  192. package/lib/id-compressor/utils.js +79 -0
  193. package/lib/id-compressor/utils.js.map +1 -0
  194. package/lib/id-compressor/uuidUtilities.d.ts +30 -0
  195. package/lib/id-compressor/uuidUtilities.d.ts.map +1 -0
  196. package/lib/id-compressor/uuidUtilities.js +98 -0
  197. package/lib/id-compressor/uuidUtilities.js.map +1 -0
  198. package/lib/index.d.ts +1 -0
  199. package/lib/index.d.ts.map +1 -1
  200. package/lib/index.js +1 -0
  201. package/lib/index.js.map +1 -1
  202. package/lib/opLifecycle/batchManager.d.ts +9 -2
  203. package/lib/opLifecycle/batchManager.d.ts.map +1 -1
  204. package/lib/opLifecycle/batchManager.js +19 -1
  205. package/lib/opLifecycle/batchManager.js.map +1 -1
  206. package/lib/opLifecycle/index.d.ts +2 -1
  207. package/lib/opLifecycle/index.d.ts.map +1 -1
  208. package/lib/opLifecycle/index.js +1 -0
  209. package/lib/opLifecycle/index.js.map +1 -1
  210. package/lib/opLifecycle/opDecompressor.d.ts.map +1 -1
  211. package/lib/opLifecycle/opDecompressor.js +2 -1
  212. package/lib/opLifecycle/opDecompressor.js.map +1 -1
  213. package/lib/opLifecycle/opGroupingManager.d.ts +14 -0
  214. package/lib/opLifecycle/opGroupingManager.d.ts.map +1 -0
  215. package/lib/opLifecycle/opGroupingManager.js +57 -0
  216. package/lib/opLifecycle/opGroupingManager.js.map +1 -0
  217. package/lib/opLifecycle/opSplitter.d.ts +1 -1
  218. package/lib/opLifecycle/opSplitter.d.ts.map +1 -1
  219. package/lib/opLifecycle/opSplitter.js +5 -6
  220. package/lib/opLifecycle/opSplitter.js.map +1 -1
  221. package/lib/opLifecycle/outbox.d.ts +4 -2
  222. package/lib/opLifecycle/outbox.d.ts.map +1 -1
  223. package/lib/opLifecycle/outbox.js +38 -26
  224. package/lib/opLifecycle/outbox.js.map +1 -1
  225. package/lib/opLifecycle/remoteMessageProcessor.d.ts +4 -2
  226. package/lib/opLifecycle/remoteMessageProcessor.d.ts.map +1 -1
  227. package/lib/opLifecycle/remoteMessageProcessor.js +30 -20
  228. package/lib/opLifecycle/remoteMessageProcessor.js.map +1 -1
  229. package/lib/packageVersion.d.ts +1 -1
  230. package/lib/packageVersion.js +1 -1
  231. package/lib/packageVersion.js.map +1 -1
  232. package/lib/pendingStateManager.d.ts +1 -1
  233. package/lib/pendingStateManager.d.ts.map +1 -1
  234. package/lib/pendingStateManager.js +11 -3
  235. package/lib/pendingStateManager.js.map +1 -1
  236. package/lib/summary/index.d.ts +2 -2
  237. package/lib/summary/index.d.ts.map +1 -1
  238. package/lib/summary/index.js +2 -1
  239. package/lib/summary/index.js.map +1 -1
  240. package/lib/summary/orderedClientElection.d.ts +1 -0
  241. package/lib/summary/orderedClientElection.d.ts.map +1 -1
  242. package/lib/summary/orderedClientElection.js +19 -0
  243. package/lib/summary/orderedClientElection.js.map +1 -1
  244. package/lib/summary/runningSummarizer.d.ts +4 -3
  245. package/lib/summary/runningSummarizer.d.ts.map +1 -1
  246. package/lib/summary/runningSummarizer.js +65 -66
  247. package/lib/summary/runningSummarizer.js.map +1 -1
  248. package/lib/summary/summarizer.d.ts.map +1 -1
  249. package/lib/summary/summarizer.js +1 -5
  250. package/lib/summary/summarizer.js.map +1 -1
  251. package/lib/summary/summarizerHeuristics.d.ts +1 -0
  252. package/lib/summary/summarizerHeuristics.d.ts.map +1 -1
  253. package/lib/summary/summarizerHeuristics.js +3 -0
  254. package/lib/summary/summarizerHeuristics.js.map +1 -1
  255. package/lib/summary/summarizerNode/summarizerNode.js +1 -1
  256. package/lib/summary/summarizerNode/summarizerNode.js.map +1 -1
  257. package/lib/summary/summarizerNode/summarizerNodeWithGc.d.ts +128 -2
  258. package/lib/summary/summarizerNode/summarizerNodeWithGc.d.ts.map +1 -1
  259. package/lib/summary/summarizerNode/summarizerNodeWithGc.js +3 -3
  260. package/lib/summary/summarizerNode/summarizerNodeWithGc.js.map +1 -1
  261. package/lib/summary/summarizerTypes.d.ts +14 -2
  262. package/lib/summary/summarizerTypes.d.ts.map +1 -1
  263. package/lib/summary/summarizerTypes.js.map +1 -1
  264. package/lib/summary/summaryFormat.d.ts +3 -0
  265. package/lib/summary/summaryFormat.d.ts.map +1 -1
  266. package/lib/summary/summaryFormat.js +2 -0
  267. package/lib/summary/summaryFormat.js.map +1 -1
  268. package/lib/summary/summaryGenerator.d.ts +28 -2
  269. package/lib/summary/summaryGenerator.d.ts.map +1 -1
  270. package/lib/summary/summaryGenerator.js +17 -15
  271. package/lib/summary/summaryGenerator.js.map +1 -1
  272. package/lib/summary/summaryManager.d.ts.map +1 -1
  273. package/lib/summary/summaryManager.js +2 -0
  274. package/lib/summary/summaryManager.js.map +1 -1
  275. package/package.json +29 -17
  276. package/src/blobManager.ts +64 -41
  277. package/src/containerRuntime.ts +294 -65
  278. package/src/dataStoreContext.ts +6 -0
  279. package/src/dataStores.ts +4 -7
  280. package/src/gc/garbageCollection.ts +7 -6
  281. package/src/gc/gcConfigs.ts +1 -3
  282. package/src/gc/gcDefinitions.ts +1 -1
  283. package/src/gc/gcHelpers.ts +9 -6
  284. package/src/id-compressor/README.md +3 -0
  285. package/src/id-compressor/appendOnlySortedMap.ts +427 -0
  286. package/src/id-compressor/idCompressor.ts +1854 -0
  287. package/src/id-compressor/idRange.ts +35 -0
  288. package/src/id-compressor/index.ts +35 -0
  289. package/src/id-compressor/numericUuid.ts +383 -0
  290. package/src/id-compressor/sessionIdNormalizer.ts +609 -0
  291. package/src/id-compressor/utils.ts +114 -0
  292. package/src/id-compressor/uuidUtilities.ts +123 -0
  293. package/src/index.ts +1 -0
  294. package/src/opLifecycle/README.md +119 -0
  295. package/src/opLifecycle/batchManager.ts +35 -2
  296. package/src/opLifecycle/index.ts +2 -1
  297. package/src/opLifecycle/opDecompressor.ts +1 -0
  298. package/src/opLifecycle/opGroupingManager.ts +82 -0
  299. package/src/opLifecycle/opSplitter.ts +1 -5
  300. package/src/opLifecycle/outbox.ts +64 -26
  301. package/src/opLifecycle/remoteMessageProcessor.ts +38 -22
  302. package/src/packageVersion.ts +1 -1
  303. package/src/pendingStateManager.ts +21 -7
  304. package/src/summary/index.ts +2 -1
  305. package/src/summary/orderedClientElection.ts +17 -1
  306. package/src/summary/runningSummarizer.ts +78 -77
  307. package/src/summary/summarizer.ts +0 -8
  308. package/src/summary/summarizerHeuristics.ts +4 -0
  309. package/src/summary/summarizerNode/summarizerNode.ts +1 -1
  310. package/src/summary/summarizerNode/summarizerNodeWithGc.ts +3 -3
  311. package/src/summary/summarizerTypes.ts +20 -3
  312. package/src/summary/summaryFormat.ts +4 -0
  313. package/src/summary/summaryGenerator.ts +22 -16
  314. package/src/summary/summaryManager.ts +2 -0
@@ -15,9 +15,15 @@ import {
15
15
  } from "@fluidframework/telemetry-utils";
16
16
  import { ICompressionRuntimeOptions } from "../containerRuntime";
17
17
  import { PendingStateManager } from "../pendingStateManager";
18
- import { BatchManager, estimateSocketSize } from "./batchManager";
18
+ import {
19
+ BatchManager,
20
+ BatchSequenceNumbers,
21
+ estimateSocketSize,
22
+ sequenceNumbersMatch,
23
+ } from "./batchManager";
19
24
  import { BatchMessage, IBatch } from "./definitions";
20
25
  import { OpCompressor } from "./opCompressor";
26
+ import { OpGroupingManager } from "./opGroupingManager";
21
27
  import { OpSplitter } from "./opSplitter";
22
28
 
23
29
  export interface IOutboxConfig {
@@ -35,6 +41,21 @@ export interface IOutboxParameters {
35
41
  readonly compressor: OpCompressor;
36
42
  readonly splitter: OpSplitter;
37
43
  readonly logger: ITelemetryLogger;
44
+ readonly groupingManager: OpGroupingManager;
45
+ readonly getCurrentSequenceNumbers: () => BatchSequenceNumbers;
46
+ }
47
+
48
+ function getLongStack(action: () => Error): Error {
49
+ // Increase the stack trace limit temporarily, so as to debug better in case it occurs.
50
+ try {
51
+ const originalStackTraceLimit = (Error as any).stackTraceLimit;
52
+ (Error as any).stackTraceLimit = 50;
53
+ const result = action();
54
+ (Error as any).stackTraceLimit = originalStackTraceLimit;
55
+ return result;
56
+ } catch (error) {
57
+ return action();
58
+ }
38
59
  }
39
60
 
40
61
  export class Outbox {
@@ -74,39 +95,39 @@ export class Outbox {
74
95
  * what was already in the batch managers, this means that batching has been interrupted so
75
96
  * we will flush the accumulated messages to account for that and create a new batch with the new
76
97
  * message as the first message.
77
- *
78
- * @param message - the incoming message
79
98
  */
80
- private maybeFlushPartialBatch(message: BatchMessage) {
81
- const mainBatchReference = this.mainBatch.referenceSequenceNumber;
82
- const attachFlowBatchReference = this.attachFlowBatch.referenceSequenceNumber;
99
+ private maybeFlushPartialBatch() {
100
+ const mainBatchSeqNums = this.mainBatch.sequenceNumbers;
101
+ const attachFlowBatchSeqNums = this.attachFlowBatch.sequenceNumbers;
83
102
  assert(
84
103
  this.params.config.disablePartialFlush ||
85
- mainBatchReference === undefined ||
86
- attachFlowBatchReference === undefined ||
87
- mainBatchReference === attachFlowBatchReference,
104
+ sequenceNumbersMatch(mainBatchSeqNums, attachFlowBatchSeqNums),
88
105
  0x58d /* Reference sequence numbers from both batches must be in sync */,
89
106
  );
90
107
 
108
+ const currentSequenceNumbers = this.params.getCurrentSequenceNumbers();
109
+
91
110
  if (
92
- (mainBatchReference === undefined ||
93
- mainBatchReference === message.referenceSequenceNumber) &&
94
- (attachFlowBatchReference === undefined ||
95
- attachFlowBatchReference === message.referenceSequenceNumber)
111
+ sequenceNumbersMatch(mainBatchSeqNums, currentSequenceNumbers) &&
112
+ sequenceNumbersMatch(attachFlowBatchSeqNums, currentSequenceNumbers)
96
113
  ) {
97
114
  // The reference sequence numbers are stable, there is nothing to do
98
115
  return;
99
116
  }
100
117
 
101
118
  if (++this.mismatchedOpsReported <= this.maxMismatchedOpsToReport) {
102
- this.mc.logger.sendErrorEvent(
119
+ this.mc.logger.sendTelemetryEvent(
103
120
  {
121
+ category: this.params.config.disablePartialFlush ? "error" : "generic",
104
122
  eventName: "ReferenceSequenceNumberMismatch",
105
- mainReferenceSequenceNumber: mainBatchReference,
106
- attachReferenceSequenceNumber: attachFlowBatchReference,
107
- messageReferenceSequenceNumber: message.referenceSequenceNumber,
123
+ mainReferenceSequenceNumber: mainBatchSeqNums.referenceSequenceNumber,
124
+ mainClientSequenceNumber: mainBatchSeqNums.clientSequenceNumber,
125
+ attachReferenceSequenceNumber: attachFlowBatchSeqNums.referenceSequenceNumber,
126
+ attachClientSequenceNumber: attachFlowBatchSeqNums.clientSequenceNumber,
127
+ currentReferenceSequenceNumber: currentSequenceNumbers.referenceSequenceNumber,
128
+ currentClientSequenceNumber: currentSequenceNumbers.clientSequenceNumber,
108
129
  },
109
- new UsageError("Submission of an out of order message"),
130
+ getLongStack(() => new UsageError("Submission of an out of order message")),
110
131
  );
111
132
  }
112
133
 
@@ -116,9 +137,14 @@ export class Outbox {
116
137
  }
117
138
 
118
139
  public submit(message: BatchMessage) {
119
- this.maybeFlushPartialBatch(message);
140
+ this.maybeFlushPartialBatch();
120
141
 
121
- if (!this.mainBatch.push(message)) {
142
+ if (
143
+ !this.mainBatch.push(
144
+ message,
145
+ this.params.getCurrentSequenceNumbers().clientSequenceNumber,
146
+ )
147
+ ) {
122
148
  throw new GenericError("BatchTooLarge", /* error */ undefined, {
123
149
  opSize: message.contents?.length ?? 0,
124
150
  batchSize: this.mainBatch.contentSizeInBytes,
@@ -129,14 +155,24 @@ export class Outbox {
129
155
  }
130
156
 
131
157
  public submitAttach(message: BatchMessage) {
132
- this.maybeFlushPartialBatch(message);
158
+ this.maybeFlushPartialBatch();
133
159
 
134
- if (!this.attachFlowBatch.push(message)) {
160
+ if (
161
+ !this.attachFlowBatch.push(
162
+ message,
163
+ this.params.getCurrentSequenceNumbers().clientSequenceNumber,
164
+ )
165
+ ) {
135
166
  // BatchManager has two limits - soft limit & hard limit. Soft limit is only engaged
136
167
  // when queue is not empty.
137
168
  // Flush queue & retry. Failure on retry would mean - single message is bigger than hard limit
138
169
  this.flushInternal(this.attachFlowBatch.popBatch());
139
- if (!this.attachFlowBatch.push(message)) {
170
+ if (
171
+ !this.attachFlowBatch.push(
172
+ message,
173
+ this.params.getCurrentSequenceNumbers().clientSequenceNumber,
174
+ )
175
+ ) {
140
176
  throw new GenericError("BatchTooLarge", /* error */ undefined, {
141
177
  opSize: message.contents?.length ?? 0,
142
178
  batchSize: this.attachFlowBatch.contentSizeInBytes,
@@ -180,15 +216,17 @@ export class Outbox {
180
216
  this.params.containerContext.submitBatchFn === undefined
181
217
  ) {
182
218
  // Nothing to do if the batch is empty or if compression is disabled or not supported, or if we don't need to compress
183
- return batch;
219
+ return this.params.groupingManager.groupBatch(batch);
184
220
  }
185
221
 
186
- const compressedBatch = this.params.compressor.compressBatch(batch);
222
+ const compressedBatch = this.params.groupingManager.groupBatch(
223
+ this.params.compressor.compressBatch(batch),
224
+ );
187
225
 
188
226
  if (this.params.splitter.isBatchChunkingEnabled) {
189
227
  return compressedBatch.contentSizeInBytes <= this.params.splitter.chunkSizeInBytes
190
228
  ? compressedBatch
191
- : this.params.splitter.splitCompressedBatch(compressedBatch);
229
+ : this.params.splitter.splitFirstBatchMessage(compressedBatch);
192
230
  }
193
231
 
194
232
  if (compressedBatch.contentSizeInBytes >= this.params.config.maxBatchSizeInBytes) {
@@ -6,12 +6,14 @@
6
6
  import { ISequencedDocumentMessage, MessageType } from "@fluidframework/protocol-definitions";
7
7
  import { ContainerMessageType, ContainerRuntimeMessage } from "../containerRuntime";
8
8
  import { OpDecompressor } from "./opDecompressor";
9
+ import { OpGroupingManager } from "./opGroupingManager";
9
10
  import { OpSplitter } from "./opSplitter";
10
11
 
11
12
  export class RemoteMessageProcessor {
12
13
  constructor(
13
14
  private readonly opSplitter: OpSplitter,
14
15
  private readonly opDecompressor: OpDecompressor,
16
+ private readonly opGroupingManager: OpGroupingManager,
15
17
  ) {}
16
18
 
17
19
  public get partialMessages(): ReadonlyMap<string, string[]> {
@@ -22,30 +24,44 @@ export class RemoteMessageProcessor {
22
24
  this.opSplitter.clearPartialChunks(clientId);
23
25
  }
24
26
 
25
- public process(remoteMessage: ISequencedDocumentMessage): ISequencedDocumentMessage {
26
- let message = copy(remoteMessage);
27
- message = this.opDecompressor.processMessage(message).message;
28
- unpackRuntimeMessage(message);
29
-
30
- const chunkProcessingResult = this.opSplitter.processRemoteMessage(message);
31
- message = chunkProcessingResult.message;
32
- if (chunkProcessingResult.state !== "Processed") {
33
- // If the message is not chunked or if the splitter is still rebuilding the original message,
34
- // there is no need to continue processing
35
- return message;
36
- }
27
+ public process(remoteMessage: ISequencedDocumentMessage): ISequencedDocumentMessage[] {
28
+ const result: ISequencedDocumentMessage[] = [];
37
29
 
38
- const decompressionAfterChunking = this.opDecompressor.processMessage(message);
39
- message = decompressionAfterChunking.message;
40
- if (decompressionAfterChunking.state === "Skipped") {
41
- // After chunking, if the original message was not compressed,
42
- // there is no need to continue processing
43
- return message;
44
- }
30
+ // Ungroup before processing chunks
31
+ for (let ungroupedMessage of this.opGroupingManager.ungroupOp(copy(remoteMessage))) {
32
+ ungroupedMessage = this.opDecompressor.processMessage(ungroupedMessage).message;
33
+ unpackRuntimeMessage(ungroupedMessage);
45
34
 
46
- // The message needs to be unpacked after chunking + decompression
47
- unpack(message);
48
- return message;
35
+ const chunkProcessingResult = this.opSplitter.processRemoteMessage(ungroupedMessage);
36
+ ungroupedMessage = chunkProcessingResult.message;
37
+ if (chunkProcessingResult.state !== "Processed") {
38
+ // If the message is not chunked or if the splitter is still rebuilding the original message,
39
+ // there is no need to continue processing
40
+ result.push(ungroupedMessage);
41
+ continue;
42
+ }
43
+
44
+ // Ungroup the chunked message before decompressing
45
+ for (let ungroupedMessageAfterChunking of this.opGroupingManager.ungroupOp(
46
+ ungroupedMessage,
47
+ )) {
48
+ const decompressionAfterChunking = this.opDecompressor.processMessage(
49
+ ungroupedMessageAfterChunking,
50
+ );
51
+ ungroupedMessageAfterChunking = decompressionAfterChunking.message;
52
+ if (decompressionAfterChunking.state === "Skipped") {
53
+ // After chunking, if the original message was not compressed,
54
+ // there is no need to continue processing
55
+ result.push(ungroupedMessageAfterChunking);
56
+ continue;
57
+ }
58
+
59
+ // The message needs to be unpacked after chunking + decompression
60
+ unpack(ungroupedMessageAfterChunking);
61
+ result.push(ungroupedMessageAfterChunking);
62
+ }
63
+ }
64
+ return result;
49
65
  }
50
66
  }
51
67
 
@@ -6,4 +6,4 @@
6
6
  */
7
7
 
8
8
  export const pkgName = "@fluidframework/container-runtime";
9
- export const pkgVersion = "2.0.0-dev.4.1.0.148229";
9
+ export const pkgVersion = "2.0.0-dev.4.3.0.157531";
@@ -49,10 +49,7 @@ export interface IRuntimeStateHandler {
49
49
  connected(): boolean;
50
50
  clientId(): string | undefined;
51
51
  close(error?: ICriticalContainerError): void;
52
- applyStashedOp: (
53
- type: ContainerMessageType,
54
- content: ISequencedDocumentMessage,
55
- ) => Promise<unknown>;
52
+ applyStashedOp: (type: ContainerMessageType, content: unknown) => Promise<unknown>;
56
53
  reSubmit(
57
54
  type: ContainerMessageType,
58
55
  content: any,
@@ -110,9 +107,20 @@ export class PendingStateManager implements IDisposable {
110
107
  return {
111
108
  // delete localOpMetadata since it may not be serializable
112
109
  // and will be regenerated by applyStashedOp()
113
- pendingStates: this.pendingMessages
114
- .toArray()
115
- .map((message) => ({ ...message, localOpMetadata: undefined })),
110
+ pendingStates: this.pendingMessages.toArray().map((message) =>
111
+ // IdAllocations need their localOpMetadata stashed in the contents
112
+ // of the op to correctly resume the session when processing stashed ops
113
+ message.messageType === ContainerMessageType.IdAllocation
114
+ ? {
115
+ ...message,
116
+ content: {
117
+ ...message.content,
118
+ stashedState: message.localOpMetadata,
119
+ },
120
+ localOpMetadata: undefined,
121
+ }
122
+ : { ...message, localOpMetadata: undefined },
123
+ ),
116
124
  };
117
125
  }
118
126
  }
@@ -211,6 +219,12 @@ export class PendingStateManager implements IDisposable {
211
219
  );
212
220
  nextMessage.localOpMetadata = localOpMetadata;
213
221
 
222
+ if (nextMessage.messageType === ContainerMessageType.IdAllocation) {
223
+ // Remove the stashed state from the op
224
+ // so that it doesn't go over the wire
225
+ delete nextMessage.content.stashedState;
226
+ }
227
+
214
228
  // then we push onto pendingMessages which will cause PendingStateManager to resubmit when we connect
215
229
  // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
216
230
  this.pendingMessages.push(this.initialMessages.shift()!);
@@ -94,8 +94,9 @@ export {
94
94
  rootHasIsolatedChannels,
95
95
  WriteFluidDataStoreAttributes,
96
96
  wrapSummaryInChannelsTree,
97
+ idCompressorBlobName,
97
98
  } from "./summaryFormat";
98
- export { SummarizeReason } from "./summaryGenerator";
99
+ export { getFailMessage, SummarizeReason } from "./summaryGenerator";
99
100
  export {
100
101
  IConnectedEvents,
101
102
  IConnectedState,
@@ -336,7 +336,7 @@ export class OrderedClientElection
336
336
  }
337
337
 
338
338
  constructor(
339
- logger: ITelemetryLogger,
339
+ private readonly logger: ITelemetryLogger,
340
340
  private readonly orderedClientCollection: IOrderedClientCollection,
341
341
  /** Serialized state from summary or current sequence number at time of load if new. */
342
342
  initialState: ISerializedElection | number,
@@ -416,6 +416,14 @@ export class OrderedClientElection
416
416
  change = true;
417
417
  }
418
418
  if (change) {
419
+ if (isSummarizerClient) {
420
+ this.logger.sendTelemetryEvent({
421
+ eventName: "SummarizerClientElected",
422
+ electedClientId: this._electedClient?.clientId,
423
+ electedParentId: this._electedParent?.clientId,
424
+ electionSequenceNumber: sequenceNumber,
425
+ });
426
+ }
419
427
  this.emit("election", client, sequenceNumber, prevClient);
420
428
  }
421
429
  }
@@ -423,6 +431,14 @@ export class OrderedClientElection
423
431
  private tryElectingParent(client: ILinkedClient | undefined, sequenceNumber: number): void {
424
432
  if (this._electedParent !== client) {
425
433
  this._electedParent = client;
434
+ if (client?.client.details.type === summarizerClientType) {
435
+ this.logger.sendTelemetryEvent({
436
+ eventName: "SummarizerParentElected",
437
+ electedClientId: this._electedClient?.clientId,
438
+ electedParentId: this._electedParent?.clientId,
439
+ electionSequenceNumber: sequenceNumber,
440
+ });
441
+ }
426
442
  this.emit("election", this._electedClient, sequenceNumber, this._electedClient);
427
443
  }
428
444
  }
@@ -46,6 +46,7 @@ import {
46
46
  const maxSummarizeAckWaitTime = 10 * 60 * 1000; // 10 minutes
47
47
 
48
48
  const defaultNumberSummarizationAttempts = 2; // only up to 2 attempts
49
+
49
50
  /**
50
51
  * An instance of RunningSummarizer manages the heuristics for summarizing.
51
52
  * Until disposed, the instance of RunningSummarizer can assume that it is
@@ -61,7 +62,6 @@ export class RunningSummarizer implements IDisposable {
61
62
  submitSummaryCallback: (options: ISubmitSummaryOptions) => Promise<SubmitSummaryResult>,
62
63
  refreshLatestSummaryAckCallback: (options: IRefreshSummaryAckOptions) => Promise<void>,
63
64
  heuristicData: ISummarizeHeuristicData,
64
- raiseSummarizingError: (errorMessage: string) => void,
65
65
  summaryCollection: SummaryCollection,
66
66
  cancellationToken: ISummaryCancellationToken,
67
67
  stopSummarizerCallback: (reason: SummarizerStopReason) => void,
@@ -74,7 +74,6 @@ export class RunningSummarizer implements IDisposable {
74
74
  submitSummaryCallback,
75
75
  refreshLatestSummaryAckCallback,
76
76
  heuristicData,
77
- raiseSummarizingError,
78
77
  summaryCollection,
79
78
  cancellationToken,
80
79
  stopSummarizerCallback,
@@ -146,6 +145,9 @@ export class RunningSummarizer implements IDisposable {
146
145
  private totalSuccessfulAttempts = 0;
147
146
  private initialized = false;
148
147
 
148
+ private readonly deltaManagerListener;
149
+ private readonly runtimeListener;
150
+
149
151
  private constructor(
150
152
  baseLogger: ITelemetryLogger,
151
153
  private readonly summaryWatcher: IClientSummaryWatcher,
@@ -157,7 +159,6 @@ export class RunningSummarizer implements IDisposable {
157
159
  options: IRefreshSummaryAckOptions,
158
160
  ) => Promise<void>,
159
161
  private readonly heuristicData: ISummarizeHeuristicData,
160
- private readonly raiseSummarizingError: (errorMessage: string) => void,
161
162
  private readonly summaryCollection: SummaryCollection,
162
163
  private readonly cancellationToken: ISummaryCancellationToken,
163
164
  private readonly stopSummarizerCallback: (reason: SummarizerStopReason) => void,
@@ -198,13 +199,12 @@ export class RunningSummarizer implements IDisposable {
198
199
  const maxAckWaitTime = Math.min(this.configuration.maxAckWaitTime, maxSummarizeAckWaitTime);
199
200
 
200
201
  this.pendingAckTimer = new PromiseTimer(maxAckWaitTime, () => {
201
- // pre-0.58 error message: summaryAckWaitTimeout
202
- this.raiseSummarizingError("Pending summary ack not received in time");
203
202
  // Note: summarizeCount (from ChildLogger definition) may be 0,
204
203
  // since this code path is hit when RunningSummarizer first starts up,
205
204
  // before this instance has kicked off a new summarize run.
206
205
  this.mc.logger.sendErrorEvent({
207
206
  eventName: "SummaryAckWaitTimeout",
207
+ message: "Pending summary ack not received in time",
208
208
  maxAckWaitTime,
209
209
  referenceSequenceNumber: this.heuristicData.lastAttempt.refSequenceNumber,
210
210
  summarySequenceNumber: this.heuristicData.lastAttempt.summarySequenceNumber,
@@ -227,7 +227,6 @@ export class RunningSummarizer implements IDisposable {
227
227
  this.pendingAckTimer,
228
228
  this.heuristicData,
229
229
  this.submitSummaryCallback,
230
- this.raiseSummarizingError,
231
230
  () => {
232
231
  this.totalSuccessfulAttempts++;
233
232
  },
@@ -235,10 +234,25 @@ export class RunningSummarizer implements IDisposable {
235
234
  this.mc.logger,
236
235
  );
237
236
 
238
- // Listen for ops
239
- this.runtime.deltaManager.on("op", (op) => {
240
- this.handleOp(op);
241
- });
237
+ // Listen to deltaManager for non-runtime ops
238
+ this.deltaManagerListener = (op) => {
239
+ if (!isRuntimeMessage(op)) {
240
+ this.handleOp(op, false);
241
+ }
242
+ };
243
+
244
+ // Listen to runtime for runtime ops
245
+ this.runtimeListener = (op, runtimeMessage) => {
246
+ if (runtimeMessage) {
247
+ this.handleOp(op, true);
248
+ }
249
+ };
250
+
251
+ // Purpose of listening to deltaManager is for back-compat
252
+ // Can remove and only listen to runtime once loader version is past 2.0.0-internal.1.2.0 (https://github.com/microsoft/FluidFramework/pull/11832)
253
+ // Tracked by AB#3883
254
+ this.runtime.deltaManager.on("op", this.deltaManagerListener);
255
+ this.runtime.on?.("op", this.runtimeListener);
242
256
  }
243
257
 
244
258
  private async handleSummaryAck(): Promise<number> {
@@ -248,67 +262,54 @@ export class RunningSummarizer implements IDisposable {
248
262
  if (lastAck !== undefined) {
249
263
  refSequenceNumber = lastAck.summaryOp.referenceSequenceNumber;
250
264
  const summaryLogger = this.tryGetCorrelatedLogger(refSequenceNumber) ?? this.mc.logger;
251
- try {
252
- const summaryOpHandle = lastAck.summaryOp.contents.handle;
253
- const summaryAckHandle = lastAck.summaryAck.contents.handle;
254
- while (this.summarizingLock !== undefined) {
255
- summaryLogger.sendTelemetryEvent({
256
- eventName: "RefreshAttemptWithSummarizerRunning",
257
- referenceSequenceNumber: refSequenceNumber,
265
+ const summaryOpHandle = lastAck.summaryOp.contents.handle;
266
+ const summaryAckHandle = lastAck.summaryAck.contents.handle;
267
+ while (this.summarizingLock !== undefined) {
268
+ summaryLogger.sendTelemetryEvent({
269
+ eventName: "RefreshAttemptWithSummarizerRunning",
270
+ referenceSequenceNumber: refSequenceNumber,
271
+ proposalHandle: summaryOpHandle,
272
+ ackHandle: summaryAckHandle,
273
+ });
274
+ await this.summarizingLock;
275
+ }
276
+
277
+ // Make sure we block any summarizer from being executed/enqueued while
278
+ // executing the refreshLatestSummaryAck.
279
+ // https://dev.azure.com/fluidframework/internal/_workitems/edit/779
280
+ await this.lockedSummaryAction(
281
+ () => {},
282
+ async () =>
283
+ this.refreshLatestSummaryAckCallback({
258
284
  proposalHandle: summaryOpHandle,
259
285
  ackHandle: summaryAckHandle,
260
- });
261
- await this.summarizingLock;
262
- }
263
-
264
- // Make sure we block any summarizer from being executed/enqueued while
265
- // executing the refreshLatestSummaryAck.
266
- // https://dev.azure.com/fluidframework/internal/_workitems/edit/779
267
- await this.lockedSummaryAction(
268
- () => {},
269
- async () =>
270
- this.refreshLatestSummaryAckCallback({
271
- proposalHandle: summaryOpHandle,
272
- ackHandle: summaryAckHandle,
273
- summaryRefSeq: refSequenceNumber,
274
- summaryLogger,
275
- }).catch(async (error) => {
276
- // If the error is 404, so maybe the fetched version no longer exists on server. We just
277
- // ignore this error in that case, as that means we will have another summaryAck for the
278
- // latest version with which we will refresh the state. However in case of single commit
279
- // summary, we might me missing a summary ack, so in that case we are still fine as the
280
- // code in `submitSummary` function in container runtime, will refresh the latest state
281
- // by calling `refreshLatestSummaryAckFromServer` and we will be fine.
282
- if (
283
- isFluidError(error) &&
284
- error.errorType === DriverErrorType.fileNotFoundOrAccessDeniedError
285
- ) {
286
- summaryLogger.sendTelemetryEvent(
287
- {
288
- eventName: "HandleSummaryAckErrorIgnored",
289
- referenceSequenceNumber: refSequenceNumber,
290
- proposalHandle: summaryOpHandle,
291
- ackHandle: summaryAckHandle,
292
- },
293
- error,
294
- );
295
- } else {
296
- throw error;
297
- }
298
- }),
299
- () => {},
300
- );
301
- } catch (error) {
302
- summaryLogger.sendErrorEvent(
303
- {
304
- eventName: "HandleLastSummaryAckError",
305
- referenceSequenceNumber: refSequenceNumber,
306
- handle: lastAck?.summaryOp?.contents?.handle,
307
- ackHandle: lastAck?.summaryAck?.contents?.handle,
308
- },
309
- error,
310
- );
311
- }
286
+ summaryRefSeq: refSequenceNumber,
287
+ summaryLogger,
288
+ }).catch(async (error) => {
289
+ // If the error is 404, so maybe the fetched version no longer exists on server. We just
290
+ // ignore this error in that case, as that means we will have another summaryAck for the
291
+ // latest version with which we will refresh the state. However in case of single commit
292
+ // summary, we might me missing a summary ack, so in that case we are still fine as the
293
+ // code in `submitSummary` function in container runtime, will refresh the latest state
294
+ // by calling `refreshLatestSummaryAckFromServer` and we will be fine.
295
+ const isIgnoredError =
296
+ isFluidError(error) &&
297
+ error.errorType === DriverErrorType.fileNotFoundOrAccessDeniedError;
298
+
299
+ summaryLogger.sendTelemetryEvent(
300
+ {
301
+ eventName: isIgnoredError
302
+ ? "HandleSummaryAckErrorIgnored"
303
+ : "HandleLastSummaryAckError",
304
+ referenceSequenceNumber: refSequenceNumber,
305
+ proposalHandle: summaryOpHandle,
306
+ ackHandle: summaryAckHandle,
307
+ },
308
+ error,
309
+ );
310
+ }),
311
+ () => {},
312
+ );
312
313
  refSequenceNumber++;
313
314
  }
314
315
  return refSequenceNumber;
@@ -345,9 +346,8 @@ export class RunningSummarizer implements IDisposable {
345
346
  }
346
347
 
347
348
  public dispose(): void {
348
- this.runtime.deltaManager.off("op", (op) => {
349
- this.handleOp(op);
350
- });
349
+ this.runtime.deltaManager.off("op", this.deltaManagerListener);
350
+ this.runtime.off?.("op", this.runtimeListener);
351
351
  this.summaryWatcher.dispose();
352
352
  this.heuristicRunner?.dispose();
353
353
  this.heuristicRunner = undefined;
@@ -372,10 +372,10 @@ export class RunningSummarizer implements IDisposable {
372
372
  /** We only want a single heuristic runner micro-task (will provide better optimized grouping of ops) */
373
373
  private heuristicRunnerMicroTaskExists = false;
374
374
 
375
- public handleOp(op: ISequencedDocumentMessage) {
375
+ public handleOp(op: ISequencedDocumentMessage, runtimeMessage: boolean) {
376
376
  this.heuristicData.lastOpSequenceNumber = op.sequenceNumber;
377
377
 
378
- if (isRuntimeMessage(op)) {
378
+ if (runtimeMessage) {
379
379
  this.heuristicData.numRuntimeOps++;
380
380
  } else {
381
381
  this.heuristicData.numNonRuntimeOps++;
@@ -386,7 +386,7 @@ export class RunningSummarizer implements IDisposable {
386
386
  // Check for enqueued on-demand summaries; Intentionally do nothing otherwise
387
387
  if (
388
388
  this.initialized &&
389
- this.opCanTriggerSummary(op) &&
389
+ this.opCanTriggerSummary(op, runtimeMessage) &&
390
390
  !this.tryRunEnqueuedSummary() &&
391
391
  !this.heuristicRunnerMicroTaskExists
392
392
  ) {
@@ -407,14 +407,14 @@ export class RunningSummarizer implements IDisposable {
407
407
  * @param op - op to check
408
408
  * @returns true if this op can trigger a summary
409
409
  */
410
- private opCanTriggerSummary(op: ISequencedDocumentMessage): boolean {
410
+ private opCanTriggerSummary(op: ISequencedDocumentMessage, runtimeMessage: boolean): boolean {
411
411
  switch (op.type) {
412
412
  case MessageType.Summarize:
413
413
  case MessageType.SummaryAck:
414
414
  case MessageType.SummaryNack:
415
415
  return false;
416
416
  default:
417
- return isRuntimeMessage(op) || this.nonRuntimeOpCanTriggerSummary();
417
+ return runtimeMessage || this.nonRuntimeOpCanTriggerSummary();
418
418
  }
419
419
  }
420
420
 
@@ -646,6 +646,7 @@ export class RunningSummarizer implements IDisposable {
646
646
  if (result.success) {
647
647
  return;
648
648
  }
649
+
649
650
  // Check for retryDelay that can come from summaryNack or upload summary flow.
650
651
  // Retry the same step only once per retryAfter response.
651
652
  overrideDelaySeconds = result.retryAfterSeconds;
@@ -263,14 +263,6 @@ export class Summarizer extends EventEmitter implements ISummarizer {
263
263
  refSequenceNumber: this.runtime.deltaManager.initialSequenceNumber,
264
264
  summaryTime: Date.now(),
265
265
  } as const),
266
- (errorMessage: string) => {
267
- if (!this._disposed) {
268
- this.logger.sendErrorEvent(
269
- { eventName: "summarizingError" },
270
- createSummarizingWarning(errorMessage, true),
271
- );
272
- }
273
- },
274
266
  this.summaryCollection,
275
267
  runCoordinator /* cancellationToken */,
276
268
  (reason) => runCoordinator.stop(reason) /* stopSummarizerCallback */,
@@ -26,6 +26,10 @@ export class SummarizeHeuristicData implements ISummarizeHeuristicData {
26
26
  return this._lastSuccessfulSummary;
27
27
  }
28
28
 
29
+ public get opsSinceLastSummary(): number {
30
+ return this.numSystemOpsBefore + this.numNonSystemOpsBefore;
31
+ }
32
+
29
33
  public numNonRuntimeOps: number = 0;
30
34
  public totalOpsSize: number = 0;
31
35
  public hasMissingOpData: boolean = false;
@@ -164,7 +164,7 @@ export class SummarizerNode implements IRootSummarizerNode {
164
164
  // complains if this assert isn't done this way
165
165
  assert(
166
166
  this.wipReferenceSequenceNumber !== undefined,
167
- "Summarize should not be called when not tracking the summary",
167
+ 0x5df /* Summarize should not be called when not tracking the summary */,
168
168
  );
169
169
  const incrementalSummaryContext: IExperimentalIncrementalSummaryContext | undefined =
170
170
  this._latestSummary !== undefined
@@ -69,7 +69,7 @@ class SummaryNodeWithGC extends SummaryNode {
69
69
  * - Adds trackState param to summarize. If trackState is false, it bypasses the SummarizerNode and calls
70
70
  * directly into summarizeInternal method.
71
71
  */
72
- class SummarizerNodeWithGC extends SummarizerNode implements IRootSummarizerNodeWithGC {
72
+ export class SummarizerNodeWithGC extends SummarizerNode implements IRootSummarizerNodeWithGC {
73
73
  // Tracks the work-in-progress used routes during summary.
74
74
  private wipSerializedUsedRoutes: string | undefined;
75
75
 
@@ -536,8 +536,8 @@ class SummarizerNodeWithGC extends SummarizerNode implements IRootSummarizerNode
536
536
  JSON.stringify(newSerializedRoutes),
537
537
  {
538
538
  referenceSequenceNumber: value.referenceSequenceNumber,
539
- basePath: value.basePath,
540
- localPath: value.localPath,
539
+ basePath: child.latestSummary.basePath,
540
+ localPath: child.latestSummary.localPath,
541
541
  },
542
542
  );
543
543
  child.addPendingSummary(key, newLatestSummaryNode);