@fluidframework/container-runtime 2.0.0-internal.3.0.0 → 2.0.0-internal.3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (327) 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 +10 -0
  18. package/dist/containerRuntime.d.ts.map +1 -1
  19. package/dist/containerRuntime.js +140 -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 -1
  25. package/dist/dataStoreContext.d.ts.map +1 -1
  26. package/dist/dataStoreContext.js +66 -15
  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 +34 -14
  42. package/dist/garbageCollection.d.ts.map +1 -1
  43. package/dist/garbageCollection.js +188 -93
  44. package/dist/garbageCollection.js.map +1 -1
  45. package/dist/garbageCollectionConstants.d.ts +3 -0
  46. package/dist/garbageCollectionConstants.d.ts.map +1 -1
  47. package/dist/garbageCollectionConstants.js +6 -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.map +1 -1
  71. package/dist/opLifecycle/opDecompressor.js +5 -2
  72. package/dist/opLifecycle/opDecompressor.js.map +1 -1
  73. package/dist/opLifecycle/opSplitter.d.ts.map +1 -1
  74. package/dist/opLifecycle/opSplitter.js +4 -1
  75. package/dist/opLifecycle/opSplitter.js.map +1 -1
  76. package/dist/opLifecycle/outbox.d.ts.map +1 -1
  77. package/dist/opLifecycle/outbox.js +19 -17
  78. package/dist/opLifecycle/outbox.js.map +1 -1
  79. package/dist/opLifecycle/remoteMessageProcessor.d.ts.map +1 -1
  80. package/dist/opLifecycle/remoteMessageProcessor.js.map +1 -1
  81. package/dist/opProperties.d.ts.map +1 -1
  82. package/dist/opProperties.js +1 -3
  83. package/dist/opProperties.js.map +1 -1
  84. package/dist/orderedClientElection.d.ts.map +1 -1
  85. package/dist/orderedClientElection.js +10 -4
  86. package/dist/orderedClientElection.js.map +1 -1
  87. package/dist/packageVersion.d.ts +1 -1
  88. package/dist/packageVersion.js +1 -1
  89. package/dist/packageVersion.js.map +1 -1
  90. package/dist/pendingStateManager.d.ts +7 -0
  91. package/dist/pendingStateManager.d.ts.map +1 -1
  92. package/dist/pendingStateManager.js +7 -4
  93. package/dist/pendingStateManager.js.map +1 -1
  94. package/dist/runWhileConnectedCoordinator.d.ts.map +1 -1
  95. package/dist/runWhileConnectedCoordinator.js.map +1 -1
  96. package/dist/runningSummarizer.d.ts.map +1 -1
  97. package/dist/runningSummarizer.js +34 -21
  98. package/dist/runningSummarizer.js.map +1 -1
  99. package/dist/scheduleManager.d.ts.map +1 -1
  100. package/dist/scheduleManager.js +3 -2
  101. package/dist/scheduleManager.js.map +1 -1
  102. package/dist/serializedSnapshotStorage.d.ts +2 -2
  103. package/dist/serializedSnapshotStorage.d.ts.map +1 -1
  104. package/dist/serializedSnapshotStorage.js +5 -3
  105. package/dist/serializedSnapshotStorage.js.map +1 -1
  106. package/dist/summarizer.d.ts +2 -2
  107. package/dist/summarizer.d.ts.map +1 -1
  108. package/dist/summarizer.js +37 -17
  109. package/dist/summarizer.js.map +1 -1
  110. package/dist/summarizerClientElection.d.ts.map +1 -1
  111. package/dist/summarizerClientElection.js.map +1 -1
  112. package/dist/summarizerHandle.d.ts.map +1 -1
  113. package/dist/summarizerHandle.js.map +1 -1
  114. package/dist/summarizerHeuristics.d.ts.map +1 -1
  115. package/dist/summarizerHeuristics.js +6 -9
  116. package/dist/summarizerHeuristics.js.map +1 -1
  117. package/dist/summarizerTypes.d.ts +21 -21
  118. package/dist/summarizerTypes.d.ts.map +1 -1
  119. package/dist/summarizerTypes.js.map +1 -1
  120. package/dist/summaryCollection.d.ts.map +1 -1
  121. package/dist/summaryCollection.js +18 -8
  122. package/dist/summaryCollection.js.map +1 -1
  123. package/dist/summaryFormat.d.ts +22 -0
  124. package/dist/summaryFormat.d.ts.map +1 -1
  125. package/dist/summaryFormat.js +18 -10
  126. package/dist/summaryFormat.js.map +1 -1
  127. package/dist/summaryGenerator.d.ts.map +1 -1
  128. package/dist/summaryGenerator.js +34 -15
  129. package/dist/summaryGenerator.js.map +1 -1
  130. package/dist/summaryManager.d.ts.map +1 -1
  131. package/dist/summaryManager.js +21 -9
  132. package/dist/summaryManager.js.map +1 -1
  133. package/dist/throttler.d.ts +2 -2
  134. package/dist/throttler.d.ts.map +1 -1
  135. package/dist/throttler.js +4 -4
  136. package/dist/throttler.js.map +1 -1
  137. package/garbageCollection.md +15 -2
  138. package/lib/batchTracker.d.ts.map +1 -1
  139. package/lib/batchTracker.js +2 -1
  140. package/lib/batchTracker.js.map +1 -1
  141. package/lib/blobManager.d.ts +9 -2
  142. package/lib/blobManager.d.ts.map +1 -1
  143. package/lib/blobManager.js +82 -35
  144. package/lib/blobManager.js.map +1 -1
  145. package/lib/connectionTelemetry.d.ts.map +1 -1
  146. package/lib/connectionTelemetry.js +11 -9
  147. package/lib/connectionTelemetry.js.map +1 -1
  148. package/lib/containerHandleContext.d.ts.map +1 -1
  149. package/lib/containerHandleContext.js +3 -1
  150. package/lib/containerHandleContext.js.map +1 -1
  151. package/lib/containerRuntime.d.ts +10 -0
  152. package/lib/containerRuntime.d.ts.map +1 -1
  153. package/lib/containerRuntime.js +146 -78
  154. package/lib/containerRuntime.js.map +1 -1
  155. package/lib/dataStore.d.ts.map +1 -1
  156. package/lib/dataStore.js +11 -9
  157. package/lib/dataStore.js.map +1 -1
  158. package/lib/dataStoreContext.d.ts +18 -1
  159. package/lib/dataStoreContext.d.ts.map +1 -1
  160. package/lib/dataStoreContext.js +68 -17
  161. package/lib/dataStoreContext.js.map +1 -1
  162. package/lib/dataStoreContexts.d.ts.map +1 -1
  163. package/lib/dataStoreContexts.js +7 -3
  164. package/lib/dataStoreContexts.js.map +1 -1
  165. package/lib/dataStoreRegistry.d.ts.map +1 -1
  166. package/lib/dataStoreRegistry.js +3 -1
  167. package/lib/dataStoreRegistry.js.map +1 -1
  168. package/lib/dataStores.d.ts +26 -1
  169. package/lib/dataStores.d.ts.map +1 -1
  170. package/lib/dataStores.js +109 -24
  171. package/lib/dataStores.js.map +1 -1
  172. package/lib/deltaScheduler.d.ts.map +1 -1
  173. package/lib/deltaScheduler.js +9 -4
  174. package/lib/deltaScheduler.js.map +1 -1
  175. package/lib/garbageCollection.d.ts +34 -14
  176. package/lib/garbageCollection.d.ts.map +1 -1
  177. package/lib/garbageCollection.js +190 -95
  178. package/lib/garbageCollection.js.map +1 -1
  179. package/lib/garbageCollectionConstants.d.ts +3 -0
  180. package/lib/garbageCollectionConstants.d.ts.map +1 -1
  181. package/lib/garbageCollectionConstants.js +5 -0
  182. package/lib/garbageCollectionConstants.js.map +1 -1
  183. package/lib/garbageCollectionHelpers.d.ts +26 -0
  184. package/lib/garbageCollectionHelpers.d.ts.map +1 -0
  185. package/lib/garbageCollectionHelpers.js +40 -0
  186. package/lib/garbageCollectionHelpers.js.map +1 -0
  187. package/lib/gcSweepReadyUsageDetection.d.ts +5 -5
  188. package/lib/gcSweepReadyUsageDetection.d.ts.map +1 -1
  189. package/lib/gcSweepReadyUsageDetection.js +14 -10
  190. package/lib/gcSweepReadyUsageDetection.js.map +1 -1
  191. package/lib/index.d.ts +2 -2
  192. package/lib/index.d.ts.map +1 -1
  193. package/lib/index.js +1 -1
  194. package/lib/index.js.map +1 -1
  195. package/lib/opLifecycle/batchManager.d.ts +5 -5
  196. package/lib/opLifecycle/batchManager.d.ts.map +1 -1
  197. package/lib/opLifecycle/batchManager.js +19 -12
  198. package/lib/opLifecycle/batchManager.js.map +1 -1
  199. package/lib/opLifecycle/definitions.d.ts.map +1 -1
  200. package/lib/opLifecycle/definitions.js.map +1 -1
  201. package/lib/opLifecycle/index.d.ts.map +1 -1
  202. package/lib/opLifecycle/index.js.map +1 -1
  203. package/lib/opLifecycle/opCompressor.d.ts.map +1 -1
  204. package/lib/opLifecycle/opCompressor.js.map +1 -1
  205. package/lib/opLifecycle/opDecompressor.d.ts.map +1 -1
  206. package/lib/opLifecycle/opDecompressor.js +5 -2
  207. package/lib/opLifecycle/opDecompressor.js.map +1 -1
  208. package/lib/opLifecycle/opSplitter.d.ts.map +1 -1
  209. package/lib/opLifecycle/opSplitter.js +5 -2
  210. package/lib/opLifecycle/opSplitter.js.map +1 -1
  211. package/lib/opLifecycle/outbox.d.ts.map +1 -1
  212. package/lib/opLifecycle/outbox.js +19 -17
  213. package/lib/opLifecycle/outbox.js.map +1 -1
  214. package/lib/opLifecycle/remoteMessageProcessor.d.ts.map +1 -1
  215. package/lib/opLifecycle/remoteMessageProcessor.js.map +1 -1
  216. package/lib/opProperties.d.ts.map +1 -1
  217. package/lib/opProperties.js +1 -3
  218. package/lib/opProperties.js.map +1 -1
  219. package/lib/orderedClientElection.d.ts.map +1 -1
  220. package/lib/orderedClientElection.js +10 -4
  221. package/lib/orderedClientElection.js.map +1 -1
  222. package/lib/packageVersion.d.ts +1 -1
  223. package/lib/packageVersion.js +1 -1
  224. package/lib/packageVersion.js.map +1 -1
  225. package/lib/pendingStateManager.d.ts +7 -0
  226. package/lib/pendingStateManager.d.ts.map +1 -1
  227. package/lib/pendingStateManager.js +7 -4
  228. package/lib/pendingStateManager.js.map +1 -1
  229. package/lib/runWhileConnectedCoordinator.d.ts.map +1 -1
  230. package/lib/runWhileConnectedCoordinator.js.map +1 -1
  231. package/lib/runningSummarizer.d.ts.map +1 -1
  232. package/lib/runningSummarizer.js +35 -22
  233. package/lib/runningSummarizer.js.map +1 -1
  234. package/lib/scheduleManager.d.ts.map +1 -1
  235. package/lib/scheduleManager.js +3 -2
  236. package/lib/scheduleManager.js.map +1 -1
  237. package/lib/serializedSnapshotStorage.d.ts +2 -2
  238. package/lib/serializedSnapshotStorage.d.ts.map +1 -1
  239. package/lib/serializedSnapshotStorage.js +5 -3
  240. package/lib/serializedSnapshotStorage.js.map +1 -1
  241. package/lib/summarizer.d.ts +2 -2
  242. package/lib/summarizer.d.ts.map +1 -1
  243. package/lib/summarizer.js +37 -17
  244. package/lib/summarizer.js.map +1 -1
  245. package/lib/summarizerClientElection.d.ts.map +1 -1
  246. package/lib/summarizerClientElection.js.map +1 -1
  247. package/lib/summarizerHandle.d.ts.map +1 -1
  248. package/lib/summarizerHandle.js.map +1 -1
  249. package/lib/summarizerHeuristics.d.ts.map +1 -1
  250. package/lib/summarizerHeuristics.js +6 -9
  251. package/lib/summarizerHeuristics.js.map +1 -1
  252. package/lib/summarizerTypes.d.ts +21 -21
  253. package/lib/summarizerTypes.d.ts.map +1 -1
  254. package/lib/summarizerTypes.js.map +1 -1
  255. package/lib/summaryCollection.d.ts.map +1 -1
  256. package/lib/summaryCollection.js +18 -8
  257. package/lib/summaryCollection.js.map +1 -1
  258. package/lib/summaryFormat.d.ts +22 -0
  259. package/lib/summaryFormat.d.ts.map +1 -1
  260. package/lib/summaryFormat.js +20 -12
  261. package/lib/summaryFormat.js.map +1 -1
  262. package/lib/summaryGenerator.d.ts.map +1 -1
  263. package/lib/summaryGenerator.js +34 -15
  264. package/lib/summaryGenerator.js.map +1 -1
  265. package/lib/summaryManager.d.ts.map +1 -1
  266. package/lib/summaryManager.js +21 -9
  267. package/lib/summaryManager.js.map +1 -1
  268. package/lib/throttler.d.ts +2 -2
  269. package/lib/throttler.d.ts.map +1 -1
  270. package/lib/throttler.js +4 -4
  271. package/lib/throttler.js.map +1 -1
  272. package/package.json +121 -149
  273. package/prettier.config.cjs +1 -1
  274. package/src/batchTracker.ts +54 -49
  275. package/src/blobManager.ts +793 -672
  276. package/src/connectionTelemetry.ts +280 -249
  277. package/src/containerHandleContext.ts +27 -29
  278. package/src/containerRuntime.ts +3168 -2940
  279. package/src/dataStore.ts +172 -159
  280. package/src/dataStoreContext.ts +1098 -996
  281. package/src/dataStoreContexts.ts +178 -161
  282. package/src/dataStoreRegistry.ts +25 -20
  283. package/src/dataStores.ts +884 -728
  284. package/src/deltaScheduler.ts +158 -150
  285. package/src/garbageCollection.ts +1883 -1692
  286. package/src/garbageCollectionConstants.ts +6 -0
  287. package/src/garbageCollectionHelpers.ts +61 -0
  288. package/src/gcSweepReadyUsageDetection.ts +89 -83
  289. package/src/index.ts +67 -66
  290. package/src/opLifecycle/README.md +152 -0
  291. package/src/opLifecycle/batchManager.ts +145 -141
  292. package/src/opLifecycle/definitions.ts +29 -29
  293. package/src/opLifecycle/index.ts +5 -5
  294. package/src/opLifecycle/opCompressor.ts +54 -53
  295. package/src/opLifecycle/opDecompressor.ts +100 -81
  296. package/src/opLifecycle/opSplitter.ts +214 -188
  297. package/src/opLifecycle/outbox.ts +204 -194
  298. package/src/opLifecycle/remoteMessageProcessor.ts +62 -62
  299. package/src/opProperties.ts +11 -9
  300. package/src/orderedClientElection.ts +489 -457
  301. package/src/packageVersion.ts +1 -1
  302. package/src/pendingStateManager.ts +384 -338
  303. package/src/runWhileConnectedCoordinator.ts +78 -71
  304. package/src/runningSummarizer.ts +619 -581
  305. package/src/scheduleManager.ts +299 -269
  306. package/src/serializedSnapshotStorage.ts +126 -112
  307. package/src/summarizer.ts +417 -381
  308. package/src/summarizerClientElection.ts +107 -100
  309. package/src/summarizerHandle.ts +11 -9
  310. package/src/summarizerHeuristics.ts +183 -186
  311. package/src/summarizerTypes.ts +344 -330
  312. package/src/summaryCollection.ts +378 -349
  313. package/src/summaryFormat.ts +170 -126
  314. package/src/summaryGenerator.ts +465 -406
  315. package/src/summaryManager.ts +377 -348
  316. package/src/throttler.ts +131 -122
  317. package/tsconfig.esnext.json +6 -6
  318. package/tsconfig.json +9 -13
  319. package/dist/garbageCollectionTombstoneUtils.d.ts +0 -14
  320. package/dist/garbageCollectionTombstoneUtils.d.ts.map +0 -1
  321. package/dist/garbageCollectionTombstoneUtils.js +0 -23
  322. package/dist/garbageCollectionTombstoneUtils.js.map +0 -1
  323. package/lib/garbageCollectionTombstoneUtils.d.ts +0 -14
  324. package/lib/garbageCollectionTombstoneUtils.d.ts.map +0 -1
  325. package/lib/garbageCollectionTombstoneUtils.js +0 -19
  326. package/lib/garbageCollectionTombstoneUtils.js.map +0 -1
  327. 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
  }