@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
@@ -7,36 +7,36 @@ import { IDisposable, IEvent, ITelemetryLogger } from "@fluidframework/common-de
7
7
  import { Deferred, assert, TypedEventEmitter } from "@fluidframework/common-utils";
8
8
  import { IDeltaManager } from "@fluidframework/container-definitions";
9
9
  import {
10
- IDocumentMessage,
11
- ISequencedDocumentMessage,
12
- ISummaryAck,
13
- ISummaryContent,
14
- ISummaryNack,
15
- MessageType,
10
+ IDocumentMessage,
11
+ ISequencedDocumentMessage,
12
+ ISummaryAck,
13
+ ISummaryContent,
14
+ ISummaryNack,
15
+ MessageType,
16
16
  } from "@fluidframework/protocol-definitions";
17
17
 
18
18
  /**
19
19
  * Interface for summary op messages with typed contents.
20
20
  */
21
21
  export interface ISummaryOpMessage extends ISequencedDocumentMessage {
22
- type: MessageType.Summarize;
23
- contents: ISummaryContent;
22
+ type: MessageType.Summarize;
23
+ contents: ISummaryContent;
24
24
  }
25
25
 
26
26
  /**
27
27
  * Interface for summary ack messages with typed contents.
28
28
  */
29
29
  export interface ISummaryAckMessage extends ISequencedDocumentMessage {
30
- type: MessageType.SummaryAck;
31
- contents: ISummaryAck;
30
+ type: MessageType.SummaryAck;
31
+ contents: ISummaryAck;
32
32
  }
33
33
 
34
34
  /**
35
35
  * Interface for summary nack messages with typed contents.
36
36
  */
37
37
  export interface ISummaryNackMessage extends ISequencedDocumentMessage {
38
- type: MessageType.SummaryNack;
39
- contents: ISummaryNack;
38
+ type: MessageType.SummaryNack;
39
+ contents: ISummaryNack;
40
40
  }
41
41
 
42
42
  /**
@@ -44,92 +44,102 @@ export interface ISummaryNackMessage extends ISequencedDocumentMessage {
44
44
  * The life cycle is: Local to Broadcast to Acked/Nacked.
45
45
  */
46
46
  export interface ISummary {
47
- readonly clientId: string;
48
- readonly clientSequenceNumber: number;
49
- waitBroadcast(): Promise<ISummaryOpMessage>;
50
- waitAckNack(): Promise<ISummaryAckMessage | ISummaryNackMessage>;
47
+ readonly clientId: string;
48
+ readonly clientSequenceNumber: number;
49
+ waitBroadcast(): Promise<ISummaryOpMessage>;
50
+ waitAckNack(): Promise<ISummaryAckMessage | ISummaryNackMessage>;
51
51
  }
52
52
 
53
53
  /**
54
54
  * A single summary which has already been acked by the server.
55
55
  */
56
56
  export interface IAckedSummary {
57
- readonly summaryOp: ISummaryOpMessage;
58
- readonly summaryAck: ISummaryAckMessage;
57
+ readonly summaryOp: ISummaryOpMessage;
58
+ readonly summaryAck: ISummaryAckMessage;
59
59
  }
60
60
 
61
61
  enum SummaryState {
62
- Local = 0,
63
- Broadcast = 1,
64
- Acked = 2,
65
- Nacked = -1,
62
+ Local = 0,
63
+ Broadcast = 1,
64
+ Acked = 2,
65
+ Nacked = -1,
66
66
  }
67
67
 
68
68
  class Summary implements ISummary {
69
- public static createLocal(clientId: string, clientSequenceNumber: number) {
70
- return new Summary(clientId, clientSequenceNumber);
71
- }
72
- public static createFromOp(op: ISummaryOpMessage) {
73
- const summary = new Summary(op.clientId, op.clientSequenceNumber);
74
- summary.broadcast(op);
75
- return summary;
76
- }
77
-
78
- private state = SummaryState.Local;
79
-
80
- private _summaryOp?: ISummaryOpMessage;
81
- private _summaryAckNack?: ISummaryAckMessage | ISummaryNackMessage;
82
-
83
- private readonly defSummaryOp = new Deferred<void>();
84
- private readonly defSummaryAck = new Deferred<void>();
85
-
86
- public get summaryOp() { return this._summaryOp; }
87
- public get summaryAckNack() { return this._summaryAckNack; }
88
-
89
- private constructor(
90
- public readonly clientId: string,
91
- public readonly clientSequenceNumber: number) { }
92
-
93
- public hasBeenAcked(): this is IAckedSummary {
94
- return this.state === SummaryState.Acked;
95
- }
96
-
97
- public broadcast(op: ISummaryOpMessage) {
98
- assert(this.state === SummaryState.Local, 0x175 /* "Can only broadcast if summarizer starts in local state" */);
99
- this._summaryOp = op;
100
- this.defSummaryOp.resolve();
101
- this.state = SummaryState.Broadcast;
102
- return true;
103
- }
104
-
105
- public ackNack(op: ISummaryAckMessage | ISummaryNackMessage) {
106
- assert(this.state === SummaryState.Broadcast,
107
- 0x176 /* "Can only ack/nack if summarizer is in broadcasting state" */);
108
- this._summaryAckNack = op;
109
- this.defSummaryAck.resolve();
110
- this.state = op.type === MessageType.SummaryAck ? SummaryState.Acked : SummaryState.Nacked;
111
- return true;
112
- }
113
-
114
- public async waitBroadcast(): Promise<ISummaryOpMessage> {
115
- await this.defSummaryOp.promise;
116
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
117
- return this._summaryOp!;
118
- }
119
-
120
- public async waitAckNack(): Promise<ISummaryAckMessage | ISummaryNackMessage> {
121
- await this.defSummaryAck.promise;
122
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
123
- return this._summaryAckNack!;
124
- }
69
+ public static createLocal(clientId: string, clientSequenceNumber: number) {
70
+ return new Summary(clientId, clientSequenceNumber);
71
+ }
72
+ public static createFromOp(op: ISummaryOpMessage) {
73
+ const summary = new Summary(op.clientId, op.clientSequenceNumber);
74
+ summary.broadcast(op);
75
+ return summary;
76
+ }
77
+
78
+ private state = SummaryState.Local;
79
+
80
+ private _summaryOp?: ISummaryOpMessage;
81
+ private _summaryAckNack?: ISummaryAckMessage | ISummaryNackMessage;
82
+
83
+ private readonly defSummaryOp = new Deferred<void>();
84
+ private readonly defSummaryAck = new Deferred<void>();
85
+
86
+ public get summaryOp() {
87
+ return this._summaryOp;
88
+ }
89
+ public get summaryAckNack() {
90
+ return this._summaryAckNack;
91
+ }
92
+
93
+ private constructor(
94
+ public readonly clientId: string,
95
+ public readonly clientSequenceNumber: number,
96
+ ) {}
97
+
98
+ public hasBeenAcked(): this is IAckedSummary {
99
+ return this.state === SummaryState.Acked;
100
+ }
101
+
102
+ public broadcast(op: ISummaryOpMessage) {
103
+ assert(
104
+ this.state === SummaryState.Local,
105
+ 0x175 /* "Can only broadcast if summarizer starts in local state" */,
106
+ );
107
+ this._summaryOp = op;
108
+ this.defSummaryOp.resolve();
109
+ this.state = SummaryState.Broadcast;
110
+ return true;
111
+ }
112
+
113
+ public ackNack(op: ISummaryAckMessage | ISummaryNackMessage) {
114
+ assert(
115
+ this.state === SummaryState.Broadcast,
116
+ 0x176 /* "Can only ack/nack if summarizer is in broadcasting state" */,
117
+ );
118
+ this._summaryAckNack = op;
119
+ this.defSummaryAck.resolve();
120
+ this.state = op.type === MessageType.SummaryAck ? SummaryState.Acked : SummaryState.Nacked;
121
+ return true;
122
+ }
123
+
124
+ public async waitBroadcast(): Promise<ISummaryOpMessage> {
125
+ await this.defSummaryOp.promise;
126
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
127
+ return this._summaryOp!;
128
+ }
129
+
130
+ public async waitAckNack(): Promise<ISummaryAckMessage | ISummaryNackMessage> {
131
+ await this.defSummaryAck.promise;
132
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
133
+ return this._summaryAckNack!;
134
+ }
125
135
  }
126
136
 
127
137
  /**
128
138
  * Watches summaries created by a specific client.
129
139
  */
130
140
  export interface IClientSummaryWatcher extends IDisposable {
131
- watchSummary(clientSequenceNumber: number): ISummary;
132
- waitFlushed(): Promise<IAckedSummary | undefined>;
141
+ watchSummary(clientSequenceNumber: number): ISummary;
142
+ waitFlushed(): Promise<IAckedSummary | undefined>;
133
143
  }
134
144
 
135
145
  /**
@@ -137,65 +147,71 @@ export interface IClientSummaryWatcher extends IDisposable {
137
147
  * It should be created and managed from a SummaryCollection.
138
148
  */
139
149
  class ClientSummaryWatcher implements IClientSummaryWatcher {
140
- // key: clientSeqNum
141
- private readonly localSummaries = new Map<number, Summary>();
142
- private _disposed = false;
143
-
144
- public get disposed() { return this._disposed; }
145
-
146
- public constructor(
147
- public readonly clientId: string,
148
- private readonly summaryCollection: SummaryCollection,
149
- ) { }
150
-
151
- /**
152
- * Watches for a specific sent summary op.
153
- * @param clientSequenceNumber - client sequence number of sent summary op
154
- */
155
- public watchSummary(clientSequenceNumber: number): ISummary {
156
- let summary = this.localSummaries.get(clientSequenceNumber);
157
- if (!summary) {
158
- summary = Summary.createLocal(this.clientId, clientSequenceNumber);
159
- this.localSummaries.set(summary.clientSequenceNumber, summary);
160
- }
161
- return summary;
162
- }
163
-
164
- /**
165
- * Waits until all of the pending summaries in the underlying SummaryCollection
166
- * are acked/nacked.
167
- */
168
- // eslint-disable-next-line @typescript-eslint/promise-function-async
169
- public waitFlushed() {
170
- return this.summaryCollection.waitFlushed();
171
- }
172
-
173
- /**
174
- * Gets a watched summary or returns undefined if not watched.
175
- * @param clientSequenceNumber - client sequence number of sent summary op
176
- */
177
- public tryGetSummary(clientSequenceNumber: number) {
178
- return this.localSummaries.get(clientSequenceNumber);
179
- }
180
-
181
- /**
182
- * Starts watching a summary made by this client.
183
- * @param summary - summary to start watching
184
- */
185
- public setSummary(summary: Summary) {
186
- this.localSummaries.set(summary.clientSequenceNumber, summary);
187
- }
188
-
189
- public dispose() {
190
- this.summaryCollection.removeWatcher(this.clientId);
191
- this._disposed = true;
192
- }
150
+ // key: clientSeqNum
151
+ private readonly localSummaries = new Map<number, Summary>();
152
+ private _disposed = false;
153
+
154
+ public get disposed() {
155
+ return this._disposed;
156
+ }
157
+
158
+ public constructor(
159
+ public readonly clientId: string,
160
+ private readonly summaryCollection: SummaryCollection,
161
+ ) {}
162
+
163
+ /**
164
+ * Watches for a specific sent summary op.
165
+ * @param clientSequenceNumber - client sequence number of sent summary op
166
+ */
167
+ public watchSummary(clientSequenceNumber: number): ISummary {
168
+ let summary = this.localSummaries.get(clientSequenceNumber);
169
+ if (!summary) {
170
+ summary = Summary.createLocal(this.clientId, clientSequenceNumber);
171
+ this.localSummaries.set(summary.clientSequenceNumber, summary);
172
+ }
173
+ return summary;
174
+ }
175
+
176
+ /**
177
+ * Waits until all of the pending summaries in the underlying SummaryCollection
178
+ * are acked/nacked.
179
+ */
180
+ // eslint-disable-next-line @typescript-eslint/promise-function-async
181
+ public waitFlushed() {
182
+ return this.summaryCollection.waitFlushed();
183
+ }
184
+
185
+ /**
186
+ * Gets a watched summary or returns undefined if not watched.
187
+ * @param clientSequenceNumber - client sequence number of sent summary op
188
+ */
189
+ public tryGetSummary(clientSequenceNumber: number) {
190
+ return this.localSummaries.get(clientSequenceNumber);
191
+ }
192
+
193
+ /**
194
+ * Starts watching a summary made by this client.
195
+ * @param summary - summary to start watching
196
+ */
197
+ public setSummary(summary: Summary) {
198
+ this.localSummaries.set(summary.clientSequenceNumber, summary);
199
+ }
200
+
201
+ public dispose() {
202
+ this.summaryCollection.removeWatcher(this.clientId);
203
+ this._disposed = true;
204
+ }
193
205
  }
194
206
 
195
- export type OpActionEventName = MessageType.Summarize | MessageType.SummaryAck | MessageType.SummaryNack | "default";
207
+ export type OpActionEventName =
208
+ | MessageType.Summarize
209
+ | MessageType.SummaryAck
210
+ | MessageType.SummaryNack
211
+ | "default";
196
212
  export type OpActionEventListener = (op: ISequencedDocumentMessage) => void;
197
213
  export interface ISummaryCollectionOpEvents extends IEvent {
198
- (event: OpActionEventName, listener: OpActionEventListener);
214
+ (event: OpActionEventName, listener: OpActionEventListener);
199
215
  }
200
216
 
201
217
  /**
@@ -204,218 +220,231 @@ export interface ISummaryCollectionOpEvents extends IEvent {
204
220
  * It provides functionality for watching specific summaries.
205
221
  */
206
222
  export class SummaryCollection extends TypedEventEmitter<ISummaryCollectionOpEvents> {
207
- // key: clientId
208
- private readonly summaryWatchers = new Map<string, ClientSummaryWatcher>();
209
- // key: summarySeqNum
210
- private readonly pendingSummaries = new Map<number, Summary>();
211
- private refreshWaitNextAck = new Deferred<void>();
212
-
213
- private lastSummaryTimestamp: number | undefined;
214
- private maxAckWaitTime: number | undefined;
215
- private pendingAckTimerTimeoutCallback: (() => void) | undefined;
216
- private lastAck: IAckedSummary | undefined;
217
-
218
- public get latestAck(): IAckedSummary | undefined { return this.lastAck; }
219
-
220
- public emit(event: OpActionEventName, ...args: Parameters<OpActionEventListener>): boolean {
221
- return super.emit(event, ...args);
222
- }
223
-
224
- public get opsSinceLastAck() {
225
- return this.deltaManager.lastSequenceNumber -
226
- (this.lastAck?.summaryAck.sequenceNumber ?? this.deltaManager.initialSequenceNumber);
227
- }
228
-
229
- public addOpListener(listener: () => void) {
230
- this.deltaManager.on("op", listener);
231
- }
232
-
233
- public removeOpListener(listener: () => void) {
234
- this.deltaManager.off("op", listener);
235
- }
236
-
237
- public constructor(
238
- private readonly deltaManager: IDeltaManager<ISequencedDocumentMessage, IDocumentMessage>,
239
- private readonly logger: ITelemetryLogger,
240
- ) {
241
- super();
242
- this.deltaManager.on("op", (op) => this.handleOp(op));
243
- }
244
-
245
- /**
246
- * Creates and returns a summary watcher for a specific client.
247
- * This will allow for local sent summaries to be better tracked.
248
- * @param clientId - client id for watcher
249
- */
250
- public createWatcher(clientId: string): IClientSummaryWatcher {
251
- const watcher = new ClientSummaryWatcher(clientId, this);
252
- this.summaryWatchers.set(clientId, watcher);
253
- return watcher;
254
- }
255
-
256
- public removeWatcher(clientId: string) {
257
- this.summaryWatchers.delete(clientId);
258
- }
259
-
260
- public setPendingAckTimerTimeoutCallback(maxAckWaitTime: number, timeoutCallback: () => void) {
261
- this.maxAckWaitTime = maxAckWaitTime;
262
- this.pendingAckTimerTimeoutCallback = timeoutCallback;
263
- }
264
-
265
- public unsetPendingAckTimerTimeoutCallback() {
266
- this.maxAckWaitTime = undefined;
267
- this.pendingAckTimerTimeoutCallback = undefined;
268
- }
269
-
270
- /**
271
- * Returns a promise that resolves once all pending summary ops
272
- * have been acked or nacked.
273
- */
274
- public async waitFlushed(): Promise<IAckedSummary | undefined> {
275
- while (this.pendingSummaries.size > 0) {
276
- // eslint-disable-next-line @typescript-eslint/promise-function-async
277
- const promises = Array.from(this.pendingSummaries, ([, summary]) => summary.waitAckNack());
278
- await Promise.all(promises);
279
- }
280
- return this.lastAck;
281
- }
282
-
283
- /**
284
- * Returns a promise that resolves once a summary is acked that has a reference
285
- * sequence number greater than or equal to the passed in sequence number.
286
- * @param referenceSequenceNumber - reference sequence number to wait for
287
- * @returns The latest acked summary
288
- */
289
- public async waitSummaryAck(referenceSequenceNumber: number): Promise<IAckedSummary> {
290
- while (!this.lastAck || this.lastAck.summaryOp.referenceSequenceNumber < referenceSequenceNumber) {
291
- await this.refreshWaitNextAck.promise;
292
- }
293
- return this.lastAck;
294
- }
295
-
296
- private parseContent(op: ISequencedDocumentMessage) {
297
- // back-compat: ADO #1385: Make this unconditional in the future,
298
- // when Container.processRemoteMessage stops parsing contents. That said, we should move to
299
- // listen for "op" events from ContainerRuntime, and parsing may not be required at all if
300
- // ContainerRuntime.process() would parse it for all types of ops.
301
- // Can make either of those changes only when LTS moves to a version that has no content
302
- // parsing in loader layer!
303
- if (typeof op.contents === "string") {
304
- op.contents = JSON.parse(op.contents);
305
- }
306
- }
307
-
308
- /**
309
- * Handler for ops; only handles ops relating to summaries.
310
- * @param op - op message to handle
311
- */
312
- private handleOp(opArg: ISequencedDocumentMessage) {
313
- const op = { ...opArg };
314
-
315
- switch (op.type) {
316
- case MessageType.Summarize:
317
- this.parseContent(op);
318
- return this.handleSummaryOp(op as ISummaryOpMessage);
319
- case MessageType.SummaryAck:
320
- case MessageType.SummaryNack:
321
- // Old files (prior to PR #10077) may not contain this info
322
- // back-compat: ADO #1385: remove cast when ISequencedDocumentMessage changes are propagated
323
- if ((op as any).data !== undefined) {
324
- op.contents = JSON.parse((op as any).data);
325
- } else {
326
- this.parseContent(op);
327
- }
328
- return op.type === MessageType.SummaryAck
329
- ? this.handleSummaryAck(op as ISummaryAckMessage)
330
- : this.handleSummaryNack(op as ISummaryNackMessage);
331
- default: {
332
- // If the difference between timestamp of current op and last summary op is greater than
333
- // the maxAckWaitTime, then we need to inform summarizer to not wait and summarize
334
- // immediately as we have already waited for maxAckWaitTime.
335
- const lastOpTimestamp = op.timestamp;
336
- if (this.lastSummaryTimestamp !== undefined &&
337
- this.maxAckWaitTime !== undefined &&
338
- lastOpTimestamp - this.lastSummaryTimestamp >= this.maxAckWaitTime
339
- ) {
340
- this.pendingAckTimerTimeoutCallback?.();
341
- }
342
- this.emit("default", op);
343
-
344
- return;
345
- }
346
- }
347
- }
348
-
349
- private handleSummaryOp(op: ISummaryOpMessage) {
350
- let summary: Summary | undefined;
351
-
352
- // Check if summary already being watched, broadcast if so
353
- const watcher = this.summaryWatchers.get(op.clientId);
354
- if (watcher) {
355
- summary = watcher.tryGetSummary(op.clientSequenceNumber);
356
- if (summary) {
357
- summary.broadcast(op);
358
- }
359
- }
360
-
361
- // If not watched, create from op
362
- if (!summary) {
363
- summary = Summary.createFromOp(op);
364
- if (watcher) {
365
- watcher.setSummary(summary);
366
- }
367
- }
368
- this.pendingSummaries.set(op.sequenceNumber, summary);
369
- this.lastSummaryTimestamp = op.timestamp;
370
- this.emit(MessageType.Summarize, op);
371
- }
372
-
373
- private handleSummaryAck(op: ISummaryAckMessage) {
374
- const seq = op.contents.summaryProposal.summarySequenceNumber;
375
- const summary = this.pendingSummaries.get(seq);
376
- if (!summary || summary.summaryOp === undefined) {
377
- // Summary ack without an op should be rare. We could fetch the
378
- // reference sequence number from the snapshot, but instead we
379
- // will not emit this ack. It should be the case that the summary
380
- // op that this ack is for is earlier than this file was loaded
381
- // from. i.e. initialSequenceNumber > summarySequenceNumber.
382
- // We really don't care about it for now, since it is older than
383
- // the one we loaded from.
384
- if (seq > this.deltaManager.initialSequenceNumber) {
385
- // Potential causes for it to be later than our initialSequenceNumber
386
- // are that the summaryOp was nacked then acked, double-acked, or
387
- // the summarySequenceNumber is incorrect.
388
- this.logger.sendTelemetryEvent({
389
- eventName: "SummaryAckWithoutOp",
390
- sequenceNumber: op.sequenceNumber, // summary ack seq #
391
- summarySequenceNumber: seq, // missing summary seq #
392
- initialSequenceNumber: this.deltaManager.initialSequenceNumber,
393
- });
394
- }
395
- return;
396
- }
397
- summary.ackNack(op);
398
- this.pendingSummaries.delete(seq);
399
-
400
- // Track latest ack
401
- if (!this.lastAck || seq > this.lastAck.summaryAck.contents.summaryProposal.summarySequenceNumber) {
402
- this.lastAck = {
403
- summaryOp: summary.summaryOp,
404
- summaryAck: op,
405
- };
406
- this.refreshWaitNextAck.resolve();
407
- this.refreshWaitNextAck = new Deferred<void>();
408
- this.emit(MessageType.SummaryAck, op);
409
- }
410
- }
411
-
412
- private handleSummaryNack(op: ISummaryNackMessage) {
413
- const seq = op.contents.summaryProposal.summarySequenceNumber;
414
- const summary = this.pendingSummaries.get(seq);
415
- if (summary) {
416
- summary.ackNack(op);
417
- this.pendingSummaries.delete(seq);
418
- this.emit(MessageType.SummaryNack, op);
419
- }
420
- }
223
+ // key: clientId
224
+ private readonly summaryWatchers = new Map<string, ClientSummaryWatcher>();
225
+ // key: summarySeqNum
226
+ private readonly pendingSummaries = new Map<number, Summary>();
227
+ private refreshWaitNextAck = new Deferred<void>();
228
+
229
+ private lastSummaryTimestamp: number | undefined;
230
+ private maxAckWaitTime: number | undefined;
231
+ private pendingAckTimerTimeoutCallback: (() => void) | undefined;
232
+ private lastAck: IAckedSummary | undefined;
233
+
234
+ public get latestAck(): IAckedSummary | undefined {
235
+ return this.lastAck;
236
+ }
237
+
238
+ public emit(event: OpActionEventName, ...args: Parameters<OpActionEventListener>): boolean {
239
+ return super.emit(event, ...args);
240
+ }
241
+
242
+ public get opsSinceLastAck() {
243
+ return (
244
+ this.deltaManager.lastSequenceNumber -
245
+ (this.lastAck?.summaryAck.sequenceNumber ?? this.deltaManager.initialSequenceNumber)
246
+ );
247
+ }
248
+
249
+ public addOpListener(listener: () => void) {
250
+ this.deltaManager.on("op", listener);
251
+ }
252
+
253
+ public removeOpListener(listener: () => void) {
254
+ this.deltaManager.off("op", listener);
255
+ }
256
+
257
+ public constructor(
258
+ private readonly deltaManager: IDeltaManager<ISequencedDocumentMessage, IDocumentMessage>,
259
+ private readonly logger: ITelemetryLogger,
260
+ ) {
261
+ super();
262
+ this.deltaManager.on("op", (op) => this.handleOp(op));
263
+ }
264
+
265
+ /**
266
+ * Creates and returns a summary watcher for a specific client.
267
+ * This will allow for local sent summaries to be better tracked.
268
+ * @param clientId - client id for watcher
269
+ */
270
+ public createWatcher(clientId: string): IClientSummaryWatcher {
271
+ const watcher = new ClientSummaryWatcher(clientId, this);
272
+ this.summaryWatchers.set(clientId, watcher);
273
+ return watcher;
274
+ }
275
+
276
+ public removeWatcher(clientId: string) {
277
+ this.summaryWatchers.delete(clientId);
278
+ }
279
+
280
+ public setPendingAckTimerTimeoutCallback(maxAckWaitTime: number, timeoutCallback: () => void) {
281
+ this.maxAckWaitTime = maxAckWaitTime;
282
+ this.pendingAckTimerTimeoutCallback = timeoutCallback;
283
+ }
284
+
285
+ public unsetPendingAckTimerTimeoutCallback() {
286
+ this.maxAckWaitTime = undefined;
287
+ this.pendingAckTimerTimeoutCallback = undefined;
288
+ }
289
+
290
+ /**
291
+ * Returns a promise that resolves once all pending summary ops
292
+ * have been acked or nacked.
293
+ */
294
+ public async waitFlushed(): Promise<IAckedSummary | undefined> {
295
+ while (this.pendingSummaries.size > 0) {
296
+ // eslint-disable-next-line @typescript-eslint/promise-function-async
297
+ const promises = Array.from(this.pendingSummaries, ([, summary]) =>
298
+ summary.waitAckNack(),
299
+ );
300
+ await Promise.all(promises);
301
+ }
302
+ return this.lastAck;
303
+ }
304
+
305
+ /**
306
+ * Returns a promise that resolves once a summary is acked that has a reference
307
+ * sequence number greater than or equal to the passed in sequence number.
308
+ * @param referenceSequenceNumber - reference sequence number to wait for
309
+ * @returns The latest acked summary
310
+ */
311
+ public async waitSummaryAck(referenceSequenceNumber: number): Promise<IAckedSummary> {
312
+ while (
313
+ !this.lastAck ||
314
+ this.lastAck.summaryOp.referenceSequenceNumber < referenceSequenceNumber
315
+ ) {
316
+ await this.refreshWaitNextAck.promise;
317
+ }
318
+ return this.lastAck;
319
+ }
320
+
321
+ private parseContent(op: ISequencedDocumentMessage) {
322
+ // back-compat: ADO #1385: Make this unconditional in the future,
323
+ // when Container.processRemoteMessage stops parsing contents. That said, we should move to
324
+ // listen for "op" events from ContainerRuntime, and parsing may not be required at all if
325
+ // ContainerRuntime.process() would parse it for all types of ops.
326
+ // Can make either of those changes only when LTS moves to a version that has no content
327
+ // parsing in loader layer!
328
+ if (typeof op.contents === "string") {
329
+ op.contents = JSON.parse(op.contents);
330
+ }
331
+ }
332
+
333
+ /**
334
+ * Handler for ops; only handles ops relating to summaries.
335
+ * @param op - op message to handle
336
+ */
337
+ private handleOp(opArg: ISequencedDocumentMessage) {
338
+ const op = { ...opArg };
339
+
340
+ switch (op.type) {
341
+ case MessageType.Summarize:
342
+ this.parseContent(op);
343
+ return this.handleSummaryOp(op as ISummaryOpMessage);
344
+ case MessageType.SummaryAck:
345
+ case MessageType.SummaryNack:
346
+ // Old files (prior to PR #10077) may not contain this info
347
+ // back-compat: ADO #1385: remove cast when ISequencedDocumentMessage changes are propagated
348
+ if ((op as any).data !== undefined) {
349
+ op.contents = JSON.parse((op as any).data);
350
+ } else {
351
+ this.parseContent(op);
352
+ }
353
+ return op.type === MessageType.SummaryAck
354
+ ? this.handleSummaryAck(op as ISummaryAckMessage)
355
+ : this.handleSummaryNack(op as ISummaryNackMessage);
356
+ default: {
357
+ // If the difference between timestamp of current op and last summary op is greater than
358
+ // the maxAckWaitTime, then we need to inform summarizer to not wait and summarize
359
+ // immediately as we have already waited for maxAckWaitTime.
360
+ const lastOpTimestamp = op.timestamp;
361
+ if (
362
+ this.lastSummaryTimestamp !== undefined &&
363
+ this.maxAckWaitTime !== undefined &&
364
+ lastOpTimestamp - this.lastSummaryTimestamp >= this.maxAckWaitTime
365
+ ) {
366
+ this.pendingAckTimerTimeoutCallback?.();
367
+ }
368
+ this.emit("default", op);
369
+
370
+ return;
371
+ }
372
+ }
373
+ }
374
+
375
+ private handleSummaryOp(op: ISummaryOpMessage) {
376
+ let summary: Summary | undefined;
377
+
378
+ // Check if summary already being watched, broadcast if so
379
+ const watcher = this.summaryWatchers.get(op.clientId);
380
+ if (watcher) {
381
+ summary = watcher.tryGetSummary(op.clientSequenceNumber);
382
+ if (summary) {
383
+ summary.broadcast(op);
384
+ }
385
+ }
386
+
387
+ // If not watched, create from op
388
+ if (!summary) {
389
+ summary = Summary.createFromOp(op);
390
+ if (watcher) {
391
+ watcher.setSummary(summary);
392
+ }
393
+ }
394
+ this.pendingSummaries.set(op.sequenceNumber, summary);
395
+ this.lastSummaryTimestamp = op.timestamp;
396
+ this.emit(MessageType.Summarize, op);
397
+ }
398
+
399
+ private handleSummaryAck(op: ISummaryAckMessage) {
400
+ const seq = op.contents.summaryProposal.summarySequenceNumber;
401
+ const summary = this.pendingSummaries.get(seq);
402
+ if (!summary || summary.summaryOp === undefined) {
403
+ // Summary ack without an op should be rare. We could fetch the
404
+ // reference sequence number from the snapshot, but instead we
405
+ // will not emit this ack. It should be the case that the summary
406
+ // op that this ack is for is earlier than this file was loaded
407
+ // from. i.e. initialSequenceNumber > summarySequenceNumber.
408
+ // We really don't care about it for now, since it is older than
409
+ // the one we loaded from.
410
+ if (seq > this.deltaManager.initialSequenceNumber) {
411
+ // Potential causes for it to be later than our initialSequenceNumber
412
+ // are that the summaryOp was nacked then acked, double-acked, or
413
+ // the summarySequenceNumber is incorrect.
414
+ this.logger.sendTelemetryEvent({
415
+ eventName: "SummaryAckWithoutOp",
416
+ sequenceNumber: op.sequenceNumber, // summary ack seq #
417
+ summarySequenceNumber: seq, // missing summary seq #
418
+ initialSequenceNumber: this.deltaManager.initialSequenceNumber,
419
+ });
420
+ }
421
+ return;
422
+ }
423
+ summary.ackNack(op);
424
+ this.pendingSummaries.delete(seq);
425
+
426
+ // Track latest ack
427
+ if (
428
+ !this.lastAck ||
429
+ seq > this.lastAck.summaryAck.contents.summaryProposal.summarySequenceNumber
430
+ ) {
431
+ this.lastAck = {
432
+ summaryOp: summary.summaryOp,
433
+ summaryAck: op,
434
+ };
435
+ this.refreshWaitNextAck.resolve();
436
+ this.refreshWaitNextAck = new Deferred<void>();
437
+ this.emit(MessageType.SummaryAck, op);
438
+ }
439
+ }
440
+
441
+ private handleSummaryNack(op: ISummaryNackMessage) {
442
+ const seq = op.contents.summaryProposal.summarySequenceNumber;
443
+ const summary = this.pendingSummaries.get(seq);
444
+ if (summary) {
445
+ summary.ackNack(op);
446
+ this.pendingSummaries.delete(seq);
447
+ this.emit(MessageType.SummaryNack, op);
448
+ }
449
+ }
421
450
  }