@fluidframework/container-runtime 2.0.0-internal.3.0.5 → 2.0.0-internal.3.1.1

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 (329) hide show
  1. package/.eslintrc.js +19 -19
  2. package/.mocharc.js +2 -2
  3. package/api-extractor.json +2 -2
  4. package/dist/batchTracker.d.ts.map +1 -1
  5. package/dist/batchTracker.js +2 -1
  6. package/dist/batchTracker.js.map +1 -1
  7. package/dist/blobManager.d.ts +9 -2
  8. package/dist/blobManager.d.ts.map +1 -1
  9. package/dist/blobManager.js +80 -33
  10. package/dist/blobManager.js.map +1 -1
  11. package/dist/connectionTelemetry.d.ts.map +1 -1
  12. package/dist/connectionTelemetry.js +11 -9
  13. package/dist/connectionTelemetry.js.map +1 -1
  14. package/dist/containerHandleContext.d.ts.map +1 -1
  15. package/dist/containerHandleContext.js +3 -1
  16. package/dist/containerHandleContext.js.map +1 -1
  17. package/dist/containerRuntime.d.ts +11 -1
  18. package/dist/containerRuntime.d.ts.map +1 -1
  19. package/dist/containerRuntime.js +116 -72
  20. package/dist/containerRuntime.js.map +1 -1
  21. package/dist/dataStore.d.ts.map +1 -1
  22. package/dist/dataStore.js +11 -9
  23. package/dist/dataStore.js.map +1 -1
  24. package/dist/dataStoreContext.d.ts +18 -13
  25. package/dist/dataStoreContext.d.ts.map +1 -1
  26. package/dist/dataStoreContext.js +68 -55
  27. package/dist/dataStoreContext.js.map +1 -1
  28. package/dist/dataStoreContexts.d.ts.map +1 -1
  29. package/dist/dataStoreContexts.js +7 -3
  30. package/dist/dataStoreContexts.js.map +1 -1
  31. package/dist/dataStoreRegistry.d.ts.map +1 -1
  32. package/dist/dataStoreRegistry.js +3 -1
  33. package/dist/dataStoreRegistry.js.map +1 -1
  34. package/dist/dataStores.d.ts +26 -1
  35. package/dist/dataStores.d.ts.map +1 -1
  36. package/dist/dataStores.js +103 -18
  37. package/dist/dataStores.js.map +1 -1
  38. package/dist/deltaScheduler.d.ts.map +1 -1
  39. package/dist/deltaScheduler.js +8 -3
  40. package/dist/deltaScheduler.js.map +1 -1
  41. package/dist/garbageCollection.d.ts +33 -14
  42. package/dist/garbageCollection.d.ts.map +1 -1
  43. package/dist/garbageCollection.js +178 -92
  44. package/dist/garbageCollection.js.map +1 -1
  45. package/dist/garbageCollectionConstants.d.ts +1 -0
  46. package/dist/garbageCollectionConstants.d.ts.map +1 -1
  47. package/dist/garbageCollectionConstants.js +4 -1
  48. package/dist/garbageCollectionConstants.js.map +1 -1
  49. package/dist/garbageCollectionHelpers.d.ts +26 -0
  50. package/dist/garbageCollectionHelpers.d.ts.map +1 -0
  51. package/dist/garbageCollectionHelpers.js +45 -0
  52. package/dist/garbageCollectionHelpers.js.map +1 -0
  53. package/dist/gcSweepReadyUsageDetection.d.ts +5 -5
  54. package/dist/gcSweepReadyUsageDetection.d.ts.map +1 -1
  55. package/dist/gcSweepReadyUsageDetection.js +14 -10
  56. package/dist/gcSweepReadyUsageDetection.js.map +1 -1
  57. package/dist/index.d.ts +2 -2
  58. package/dist/index.d.ts.map +1 -1
  59. package/dist/index.js.map +1 -1
  60. package/dist/opLifecycle/batchManager.d.ts +5 -5
  61. package/dist/opLifecycle/batchManager.d.ts.map +1 -1
  62. package/dist/opLifecycle/batchManager.js +19 -12
  63. package/dist/opLifecycle/batchManager.js.map +1 -1
  64. package/dist/opLifecycle/definitions.d.ts.map +1 -1
  65. package/dist/opLifecycle/definitions.js.map +1 -1
  66. package/dist/opLifecycle/index.d.ts.map +1 -1
  67. package/dist/opLifecycle/index.js.map +1 -1
  68. package/dist/opLifecycle/opCompressor.d.ts.map +1 -1
  69. package/dist/opLifecycle/opCompressor.js.map +1 -1
  70. package/dist/opLifecycle/opDecompressor.d.ts +0 -4
  71. package/dist/opLifecycle/opDecompressor.d.ts.map +1 -1
  72. package/dist/opLifecycle/opDecompressor.js +7 -43
  73. package/dist/opLifecycle/opDecompressor.js.map +1 -1
  74. package/dist/opLifecycle/opSplitter.d.ts.map +1 -1
  75. package/dist/opLifecycle/opSplitter.js +4 -1
  76. package/dist/opLifecycle/opSplitter.js.map +1 -1
  77. package/dist/opLifecycle/outbox.d.ts.map +1 -1
  78. package/dist/opLifecycle/outbox.js +20 -19
  79. package/dist/opLifecycle/outbox.js.map +1 -1
  80. package/dist/opLifecycle/remoteMessageProcessor.d.ts.map +1 -1
  81. package/dist/opLifecycle/remoteMessageProcessor.js.map +1 -1
  82. package/dist/opProperties.d.ts.map +1 -1
  83. package/dist/opProperties.js +1 -3
  84. package/dist/opProperties.js.map +1 -1
  85. package/dist/orderedClientElection.d.ts.map +1 -1
  86. package/dist/orderedClientElection.js +10 -4
  87. package/dist/orderedClientElection.js.map +1 -1
  88. package/dist/packageVersion.d.ts +1 -1
  89. package/dist/packageVersion.js +1 -1
  90. package/dist/packageVersion.js.map +1 -1
  91. package/dist/pendingStateManager.d.ts +7 -0
  92. package/dist/pendingStateManager.d.ts.map +1 -1
  93. package/dist/pendingStateManager.js +7 -4
  94. package/dist/pendingStateManager.js.map +1 -1
  95. package/dist/runWhileConnectedCoordinator.d.ts.map +1 -1
  96. package/dist/runWhileConnectedCoordinator.js.map +1 -1
  97. package/dist/runningSummarizer.d.ts.map +1 -1
  98. package/dist/runningSummarizer.js +34 -21
  99. package/dist/runningSummarizer.js.map +1 -1
  100. package/dist/scheduleManager.d.ts.map +1 -1
  101. package/dist/scheduleManager.js +3 -2
  102. package/dist/scheduleManager.js.map +1 -1
  103. package/dist/serializedSnapshotStorage.d.ts +2 -2
  104. package/dist/serializedSnapshotStorage.d.ts.map +1 -1
  105. package/dist/serializedSnapshotStorage.js +5 -3
  106. package/dist/serializedSnapshotStorage.js.map +1 -1
  107. package/dist/summarizer.d.ts +2 -2
  108. package/dist/summarizer.d.ts.map +1 -1
  109. package/dist/summarizer.js +37 -17
  110. package/dist/summarizer.js.map +1 -1
  111. package/dist/summarizerClientElection.d.ts.map +1 -1
  112. package/dist/summarizerClientElection.js.map +1 -1
  113. package/dist/summarizerHandle.d.ts.map +1 -1
  114. package/dist/summarizerHandle.js.map +1 -1
  115. package/dist/summarizerHeuristics.d.ts.map +1 -1
  116. package/dist/summarizerHeuristics.js +6 -9
  117. package/dist/summarizerHeuristics.js.map +1 -1
  118. package/dist/summarizerTypes.d.ts +21 -21
  119. package/dist/summarizerTypes.d.ts.map +1 -1
  120. package/dist/summarizerTypes.js.map +1 -1
  121. package/dist/summaryCollection.d.ts.map +1 -1
  122. package/dist/summaryCollection.js +18 -8
  123. package/dist/summaryCollection.js.map +1 -1
  124. package/dist/summaryFormat.d.ts +5 -2
  125. package/dist/summaryFormat.d.ts.map +1 -1
  126. package/dist/summaryFormat.js +18 -10
  127. package/dist/summaryFormat.js.map +1 -1
  128. package/dist/summaryGenerator.d.ts.map +1 -1
  129. package/dist/summaryGenerator.js +35 -16
  130. package/dist/summaryGenerator.js.map +1 -1
  131. package/dist/summaryManager.d.ts.map +1 -1
  132. package/dist/summaryManager.js +21 -9
  133. package/dist/summaryManager.js.map +1 -1
  134. package/dist/throttler.d.ts +2 -2
  135. package/dist/throttler.d.ts.map +1 -1
  136. package/dist/throttler.js +4 -4
  137. package/dist/throttler.js.map +1 -1
  138. package/garbageCollection.md +15 -2
  139. package/lib/batchTracker.d.ts.map +1 -1
  140. package/lib/batchTracker.js +2 -1
  141. package/lib/batchTracker.js.map +1 -1
  142. package/lib/blobManager.d.ts +9 -2
  143. package/lib/blobManager.d.ts.map +1 -1
  144. package/lib/blobManager.js +82 -35
  145. package/lib/blobManager.js.map +1 -1
  146. package/lib/connectionTelemetry.d.ts.map +1 -1
  147. package/lib/connectionTelemetry.js +11 -9
  148. package/lib/connectionTelemetry.js.map +1 -1
  149. package/lib/containerHandleContext.d.ts.map +1 -1
  150. package/lib/containerHandleContext.js +3 -1
  151. package/lib/containerHandleContext.js.map +1 -1
  152. package/lib/containerRuntime.d.ts +11 -1
  153. package/lib/containerRuntime.d.ts.map +1 -1
  154. package/lib/containerRuntime.js +122 -78
  155. package/lib/containerRuntime.js.map +1 -1
  156. package/lib/dataStore.d.ts.map +1 -1
  157. package/lib/dataStore.js +11 -9
  158. package/lib/dataStore.js.map +1 -1
  159. package/lib/dataStoreContext.d.ts +18 -13
  160. package/lib/dataStoreContext.d.ts.map +1 -1
  161. package/lib/dataStoreContext.js +71 -58
  162. package/lib/dataStoreContext.js.map +1 -1
  163. package/lib/dataStoreContexts.d.ts.map +1 -1
  164. package/lib/dataStoreContexts.js +7 -3
  165. package/lib/dataStoreContexts.js.map +1 -1
  166. package/lib/dataStoreRegistry.d.ts.map +1 -1
  167. package/lib/dataStoreRegistry.js +3 -1
  168. package/lib/dataStoreRegistry.js.map +1 -1
  169. package/lib/dataStores.d.ts +26 -1
  170. package/lib/dataStores.d.ts.map +1 -1
  171. package/lib/dataStores.js +109 -24
  172. package/lib/dataStores.js.map +1 -1
  173. package/lib/deltaScheduler.d.ts.map +1 -1
  174. package/lib/deltaScheduler.js +9 -4
  175. package/lib/deltaScheduler.js.map +1 -1
  176. package/lib/garbageCollection.d.ts +33 -14
  177. package/lib/garbageCollection.d.ts.map +1 -1
  178. package/lib/garbageCollection.js +180 -94
  179. package/lib/garbageCollection.js.map +1 -1
  180. package/lib/garbageCollectionConstants.d.ts +1 -0
  181. package/lib/garbageCollectionConstants.d.ts.map +1 -1
  182. package/lib/garbageCollectionConstants.js +3 -0
  183. package/lib/garbageCollectionConstants.js.map +1 -1
  184. package/lib/garbageCollectionHelpers.d.ts +26 -0
  185. package/lib/garbageCollectionHelpers.d.ts.map +1 -0
  186. package/lib/garbageCollectionHelpers.js +40 -0
  187. package/lib/garbageCollectionHelpers.js.map +1 -0
  188. package/lib/gcSweepReadyUsageDetection.d.ts +5 -5
  189. package/lib/gcSweepReadyUsageDetection.d.ts.map +1 -1
  190. package/lib/gcSweepReadyUsageDetection.js +14 -10
  191. package/lib/gcSweepReadyUsageDetection.js.map +1 -1
  192. package/lib/index.d.ts +2 -2
  193. package/lib/index.d.ts.map +1 -1
  194. package/lib/index.js +1 -1
  195. package/lib/index.js.map +1 -1
  196. package/lib/opLifecycle/batchManager.d.ts +5 -5
  197. package/lib/opLifecycle/batchManager.d.ts.map +1 -1
  198. package/lib/opLifecycle/batchManager.js +19 -12
  199. package/lib/opLifecycle/batchManager.js.map +1 -1
  200. package/lib/opLifecycle/definitions.d.ts.map +1 -1
  201. package/lib/opLifecycle/definitions.js.map +1 -1
  202. package/lib/opLifecycle/index.d.ts.map +1 -1
  203. package/lib/opLifecycle/index.js.map +1 -1
  204. package/lib/opLifecycle/opCompressor.d.ts.map +1 -1
  205. package/lib/opLifecycle/opCompressor.js.map +1 -1
  206. package/lib/opLifecycle/opDecompressor.d.ts +0 -4
  207. package/lib/opLifecycle/opDecompressor.d.ts.map +1 -1
  208. package/lib/opLifecycle/opDecompressor.js +7 -43
  209. package/lib/opLifecycle/opDecompressor.js.map +1 -1
  210. package/lib/opLifecycle/opSplitter.d.ts.map +1 -1
  211. package/lib/opLifecycle/opSplitter.js +5 -2
  212. package/lib/opLifecycle/opSplitter.js.map +1 -1
  213. package/lib/opLifecycle/outbox.d.ts.map +1 -1
  214. package/lib/opLifecycle/outbox.js +20 -19
  215. package/lib/opLifecycle/outbox.js.map +1 -1
  216. package/lib/opLifecycle/remoteMessageProcessor.d.ts.map +1 -1
  217. package/lib/opLifecycle/remoteMessageProcessor.js.map +1 -1
  218. package/lib/opProperties.d.ts.map +1 -1
  219. package/lib/opProperties.js +1 -3
  220. package/lib/opProperties.js.map +1 -1
  221. package/lib/orderedClientElection.d.ts.map +1 -1
  222. package/lib/orderedClientElection.js +10 -4
  223. package/lib/orderedClientElection.js.map +1 -1
  224. package/lib/packageVersion.d.ts +1 -1
  225. package/lib/packageVersion.js +1 -1
  226. package/lib/packageVersion.js.map +1 -1
  227. package/lib/pendingStateManager.d.ts +7 -0
  228. package/lib/pendingStateManager.d.ts.map +1 -1
  229. package/lib/pendingStateManager.js +7 -4
  230. package/lib/pendingStateManager.js.map +1 -1
  231. package/lib/runWhileConnectedCoordinator.d.ts.map +1 -1
  232. package/lib/runWhileConnectedCoordinator.js.map +1 -1
  233. package/lib/runningSummarizer.d.ts.map +1 -1
  234. package/lib/runningSummarizer.js +35 -22
  235. package/lib/runningSummarizer.js.map +1 -1
  236. package/lib/scheduleManager.d.ts.map +1 -1
  237. package/lib/scheduleManager.js +3 -2
  238. package/lib/scheduleManager.js.map +1 -1
  239. package/lib/serializedSnapshotStorage.d.ts +2 -2
  240. package/lib/serializedSnapshotStorage.d.ts.map +1 -1
  241. package/lib/serializedSnapshotStorage.js +5 -3
  242. package/lib/serializedSnapshotStorage.js.map +1 -1
  243. package/lib/summarizer.d.ts +2 -2
  244. package/lib/summarizer.d.ts.map +1 -1
  245. package/lib/summarizer.js +37 -17
  246. package/lib/summarizer.js.map +1 -1
  247. package/lib/summarizerClientElection.d.ts.map +1 -1
  248. package/lib/summarizerClientElection.js.map +1 -1
  249. package/lib/summarizerHandle.d.ts.map +1 -1
  250. package/lib/summarizerHandle.js.map +1 -1
  251. package/lib/summarizerHeuristics.d.ts.map +1 -1
  252. package/lib/summarizerHeuristics.js +6 -9
  253. package/lib/summarizerHeuristics.js.map +1 -1
  254. package/lib/summarizerTypes.d.ts +21 -21
  255. package/lib/summarizerTypes.d.ts.map +1 -1
  256. package/lib/summarizerTypes.js.map +1 -1
  257. package/lib/summaryCollection.d.ts.map +1 -1
  258. package/lib/summaryCollection.js +18 -8
  259. package/lib/summaryCollection.js.map +1 -1
  260. package/lib/summaryFormat.d.ts +5 -2
  261. package/lib/summaryFormat.d.ts.map +1 -1
  262. package/lib/summaryFormat.js +20 -12
  263. package/lib/summaryFormat.js.map +1 -1
  264. package/lib/summaryGenerator.d.ts.map +1 -1
  265. package/lib/summaryGenerator.js +35 -16
  266. package/lib/summaryGenerator.js.map +1 -1
  267. package/lib/summaryManager.d.ts.map +1 -1
  268. package/lib/summaryManager.js +21 -9
  269. package/lib/summaryManager.js.map +1 -1
  270. package/lib/throttler.d.ts +2 -2
  271. package/lib/throttler.d.ts.map +1 -1
  272. package/lib/throttler.js +4 -4
  273. package/lib/throttler.js.map +1 -1
  274. package/package.json +121 -115
  275. package/prettier.config.cjs +1 -1
  276. package/src/batchTracker.ts +54 -49
  277. package/src/blobManager.ts +793 -672
  278. package/src/connectionTelemetry.ts +280 -249
  279. package/src/containerHandleContext.ts +27 -29
  280. package/src/containerRuntime.ts +3168 -2988
  281. package/src/dataStore.ts +172 -159
  282. package/src/dataStoreContext.ts +1098 -1055
  283. package/src/dataStoreContexts.ts +178 -161
  284. package/src/dataStoreRegistry.ts +25 -20
  285. package/src/dataStores.ts +884 -728
  286. package/src/deltaScheduler.ts +158 -150
  287. package/src/garbageCollection.ts +1860 -1688
  288. package/src/garbageCollectionConstants.ts +3 -0
  289. package/src/garbageCollectionHelpers.ts +61 -0
  290. package/src/gcSweepReadyUsageDetection.ts +89 -83
  291. package/src/index.ts +67 -66
  292. package/src/opLifecycle/README.md +152 -0
  293. package/src/opLifecycle/batchManager.ts +145 -141
  294. package/src/opLifecycle/definitions.ts +29 -29
  295. package/src/opLifecycle/index.ts +5 -5
  296. package/src/opLifecycle/opCompressor.ts +54 -53
  297. package/src/opLifecycle/opDecompressor.ts +100 -128
  298. package/src/opLifecycle/opSplitter.ts +214 -188
  299. package/src/opLifecycle/outbox.ts +204 -195
  300. package/src/opLifecycle/remoteMessageProcessor.ts +62 -62
  301. package/src/opProperties.ts +11 -9
  302. package/src/orderedClientElection.ts +489 -457
  303. package/src/packageVersion.ts +1 -1
  304. package/src/pendingStateManager.ts +384 -338
  305. package/src/runWhileConnectedCoordinator.ts +78 -71
  306. package/src/runningSummarizer.ts +619 -581
  307. package/src/scheduleManager.ts +299 -269
  308. package/src/serializedSnapshotStorage.ts +126 -112
  309. package/src/summarizer.ts +417 -381
  310. package/src/summarizerClientElection.ts +107 -100
  311. package/src/summarizerHandle.ts +11 -9
  312. package/src/summarizerHeuristics.ts +183 -186
  313. package/src/summarizerTypes.ts +344 -330
  314. package/src/summaryCollection.ts +378 -349
  315. package/src/summaryFormat.ts +165 -143
  316. package/src/summaryGenerator.ts +465 -410
  317. package/src/summaryManager.ts +377 -348
  318. package/src/throttler.ts +131 -122
  319. package/tsconfig.esnext.json +6 -6
  320. package/tsconfig.json +9 -13
  321. package/dist/garbageCollectionTombstoneUtils.d.ts +0 -14
  322. package/dist/garbageCollectionTombstoneUtils.d.ts.map +0 -1
  323. package/dist/garbageCollectionTombstoneUtils.js +0 -23
  324. package/dist/garbageCollectionTombstoneUtils.js.map +0 -1
  325. package/lib/garbageCollectionTombstoneUtils.d.ts +0 -14
  326. package/lib/garbageCollectionTombstoneUtils.d.ts.map +0 -1
  327. package/lib/garbageCollectionTombstoneUtils.js +0 -19
  328. package/lib/garbageCollectionTombstoneUtils.js.map +0 -1
  329. package/src/garbageCollectionTombstoneUtils.ts +0 -28
@@ -10,154 +10,158 @@ import { ICompressionRuntimeOptions } from "../containerRuntime";
10
10
  import { BatchMessage, IBatch, IBatchCheckpoint } from "./definitions";
11
11
 
12
12
  export interface IBatchManagerOptions {
13
- readonly enableOpReentryCheck?: boolean;
14
- readonly hardLimit: number;
15
- readonly softLimit?: number;
16
- readonly compressionOptions?: ICompressionRuntimeOptions;
13
+ readonly enableOpReentryCheck?: boolean;
14
+ readonly hardLimit: number;
15
+ readonly softLimit?: number;
16
+ readonly compressionOptions?: ICompressionRuntimeOptions;
17
17
  }
18
18
 
19
19
  /**
20
20
  * Helper class that manages partial batch & rollback.
21
21
  */
22
22
  export class BatchManager {
23
- private readonly logger;
24
- private pendingBatch: BatchMessage[] = [];
25
- private batchContentSize = 0;
26
- /**
27
- * Track the number of ops which were detected to have a mismatched
28
- * reference sequence number, in order to self-throttle the telemetry events.
29
- *
30
- * This should be removed as part of ADO:2322
31
- */
32
- private readonly maxMismatchedOpsToReport = 5;
33
- private mismatchedOpsReported = 0;
34
-
35
-
36
- public get length() { return this.pendingBatch.length; }
37
- public get contentSizeInBytes() { return this.batchContentSize; }
38
-
39
- constructor(
40
- public readonly options: IBatchManagerOptions,
41
- logger: ITelemetryLogger,
42
- ) {
43
- this.logger = ChildLogger.create(logger, "BatchManager");
44
- }
45
-
46
- public push(message: BatchMessage): boolean {
47
- this.checkReferenceSequenceNumber(message);
48
-
49
- const contentSize = this.batchContentSize + (message.contents?.length ?? 0);
50
- const opCount = this.pendingBatch.length;
51
-
52
- // Attempt to estimate batch size, aka socket message size.
53
- // Each op has pretty large envelope, estimating to be 200 bytes.
54
- // Also content will be strigified, and that adds a lot of overhead due to a lot of escape characters.
55
- // Not taking it into account, as compression work should help there - compressed payload will be
56
- // initially stored as base64, and that requires only 2 extra escape characters.
57
- const socketMessageSize = contentSize + 200 * opCount;
58
-
59
- // If we were provided soft limit, check for exceeding it.
60
- // But only if we have any ops, as the intention here is to flush existing ops (on exceeding this limit)
61
- // and start over. That's not an option if we have no ops.
62
- // If compression is enabled, the soft and hard limit are ignored and the message will be pushed anyways.
63
- // Cases where the message is still too large will be handled by the maxConsecutiveReconnects path.
64
- if (this.options.softLimit !== undefined
65
- && this.length > 0
66
- && socketMessageSize >= this.options.softLimit) {
67
- return false;
68
- }
69
-
70
- if (socketMessageSize >= this.options.hardLimit) {
71
- return false;
72
- }
73
-
74
- this.batchContentSize = contentSize;
75
- this.pendingBatch.push(message);
76
- return true;
77
- }
78
-
79
- public get empty() { return this.pendingBatch.length === 0; }
80
-
81
- public popBatch(): IBatch {
82
- const batch: IBatch = {
83
- content: this.pendingBatch,
84
- contentSizeInBytes: this.batchContentSize,
85
- };
86
-
87
- this.pendingBatch = [];
88
- this.batchContentSize = 0;
89
-
90
- return addBatchMetadata(batch);
91
- }
92
-
93
- /**
94
- * Capture the pending state at this point
95
- */
96
- public checkpoint(): IBatchCheckpoint {
97
- const startPoint = this.pendingBatch.length;
98
- return {
99
- rollback: (process: (message: BatchMessage) => void) => {
100
- for (let i = this.pendingBatch.length; i > startPoint;) {
101
- i--;
102
- const message = this.pendingBatch[i];
103
- this.batchContentSize -= message.contents?.length ?? 0;
104
- process(message);
105
- }
106
-
107
- this.pendingBatch.length = startPoint;
108
- },
109
- };
110
- }
111
-
112
- private checkReferenceSequenceNumber(message: BatchMessage) {
113
- if (this.pendingBatch.length === 0 || message.referenceSequenceNumber === this.pendingBatch[0].referenceSequenceNumber) {
114
- // The reference sequence numbers are stable
115
- return;
116
- }
117
-
118
- const telemetryProperties = {
119
- referenceSequenceNumber: this.pendingBatch[0].referenceSequenceNumber,
120
- messageReferenceSequenceNumber: message.referenceSequenceNumber,
121
- type: message.deserializedContent.type,
122
- length: this.pendingBatch.length,
123
- enableOpReentryCheck: this.options.enableOpReentryCheck === true,
124
- };
125
- const error = new UsageError("Submission of an out of order message");
126
- const eventName = "ReferenceSequenceNumberMismatch";
127
-
128
- if (this.options.enableOpReentryCheck === true) {
129
- this.logger.sendErrorEvent(
130
- { eventName, ...telemetryProperties },
131
- error,
132
- );
133
- throw error;
134
- }
135
-
136
- if (++this.mismatchedOpsReported <= this.maxMismatchedOpsToReport) {
137
- this.logger.sendErrorEvent(
138
- {
139
- eventName,
140
- ...telemetryProperties,
141
- ops: this.mismatchedOpsReported,
142
- maxOps: this.maxMismatchedOpsToReport,
143
- },
144
- error,
145
- );
146
- }
147
- }
23
+ private readonly logger;
24
+ private pendingBatch: BatchMessage[] = [];
25
+ private batchContentSize = 0;
26
+ /**
27
+ * Track the number of ops which were detected to have a mismatched
28
+ * reference sequence number, in order to self-throttle the telemetry events.
29
+ *
30
+ * This should be removed as part of ADO:2322
31
+ */
32
+ private readonly maxMismatchedOpsToReport = 5;
33
+ private mismatchedOpsReported = 0;
34
+
35
+ public get length() {
36
+ return this.pendingBatch.length;
37
+ }
38
+ public get contentSizeInBytes() {
39
+ return this.batchContentSize;
40
+ }
41
+
42
+ constructor(public readonly options: IBatchManagerOptions, logger: ITelemetryLogger) {
43
+ this.logger = ChildLogger.create(logger, "BatchManager");
44
+ }
45
+
46
+ public push(message: BatchMessage): boolean {
47
+ this.checkReferenceSequenceNumber(message);
48
+
49
+ const contentSize = this.batchContentSize + (message.contents?.length ?? 0);
50
+ const opCount = this.pendingBatch.length;
51
+
52
+ // Attempt to estimate batch size, aka socket message size.
53
+ // Each op has pretty large envelope, estimating to be 200 bytes.
54
+ // Also content will be strigified, and that adds a lot of overhead due to a lot of escape characters.
55
+ // Not taking it into account, as compression work should help there - compressed payload will be
56
+ // initially stored as base64, and that requires only 2 extra escape characters.
57
+ const socketMessageSize = contentSize + 200 * opCount;
58
+
59
+ // If we were provided soft limit, check for exceeding it.
60
+ // But only if we have any ops, as the intention here is to flush existing ops (on exceeding this limit)
61
+ // and start over. That's not an option if we have no ops.
62
+ // If compression is enabled, the soft and hard limit are ignored and the message will be pushed anyways.
63
+ // Cases where the message is still too large will be handled by the maxConsecutiveReconnects path.
64
+ if (
65
+ this.options.softLimit !== undefined &&
66
+ this.length > 0 &&
67
+ socketMessageSize >= this.options.softLimit
68
+ ) {
69
+ return false;
70
+ }
71
+
72
+ if (socketMessageSize >= this.options.hardLimit) {
73
+ return false;
74
+ }
75
+
76
+ this.batchContentSize = contentSize;
77
+ this.pendingBatch.push(message);
78
+ return true;
79
+ }
80
+
81
+ public get empty() {
82
+ return this.pendingBatch.length === 0;
83
+ }
84
+
85
+ public popBatch(): IBatch {
86
+ const batch: IBatch = {
87
+ content: this.pendingBatch,
88
+ contentSizeInBytes: this.batchContentSize,
89
+ };
90
+
91
+ this.pendingBatch = [];
92
+ this.batchContentSize = 0;
93
+
94
+ return addBatchMetadata(batch);
95
+ }
96
+
97
+ /**
98
+ * Capture the pending state at this point
99
+ */
100
+ public checkpoint(): IBatchCheckpoint {
101
+ const startPoint = this.pendingBatch.length;
102
+ return {
103
+ rollback: (process: (message: BatchMessage) => void) => {
104
+ for (let i = this.pendingBatch.length; i > startPoint; ) {
105
+ i--;
106
+ const message = this.pendingBatch[i];
107
+ this.batchContentSize -= message.contents?.length ?? 0;
108
+ process(message);
109
+ }
110
+
111
+ this.pendingBatch.length = startPoint;
112
+ },
113
+ };
114
+ }
115
+
116
+ private checkReferenceSequenceNumber(message: BatchMessage) {
117
+ if (
118
+ this.pendingBatch.length === 0 ||
119
+ message.referenceSequenceNumber === this.pendingBatch[0].referenceSequenceNumber
120
+ ) {
121
+ // The reference sequence numbers are stable
122
+ return;
123
+ }
124
+
125
+ const telemetryProperties = {
126
+ referenceSequenceNumber: this.pendingBatch[0].referenceSequenceNumber,
127
+ messageReferenceSequenceNumber: message.referenceSequenceNumber,
128
+ type: message.deserializedContent.type,
129
+ length: this.pendingBatch.length,
130
+ enableOpReentryCheck: this.options.enableOpReentryCheck === true,
131
+ };
132
+ const error = new UsageError("Submission of an out of order message");
133
+ const eventName = "ReferenceSequenceNumberMismatch";
134
+
135
+ if (this.options.enableOpReentryCheck === true) {
136
+ this.logger.sendErrorEvent({ eventName, ...telemetryProperties }, error);
137
+ throw error;
138
+ }
139
+
140
+ if (++this.mismatchedOpsReported <= this.maxMismatchedOpsToReport) {
141
+ this.logger.sendErrorEvent(
142
+ {
143
+ eventName,
144
+ ...telemetryProperties,
145
+ ops: this.mismatchedOpsReported,
146
+ maxOps: this.maxMismatchedOpsToReport,
147
+ },
148
+ error,
149
+ );
150
+ }
151
+ }
148
152
  }
149
153
 
150
154
  const addBatchMetadata = (batch: IBatch): IBatch => {
151
- if (batch.content.length > 1) {
152
- batch.content[0].metadata = {
153
- ...batch.content[0].metadata,
154
- batch: true
155
- };
156
- batch.content[batch.content.length - 1].metadata = {
157
- ...batch.content[batch.content.length - 1].metadata,
158
- batch: false
159
- };
160
- }
161
-
162
- return batch;
155
+ if (batch.content.length > 1) {
156
+ batch.content[0].metadata = {
157
+ ...batch.content[0].metadata,
158
+ batch: true,
159
+ };
160
+ batch.content[batch.content.length - 1].metadata = {
161
+ ...batch.content[batch.content.length - 1].metadata,
162
+ batch: false,
163
+ };
164
+ }
165
+
166
+ return batch;
163
167
  };
@@ -11,38 +11,38 @@ import { CompressionAlgorithms, ContainerMessageType, ContainerRuntimeMessage }
11
11
  * Batch message type used internally by the runtime
12
12
  */
13
13
  export type BatchMessage = IBatchMessage & {
14
- localOpMetadata: unknown;
15
- deserializedContent: ContainerRuntimeMessage;
16
- referenceSequenceNumber: number;
17
- compression?: CompressionAlgorithms;
14
+ localOpMetadata: unknown;
15
+ deserializedContent: ContainerRuntimeMessage;
16
+ referenceSequenceNumber: number;
17
+ compression?: CompressionAlgorithms;
18
18
  };
19
19
 
20
20
  /**
21
21
  * Batch interface used internally by the runtime.
22
22
  */
23
23
  export interface IBatch {
24
- /**
25
- * Sum of the in-memory content sizes of all messages in the batch.
26
- * If the batch is compressed, this number reflects the post-compression size.
27
- */
28
- readonly contentSizeInBytes: number;
29
- /**
30
- * All the messages in the batch
31
- */
32
- readonly content: BatchMessage[];
24
+ /**
25
+ * Sum of the in-memory content sizes of all messages in the batch.
26
+ * If the batch is compressed, this number reflects the post-compression size.
27
+ */
28
+ readonly contentSizeInBytes: number;
29
+ /**
30
+ * All the messages in the batch
31
+ */
32
+ readonly content: BatchMessage[];
33
33
  }
34
34
 
35
35
  export interface IBatchCheckpoint {
36
- rollback: (action: (message: BatchMessage) => void) => void;
36
+ rollback: (action: (message: BatchMessage) => void) => void;
37
37
  }
38
38
 
39
39
  export interface IChunkedOp {
40
- chunkId: number;
41
- totalChunks: number;
42
- contents: string;
43
- originalType: MessageType | ContainerMessageType;
44
- originalMetadata?: Record<string, unknown>;
45
- originalCompression?: string;
40
+ chunkId: number;
41
+ totalChunks: number;
42
+ contents: string;
43
+ originalType: MessageType | ContainerMessageType;
44
+ originalMetadata?: Record<string, unknown>;
45
+ originalCompression?: string;
46
46
  }
47
47
 
48
48
  /**
@@ -58,13 +58,13 @@ export type ProcessingState = "Processed" | "Skipped" | "Accepted";
58
58
  * Return type for functions which process remote messages
59
59
  */
60
60
  export interface IMessageProcessingResult {
61
- /**
62
- * A shallow copy of the input message if processing happened, or
63
- * the original message otherwise
64
- */
65
- readonly message: ISequencedDocumentMessage;
66
- /**
67
- * Processing result of the input message.
68
- */
69
- readonly state: ProcessingState;
61
+ /**
62
+ * A shallow copy of the input message if processing happened, or
63
+ * the original message otherwise
64
+ */
65
+ readonly message: ISequencedDocumentMessage;
66
+ /**
67
+ * Processing result of the input message.
68
+ */
69
+ readonly state: ProcessingState;
70
70
  }
@@ -5,11 +5,11 @@
5
5
 
6
6
  export { BatchManager } from "./batchManager";
7
7
  export {
8
- BatchMessage,
9
- IBatch,
10
- IBatchCheckpoint,
11
- IChunkedOp,
12
- IMessageProcessingResult,
8
+ BatchMessage,
9
+ IBatch,
10
+ IBatchCheckpoint,
11
+ IChunkedOp,
12
+ IMessageProcessingResult,
13
13
  } from "./definitions";
14
14
  export { Outbox } from "./outbox";
15
15
  export { OpCompressor } from "./opCompressor";
@@ -17,65 +17,66 @@ import { IBatch, BatchMessage } from "./definitions";
17
17
  * op to reserve sequence numbers.
18
18
  */
19
19
  export class OpCompressor {
20
- private readonly logger;
20
+ private readonly logger;
21
21
 
22
- constructor(logger: ITelemetryLogger) {
23
- this.logger = ChildLogger.create(logger, "OpCompressor");
24
- }
22
+ constructor(logger: ITelemetryLogger) {
23
+ this.logger = ChildLogger.create(logger, "OpCompressor");
24
+ }
25
25
 
26
- public compressBatch(batch: IBatch): IBatch {
27
- const compressionStart = Date.now();
28
- const contentsAsBuffer = new TextEncoder().encode(this.serializeBatch(batch));
29
- const compressedContents = compress(contentsAsBuffer);
30
- const compressedContent = IsoBuffer.from(compressedContents).toString("base64");
31
- const duration = Date.now() - compressionStart;
26
+ public compressBatch(batch: IBatch): IBatch {
27
+ const compressionStart = Date.now();
28
+ const contentsAsBuffer = new TextEncoder().encode(this.serializeBatch(batch));
29
+ const compressedContents = compress(contentsAsBuffer);
30
+ const compressedContent = IsoBuffer.from(compressedContents).toString("base64");
31
+ const duration = Date.now() - compressionStart;
32
32
 
33
- if (batch.contentSizeInBytes > 200000) {
34
- this.logger.sendPerformanceEvent({
35
- eventName: "CompressedBatch",
36
- duration,
37
- sizeBeforeCompression: batch.contentSizeInBytes,
38
- sizeAfterCompression: compressedContent.length,
39
- });
40
- }
33
+ if (batch.contentSizeInBytes > 200000) {
34
+ this.logger.sendPerformanceEvent({
35
+ eventName: "CompressedBatch",
36
+ duration,
37
+ sizeBeforeCompression: batch.contentSizeInBytes,
38
+ sizeAfterCompression: compressedContent.length,
39
+ });
40
+ }
41
41
 
42
- const messages: BatchMessage[] = [];
43
- messages.push({
44
- ...batch.content[0], contents: JSON.stringify({ packedContents: compressedContent }),
45
- metadata: batch.content[0].metadata,
46
- compression: CompressionAlgorithms.lz4,
47
- });
42
+ const messages: BatchMessage[] = [];
43
+ messages.push({
44
+ ...batch.content[0],
45
+ contents: JSON.stringify({ packedContents: compressedContent }),
46
+ metadata: batch.content[0].metadata,
47
+ compression: CompressionAlgorithms.lz4,
48
+ });
48
49
 
49
- for (const message of batch.content.slice(1)) {
50
- messages.push({ ...message, contents: undefined });
51
- }
50
+ for (const message of batch.content.slice(1)) {
51
+ messages.push({ ...message, contents: undefined });
52
+ }
52
53
 
53
- return {
54
- contentSizeInBytes: compressedContent.length,
55
- content: messages,
56
- };
57
- }
54
+ return {
55
+ contentSizeInBytes: compressedContent.length,
56
+ content: messages,
57
+ };
58
+ }
58
59
 
59
- private serializeBatch(batch: IBatch): string {
60
- try {
61
- return JSON.stringify(batch.content.map((message) => message.deserializedContent))
62
- } catch (e: any) {
63
- if (e.message === "Invalid string length") {
64
- // This is how JSON.stringify signals that
65
- // the content size exceeds its capacity
66
- const error = new UsageError("Payload too large");
67
- this.logger.sendErrorEvent(
68
- {
69
- eventName: "BatchTooLarge",
70
- size: batch.contentSizeInBytes,
71
- length: batch.content.length,
72
- },
73
- error,
74
- );
75
- throw error;
76
- }
60
+ private serializeBatch(batch: IBatch): string {
61
+ try {
62
+ return JSON.stringify(batch.content.map((message) => message.deserializedContent));
63
+ } catch (e: any) {
64
+ if (e.message === "Invalid string length") {
65
+ // This is how JSON.stringify signals that
66
+ // the content size exceeds its capacity
67
+ const error = new UsageError("Payload too large");
68
+ this.logger.sendErrorEvent(
69
+ {
70
+ eventName: "BatchTooLarge",
71
+ size: batch.contentSizeInBytes,
72
+ length: batch.content.length,
73
+ },
74
+ error,
75
+ );
76
+ throw error;
77
+ }
77
78
 
78
- throw e;
79
- }
80
- }
79
+ throw e;
80
+ }
81
+ }
81
82
  }