@fluidframework/container-runtime 2.0.0-internal.1.4.2 → 2.0.0-internal.2.0.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 (107) hide show
  1. package/dist/batchManager.d.ts +2 -3
  2. package/dist/batchManager.d.ts.map +1 -1
  3. package/dist/batchManager.js +3 -8
  4. package/dist/batchManager.js.map +1 -1
  5. package/dist/containerRuntime.d.ts +43 -16
  6. package/dist/containerRuntime.d.ts.map +1 -1
  7. package/dist/containerRuntime.js +107 -83
  8. package/dist/containerRuntime.js.map +1 -1
  9. package/dist/dataStoreContext.d.ts +4 -20
  10. package/dist/dataStoreContext.d.ts.map +1 -1
  11. package/dist/dataStoreContext.js +17 -47
  12. package/dist/dataStoreContext.js.map +1 -1
  13. package/dist/dataStores.d.ts +2 -5
  14. package/dist/dataStores.d.ts.map +1 -1
  15. package/dist/dataStores.js +3 -11
  16. package/dist/dataStores.js.map +1 -1
  17. package/dist/garbageCollection.d.ts +1 -10
  18. package/dist/garbageCollection.d.ts.map +1 -1
  19. package/dist/garbageCollection.js +43 -51
  20. package/dist/garbageCollection.js.map +1 -1
  21. package/dist/gcSweepReadyUsageDetection.d.ts.map +1 -1
  22. package/dist/gcSweepReadyUsageDetection.js +3 -12
  23. package/dist/gcSweepReadyUsageDetection.js.map +1 -1
  24. package/dist/index.d.ts +3 -5
  25. package/dist/index.d.ts.map +1 -1
  26. package/dist/index.js +1 -5
  27. package/dist/index.js.map +1 -1
  28. package/dist/packageVersion.d.ts +1 -1
  29. package/dist/packageVersion.js +1 -1
  30. package/dist/packageVersion.js.map +1 -1
  31. package/dist/pendingStateManager.d.ts +6 -26
  32. package/dist/pendingStateManager.d.ts.map +1 -1
  33. package/dist/pendingStateManager.js +42 -62
  34. package/dist/pendingStateManager.js.map +1 -1
  35. package/dist/scheduleManager.js.map +1 -1
  36. package/dist/summarizer.js +7 -2
  37. package/dist/summarizer.js.map +1 -1
  38. package/dist/summarizerTypes.d.ts +19 -2
  39. package/dist/summarizerTypes.d.ts.map +1 -1
  40. package/dist/summarizerTypes.js.map +1 -1
  41. package/dist/summaryFormat.d.ts +4 -2
  42. package/dist/summaryFormat.d.ts.map +1 -1
  43. package/dist/summaryFormat.js.map +1 -1
  44. package/dist/summaryManager.d.ts.map +1 -1
  45. package/dist/summaryManager.js +10 -6
  46. package/dist/summaryManager.js.map +1 -1
  47. package/lib/batchManager.d.ts +2 -3
  48. package/lib/batchManager.d.ts.map +1 -1
  49. package/lib/batchManager.js +3 -8
  50. package/lib/batchManager.js.map +1 -1
  51. package/lib/containerRuntime.d.ts +43 -16
  52. package/lib/containerRuntime.d.ts.map +1 -1
  53. package/lib/containerRuntime.js +108 -84
  54. package/lib/containerRuntime.js.map +1 -1
  55. package/lib/dataStoreContext.d.ts +4 -20
  56. package/lib/dataStoreContext.d.ts.map +1 -1
  57. package/lib/dataStoreContext.js +18 -48
  58. package/lib/dataStoreContext.js.map +1 -1
  59. package/lib/dataStores.d.ts +2 -5
  60. package/lib/dataStores.d.ts.map +1 -1
  61. package/lib/dataStores.js +3 -11
  62. package/lib/dataStores.js.map +1 -1
  63. package/lib/garbageCollection.d.ts +1 -10
  64. package/lib/garbageCollection.d.ts.map +1 -1
  65. package/lib/garbageCollection.js +42 -50
  66. package/lib/garbageCollection.js.map +1 -1
  67. package/lib/gcSweepReadyUsageDetection.d.ts.map +1 -1
  68. package/lib/gcSweepReadyUsageDetection.js +3 -12
  69. package/lib/gcSweepReadyUsageDetection.js.map +1 -1
  70. package/lib/index.d.ts +3 -5
  71. package/lib/index.d.ts.map +1 -1
  72. package/lib/index.js +0 -2
  73. package/lib/index.js.map +1 -1
  74. package/lib/packageVersion.d.ts +1 -1
  75. package/lib/packageVersion.js +1 -1
  76. package/lib/packageVersion.js.map +1 -1
  77. package/lib/pendingStateManager.d.ts +6 -26
  78. package/lib/pendingStateManager.d.ts.map +1 -1
  79. package/lib/pendingStateManager.js +42 -62
  80. package/lib/pendingStateManager.js.map +1 -1
  81. package/lib/scheduleManager.js.map +1 -1
  82. package/lib/summarizer.js +7 -2
  83. package/lib/summarizer.js.map +1 -1
  84. package/lib/summarizerTypes.d.ts +19 -2
  85. package/lib/summarizerTypes.d.ts.map +1 -1
  86. package/lib/summarizerTypes.js.map +1 -1
  87. package/lib/summaryFormat.d.ts +4 -2
  88. package/lib/summaryFormat.d.ts.map +1 -1
  89. package/lib/summaryFormat.js.map +1 -1
  90. package/lib/summaryManager.d.ts.map +1 -1
  91. package/lib/summaryManager.js +10 -6
  92. package/lib/summaryManager.js.map +1 -1
  93. package/package.json +40 -38
  94. package/src/batchManager.ts +7 -11
  95. package/src/containerRuntime.ts +149 -102
  96. package/src/dataStoreContext.ts +20 -62
  97. package/src/dataStores.ts +2 -10
  98. package/src/garbageCollection.ts +45 -55
  99. package/src/gcSweepReadyUsageDetection.ts +2 -10
  100. package/src/index.ts +2 -3
  101. package/src/packageVersion.ts +1 -1
  102. package/src/pendingStateManager.ts +57 -96
  103. package/src/scheduleManager.ts +1 -0
  104. package/src/summarizer.ts +6 -6
  105. package/src/summarizerTypes.ts +20 -7
  106. package/src/summaryFormat.ts +4 -2
  107. package/src/summaryManager.ts +18 -7
package/dist/index.d.ts CHANGED
@@ -2,14 +2,12 @@
2
2
  * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
3
  * Licensed under the MIT License.
4
4
  */
5
- export { ContainerMessageType, IChunkedOp, ContainerRuntimeMessage, IGCRuntimeOptions, ISummaryRuntimeOptions, ISummaryBaseConfiguration, ISummaryConfigurationHeuristics, ISummaryConfigurationDisableSummarizer, ISummaryConfigurationDisableHeuristics, IContainerRuntimeOptions, IRootSummaryTreeWithStats, isRuntimeMessage, RuntimeMessage, unpackRuntimeMessage, agentSchedulerId, ContainerRuntime, RuntimeHeaders, ISummaryConfiguration, DefaultSummaryConfiguration, } from "./containerRuntime";
6
- export { DeltaScheduler } from "./deltaScheduler";
5
+ export { ContainerMessageType, IChunkedOp, ContainerRuntimeMessage, IGCRuntimeOptions, ISummaryRuntimeOptions, ISummaryBaseConfiguration, ISummaryConfigurationHeuristics, ISummaryConfigurationDisableSummarizer, ISummaryConfigurationDisableHeuristics, IContainerRuntimeOptions, IRootSummaryTreeWithStats, isRuntimeMessage, RuntimeMessage, unpackRuntimeMessage, agentSchedulerId, ContainerRuntime, RuntimeHeaders, ISummaryConfiguration, DefaultSummaryConfiguration, ICompressionRuntimeOptions, } from "./containerRuntime";
7
6
  export { FluidDataStoreRegistry } from "./dataStoreRegistry";
8
7
  export { gcBlobPrefix, gcTreeKey, IGarbageCollectionRuntime, IGCStats, } from "./garbageCollection";
9
- export { IPendingFlush, IPendingFlushMode, IPendingLocalState, IPendingMessage, IPendingState, } from "./pendingStateManager";
10
- export { ScheduleManager } from "./scheduleManager";
8
+ export { IPendingFlush, IPendingLocalState, IPendingMessage, IPendingState, } from "./pendingStateManager";
11
9
  export { Summarizer } from "./summarizer";
12
- export { EnqueueSummarizeResult, IAckSummaryResult, IBaseSummarizeResult, IBroadcastSummaryResult, ICancellationToken, IConnectableRuntime, IEnqueueSummarizeOptions, IGenerateSummaryTreeResult, IGeneratedSummaryStats, INackSummaryResult, IOnDemandSummarizeOptions, IProvideSummarizer, ISubmitSummaryOpResult, ISubmitSummaryOptions, ISummarizeOptions, ISummarizeResults, ISummarizer, ISummarizerEvents, ISummarizerInternalsProvider, ISummarizerRuntime, ISummarizingWarning, ISummaryCancellationToken, IUploadSummaryResult, SubmitSummaryResult, SummarizeResultPart, SummarizerStopReason, } from "./summarizerTypes";
10
+ export { EnqueueSummarizeResult, IAckSummaryResult, IBaseSummarizeResult, IBroadcastSummaryResult, ICancellationToken, IConnectableRuntime, IEnqueueSummarizeOptions, IGenerateSummaryTreeResult, IGeneratedSummaryStats, INackSummaryResult, IOnDemandSummarizeOptions, IProvideSummarizer, IRefreshSummaryAckOptions, ISubmitSummaryOpResult, ISubmitSummaryOptions, ISummarizeOptions, ISummarizeResults, ISummarizer, ISummarizerEvents, ISummarizerInternalsProvider, ISummarizerRuntime, ISummarizingWarning, ISummaryCancellationToken, IUploadSummaryResult, SubmitSummaryResult, SummarizeResultPart, SummarizerStopReason, } from "./summarizerTypes";
13
11
  export { IAckedSummary, IClientSummaryWatcher, ISummary, ISummaryCollectionOpEvents, ISummaryAckMessage, ISummaryNackMessage, ISummaryOpMessage, OpActionEventListener, OpActionEventName, SummaryCollection, } from "./summaryCollection";
14
12
  export { ICancellableSummarizerController, neverCancelledSummaryToken } from "./runWhileConnectedCoordinator";
15
13
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACH,oBAAoB,EACpB,UAAU,EACV,uBAAuB,EACvB,iBAAiB,EACjB,sBAAsB,EACtB,yBAAyB,EACzB,+BAA+B,EAC/B,sCAAsC,EACtC,sCAAsC,EACtC,wBAAwB,EACxB,yBAAyB,EACzB,gBAAgB,EAChB,cAAc,EACd,oBAAoB,EACpB,gBAAgB,EAChB,gBAAgB,EAChB,cAAc,EACd,qBAAqB,EACrB,2BAA2B,GAC9B,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAC7D,OAAO,EACH,YAAY,EACZ,SAAS,EACT,yBAAyB,EACzB,QAAQ,GACX,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACH,aAAa,EACb,iBAAiB,EACjB,kBAAkB,EAClB,eAAe,EACf,aAAa,GAChB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EACH,sBAAsB,EACtB,iBAAiB,EACjB,oBAAoB,EACpB,uBAAuB,EACvB,kBAAkB,EAClB,mBAAmB,EACnB,wBAAwB,EACxB,0BAA0B,EAC1B,sBAAsB,EACtB,kBAAkB,EAClB,yBAAyB,EACzB,kBAAkB,EAClB,sBAAsB,EACtB,qBAAqB,EACrB,iBAAiB,EACjB,iBAAiB,EACjB,WAAW,EACX,iBAAiB,EACjB,4BAA4B,EAC5B,kBAAkB,EAClB,mBAAmB,EACnB,yBAAyB,EACzB,oBAAoB,EACpB,mBAAmB,EACnB,mBAAmB,EACnB,oBAAoB,GACvB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACH,aAAa,EACb,qBAAqB,EACrB,QAAQ,EACR,0BAA0B,EAC1B,kBAAkB,EAClB,mBAAmB,EACnB,iBAAiB,EACjB,qBAAqB,EACrB,iBAAiB,EACjB,iBAAiB,GACpB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,gCAAgC,EAAE,0BAA0B,EAAE,MAAM,gCAAgC,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACH,oBAAoB,EACpB,UAAU,EACV,uBAAuB,EACvB,iBAAiB,EACjB,sBAAsB,EACtB,yBAAyB,EACzB,+BAA+B,EAC/B,sCAAsC,EACtC,sCAAsC,EACtC,wBAAwB,EACxB,yBAAyB,EACzB,gBAAgB,EAChB,cAAc,EACd,oBAAoB,EACpB,gBAAgB,EAChB,gBAAgB,EAChB,cAAc,EACd,qBAAqB,EACrB,2BAA2B,EAC3B,0BAA0B,GAC7B,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAC7D,OAAO,EACH,YAAY,EACZ,SAAS,EACT,yBAAyB,EACzB,QAAQ,GACX,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACH,aAAa,EACb,kBAAkB,EAClB,eAAe,EACf,aAAa,GAChB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EACH,sBAAsB,EACtB,iBAAiB,EACjB,oBAAoB,EACpB,uBAAuB,EACvB,kBAAkB,EAClB,mBAAmB,EACnB,wBAAwB,EACxB,0BAA0B,EAC1B,sBAAsB,EACtB,kBAAkB,EAClB,yBAAyB,EACzB,kBAAkB,EAClB,yBAAyB,EACzB,sBAAsB,EACtB,qBAAqB,EACrB,iBAAiB,EACjB,iBAAiB,EACjB,WAAW,EACX,iBAAiB,EACjB,4BAA4B,EAC5B,kBAAkB,EAClB,mBAAmB,EACnB,yBAAyB,EACzB,oBAAoB,EACpB,mBAAmB,EACnB,mBAAmB,EACnB,oBAAoB,GACvB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACH,aAAa,EACb,qBAAqB,EACrB,QAAQ,EACR,0BAA0B,EAC1B,kBAAkB,EAClB,mBAAmB,EACnB,iBAAiB,EACjB,qBAAqB,EACrB,iBAAiB,EACjB,iBAAiB,GACpB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,gCAAgC,EAAE,0BAA0B,EAAE,MAAM,gCAAgC,CAAC"}
package/dist/index.js CHANGED
@@ -4,7 +4,7 @@
4
4
  * Licensed under the MIT License.
5
5
  */
6
6
  Object.defineProperty(exports, "__esModule", { value: true });
7
- exports.neverCancelledSummaryToken = exports.SummaryCollection = exports.ISummarizer = exports.Summarizer = exports.ScheduleManager = exports.gcTreeKey = exports.gcBlobPrefix = exports.FluidDataStoreRegistry = exports.DeltaScheduler = exports.DefaultSummaryConfiguration = exports.RuntimeHeaders = exports.ContainerRuntime = exports.agentSchedulerId = exports.unpackRuntimeMessage = exports.RuntimeMessage = exports.isRuntimeMessage = exports.ContainerMessageType = void 0;
7
+ exports.neverCancelledSummaryToken = exports.SummaryCollection = exports.ISummarizer = exports.Summarizer = exports.gcTreeKey = exports.gcBlobPrefix = exports.FluidDataStoreRegistry = exports.DefaultSummaryConfiguration = exports.RuntimeHeaders = exports.ContainerRuntime = exports.agentSchedulerId = exports.unpackRuntimeMessage = exports.RuntimeMessage = exports.isRuntimeMessage = exports.ContainerMessageType = void 0;
8
8
  var containerRuntime_1 = require("./containerRuntime");
9
9
  Object.defineProperty(exports, "ContainerMessageType", { enumerable: true, get: function () { return containerRuntime_1.ContainerMessageType; } });
10
10
  Object.defineProperty(exports, "isRuntimeMessage", { enumerable: true, get: function () { return containerRuntime_1.isRuntimeMessage; } });
@@ -14,15 +14,11 @@ Object.defineProperty(exports, "agentSchedulerId", { enumerable: true, get: func
14
14
  Object.defineProperty(exports, "ContainerRuntime", { enumerable: true, get: function () { return containerRuntime_1.ContainerRuntime; } });
15
15
  Object.defineProperty(exports, "RuntimeHeaders", { enumerable: true, get: function () { return containerRuntime_1.RuntimeHeaders; } });
16
16
  Object.defineProperty(exports, "DefaultSummaryConfiguration", { enumerable: true, get: function () { return containerRuntime_1.DefaultSummaryConfiguration; } });
17
- var deltaScheduler_1 = require("./deltaScheduler");
18
- Object.defineProperty(exports, "DeltaScheduler", { enumerable: true, get: function () { return deltaScheduler_1.DeltaScheduler; } });
19
17
  var dataStoreRegistry_1 = require("./dataStoreRegistry");
20
18
  Object.defineProperty(exports, "FluidDataStoreRegistry", { enumerable: true, get: function () { return dataStoreRegistry_1.FluidDataStoreRegistry; } });
21
19
  var garbageCollection_1 = require("./garbageCollection");
22
20
  Object.defineProperty(exports, "gcBlobPrefix", { enumerable: true, get: function () { return garbageCollection_1.gcBlobPrefix; } });
23
21
  Object.defineProperty(exports, "gcTreeKey", { enumerable: true, get: function () { return garbageCollection_1.gcTreeKey; } });
24
- var scheduleManager_1 = require("./scheduleManager");
25
- Object.defineProperty(exports, "ScheduleManager", { enumerable: true, get: function () { return scheduleManager_1.ScheduleManager; } });
26
22
  var summarizer_1 = require("./summarizer");
27
23
  Object.defineProperty(exports, "Summarizer", { enumerable: true, get: function () { return summarizer_1.Summarizer; } });
28
24
  var summarizerTypes_1 = require("./summarizerTypes");
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAEH,uDAoB4B;AAnBxB,wHAAA,oBAAoB,OAAA;AAWpB,oHAAA,gBAAgB,OAAA;AAChB,kHAAA,cAAc,OAAA;AACd,wHAAA,oBAAoB,OAAA;AACpB,oHAAA,gBAAgB,OAAA;AAChB,oHAAA,gBAAgB,OAAA;AAChB,kHAAA,cAAc,OAAA;AAEd,+HAAA,2BAA2B,OAAA;AAE/B,mDAAkD;AAAzC,gHAAA,cAAc,OAAA;AACvB,yDAA6D;AAApD,2HAAA,sBAAsB,OAAA;AAC/B,yDAK6B;AAJzB,iHAAA,YAAY,OAAA;AACZ,8GAAA,SAAS,OAAA;AAWb,qDAAoD;AAA3C,kHAAA,eAAe,OAAA;AACxB,2CAA0C;AAAjC,wGAAA,UAAU,OAAA;AACnB,qDA2B2B;AAVvB,8GAAA,WAAW,OAAA;AAWf,yDAW6B;AADzB,sHAAA,iBAAiB,OAAA;AAErB,+EAA8G;AAAnE,0IAAA,0BAA0B,OAAA","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nexport {\n ContainerMessageType,\n IChunkedOp,\n ContainerRuntimeMessage,\n IGCRuntimeOptions,\n ISummaryRuntimeOptions,\n ISummaryBaseConfiguration,\n ISummaryConfigurationHeuristics,\n ISummaryConfigurationDisableSummarizer,\n ISummaryConfigurationDisableHeuristics,\n IContainerRuntimeOptions,\n IRootSummaryTreeWithStats,\n isRuntimeMessage,\n RuntimeMessage,\n unpackRuntimeMessage,\n agentSchedulerId,\n ContainerRuntime,\n RuntimeHeaders,\n ISummaryConfiguration,\n DefaultSummaryConfiguration,\n} from \"./containerRuntime\";\nexport { DeltaScheduler } from \"./deltaScheduler\";\nexport { FluidDataStoreRegistry } from \"./dataStoreRegistry\";\nexport {\n gcBlobPrefix,\n gcTreeKey,\n IGarbageCollectionRuntime,\n IGCStats,\n} from \"./garbageCollection\";\nexport {\n IPendingFlush,\n IPendingFlushMode,\n IPendingLocalState,\n IPendingMessage,\n IPendingState,\n} from \"./pendingStateManager\";\nexport { ScheduleManager } from \"./scheduleManager\";\nexport { Summarizer } from \"./summarizer\";\nexport {\n EnqueueSummarizeResult,\n IAckSummaryResult,\n IBaseSummarizeResult,\n IBroadcastSummaryResult,\n ICancellationToken,\n IConnectableRuntime,\n IEnqueueSummarizeOptions,\n IGenerateSummaryTreeResult,\n IGeneratedSummaryStats,\n INackSummaryResult,\n IOnDemandSummarizeOptions,\n IProvideSummarizer,\n ISubmitSummaryOpResult,\n ISubmitSummaryOptions,\n ISummarizeOptions,\n ISummarizeResults,\n ISummarizer,\n ISummarizerEvents,\n ISummarizerInternalsProvider,\n ISummarizerRuntime,\n ISummarizingWarning,\n ISummaryCancellationToken,\n IUploadSummaryResult,\n SubmitSummaryResult,\n SummarizeResultPart,\n SummarizerStopReason,\n} from \"./summarizerTypes\";\nexport {\n IAckedSummary,\n IClientSummaryWatcher,\n ISummary,\n ISummaryCollectionOpEvents,\n ISummaryAckMessage,\n ISummaryNackMessage,\n ISummaryOpMessage,\n OpActionEventListener,\n OpActionEventName,\n SummaryCollection,\n} from \"./summaryCollection\";\nexport { ICancellableSummarizerController, neverCancelledSummaryToken } from \"./runWhileConnectedCoordinator\";\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAEH,uDAqB4B;AApBxB,wHAAA,oBAAoB,OAAA;AAWpB,oHAAA,gBAAgB,OAAA;AAChB,kHAAA,cAAc,OAAA;AACd,wHAAA,oBAAoB,OAAA;AACpB,oHAAA,gBAAgB,OAAA;AAChB,oHAAA,gBAAgB,OAAA;AAChB,kHAAA,cAAc,OAAA;AAEd,+HAAA,2BAA2B,OAAA;AAG/B,yDAA6D;AAApD,2HAAA,sBAAsB,OAAA;AAC/B,yDAK6B;AAJzB,iHAAA,YAAY,OAAA;AACZ,8GAAA,SAAS,OAAA;AAUb,2CAA0C;AAAjC,wGAAA,UAAU,OAAA;AACnB,qDA4B2B;AAVvB,8GAAA,WAAW,OAAA;AAWf,yDAW6B;AADzB,sHAAA,iBAAiB,OAAA;AAErB,+EAA8G;AAAnE,0IAAA,0BAA0B,OAAA","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nexport {\n ContainerMessageType,\n IChunkedOp,\n ContainerRuntimeMessage,\n IGCRuntimeOptions,\n ISummaryRuntimeOptions,\n ISummaryBaseConfiguration,\n ISummaryConfigurationHeuristics,\n ISummaryConfigurationDisableSummarizer,\n ISummaryConfigurationDisableHeuristics,\n IContainerRuntimeOptions,\n IRootSummaryTreeWithStats,\n isRuntimeMessage,\n RuntimeMessage,\n unpackRuntimeMessage,\n agentSchedulerId,\n ContainerRuntime,\n RuntimeHeaders,\n ISummaryConfiguration,\n DefaultSummaryConfiguration,\n ICompressionRuntimeOptions,\n} from \"./containerRuntime\";\nexport { FluidDataStoreRegistry } from \"./dataStoreRegistry\";\nexport {\n gcBlobPrefix,\n gcTreeKey,\n IGarbageCollectionRuntime,\n IGCStats,\n} from \"./garbageCollection\";\nexport {\n IPendingFlush,\n IPendingLocalState,\n IPendingMessage,\n IPendingState,\n} from \"./pendingStateManager\";\nexport { Summarizer } from \"./summarizer\";\nexport {\n EnqueueSummarizeResult,\n IAckSummaryResult,\n IBaseSummarizeResult,\n IBroadcastSummaryResult,\n ICancellationToken,\n IConnectableRuntime,\n IEnqueueSummarizeOptions,\n IGenerateSummaryTreeResult,\n IGeneratedSummaryStats,\n INackSummaryResult,\n IOnDemandSummarizeOptions,\n IProvideSummarizer,\n IRefreshSummaryAckOptions,\n ISubmitSummaryOpResult,\n ISubmitSummaryOptions,\n ISummarizeOptions,\n ISummarizeResults,\n ISummarizer,\n ISummarizerEvents,\n ISummarizerInternalsProvider,\n ISummarizerRuntime,\n ISummarizingWarning,\n ISummaryCancellationToken,\n IUploadSummaryResult,\n SubmitSummaryResult,\n SummarizeResultPart,\n SummarizerStopReason,\n} from \"./summarizerTypes\";\nexport {\n IAckedSummary,\n IClientSummaryWatcher,\n ISummary,\n ISummaryCollectionOpEvents,\n ISummaryAckMessage,\n ISummaryNackMessage,\n ISummaryOpMessage,\n OpActionEventListener,\n OpActionEventName,\n SummaryCollection,\n} from \"./summaryCollection\";\nexport { ICancellableSummarizerController, neverCancelledSummaryToken } from \"./runWhileConnectedCoordinator\";\n"]}
@@ -5,5 +5,5 @@
5
5
  * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY
6
6
  */
7
7
  export declare const pkgName = "@fluidframework/container-runtime";
8
- export declare const pkgVersion = "2.0.0-internal.1.4.2";
8
+ export declare const pkgVersion = "2.0.0-internal.2.0.0";
9
9
  //# sourceMappingURL=packageVersion.d.ts.map
@@ -8,5 +8,5 @@
8
8
  Object.defineProperty(exports, "__esModule", { value: true });
9
9
  exports.pkgVersion = exports.pkgName = void 0;
10
10
  exports.pkgName = "@fluidframework/container-runtime";
11
- exports.pkgVersion = "2.0.0-internal.1.4.2";
11
+ exports.pkgVersion = "2.0.0-internal.2.0.0";
12
12
  //# sourceMappingURL=packageVersion.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"packageVersion.js","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;;AAEU,QAAA,OAAO,GAAG,mCAAmC,CAAC;AAC9C,QAAA,UAAU,GAAG,sBAAsB,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n *\n * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY\n */\n\nexport const pkgName = \"@fluidframework/container-runtime\";\nexport const pkgVersion = \"2.0.0-internal.1.4.2\";\n"]}
1
+ {"version":3,"file":"packageVersion.js","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;;AAEU,QAAA,OAAO,GAAG,mCAAmC,CAAC;AAC9C,QAAA,UAAU,GAAG,sBAAsB,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n *\n * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY\n */\n\nexport const pkgName = \"@fluidframework/container-runtime\";\nexport const pkgVersion = \"2.0.0-internal.2.0.0\";\n"]}
@@ -5,7 +5,6 @@
5
5
  import { IDisposable } from "@fluidframework/common-definitions";
6
6
  import { ICriticalContainerError } from "@fluidframework/container-definitions";
7
7
  import { ISequencedDocumentMessage } from "@fluidframework/protocol-definitions";
8
- import { FlushMode } from "@fluidframework/runtime-definitions";
9
8
  import { ContainerMessageType } from "./containerRuntime";
10
9
  /**
11
10
  * This represents a message that has been submitted and is added to the pending queue when `submit` is called on the
@@ -20,14 +19,6 @@ export interface IPendingMessage {
20
19
  localOpMetadata: unknown;
21
20
  opMetadata: Record<string, unknown> | undefined;
22
21
  }
23
- /**
24
- * This represents a FlushMode update and is added to the pending queue when `setFlushMode` is called on the
25
- * ContainerRuntime and the FlushMode changes.
26
- */
27
- export interface IPendingFlushMode {
28
- type: "flushMode";
29
- flushMode: FlushMode;
30
- }
31
22
  /**
32
23
  * This represents an explicit flush call and is added to the pending queue when flush is called on the ContainerRuntime
33
24
  * to flush pending messages.
@@ -35,7 +26,7 @@ export interface IPendingFlushMode {
35
26
  export interface IPendingFlush {
36
27
  type: "flush";
37
28
  }
38
- export declare type IPendingState = IPendingMessage | IPendingFlushMode | IPendingFlush;
29
+ export declare type IPendingState = IPendingMessage | IPendingFlush;
39
30
  export interface IPendingLocalState {
40
31
  /**
41
32
  * list of pending states, including ops and batch information
@@ -45,18 +36,18 @@ export interface IPendingLocalState {
45
36
  export interface IRuntimeStateHandler {
46
37
  connected(): boolean;
47
38
  clientId(): string | undefined;
48
- flushMode(): FlushMode;
49
- setFlushMode(mode: FlushMode): void;
50
39
  close(error?: ICriticalContainerError): void;
51
40
  applyStashedOp: (type: ContainerMessageType, content: ISequencedDocumentMessage) => Promise<unknown>;
52
41
  flush(): void;
53
42
  reSubmit(type: ContainerMessageType, content: any, localOpMetadata: unknown, opMetadata: Record<string, unknown> | undefined): void;
43
+ rollback(type: ContainerMessageType, content: any, localOpMetadata: unknown): void;
44
+ orderSequentially(callback: () => void): void;
54
45
  }
55
46
  /**
56
47
  * PendingStateManager is responsible for maintaining the messages that have not been sent or have not yet been
57
48
  * acknowledged by the server. It also maintains the batch information for both automatically and manually flushed
58
49
  * batches along with the messages.
59
- * When the Container reconnects, it replays the pending states, which includes setting the FlushMode, manual flushing
50
+ * When the Container reconnects, it replays the pending states, which includes manual flushing
60
51
  * of messages and triggering resubmission of unacked ops.
61
52
  *
62
53
  * It verifies that all the ops are acked, are received in the right order and batch information is correct.
@@ -70,12 +61,6 @@ export declare class PendingStateManager implements IDisposable {
70
61
  get pendingMessagesCount(): number;
71
62
  private isProcessingBatch;
72
63
  private pendingBatchBeginMessage;
73
- /**
74
- * This tracks the flush mode for the next message in the pending state queue. When replaying messages, we need to
75
- * first set the flush mode to this value and then send ops. It is important to do this info because the flush
76
- * mode could have been updated.
77
- */
78
- private flushModeForNextMessage;
79
64
  private clientId;
80
65
  /**
81
66
  * Called to check if there are any pending messages in the pending state queue.
@@ -83,7 +68,7 @@ export declare class PendingStateManager implements IDisposable {
83
68
  */
84
69
  hasPendingMessages(): boolean;
85
70
  getLocalState(): IPendingLocalState | undefined;
86
- constructor(stateHandler: IRuntimeStateHandler, initialFlushMode: FlushMode, initialLocalState: IPendingLocalState | undefined);
71
+ constructor(stateHandler: IRuntimeStateHandler, initialLocalState: IPendingLocalState | undefined);
87
72
  get disposed(): boolean;
88
73
  readonly dispose: () => void;
89
74
  /**
@@ -95,11 +80,6 @@ export declare class PendingStateManager implements IDisposable {
95
80
  * @param localOpMetadata - The local metadata associated with the message.
96
81
  */
97
82
  onSubmitMessage(type: ContainerMessageType, clientSequenceNumber: number, referenceSequenceNumber: number, content: any, localOpMetadata: unknown, opMetadata: Record<string, unknown> | undefined): void;
98
- /**
99
- * Called when the FlushMode is updated. Adds the FlushMode to the pending state queue.
100
- * @param flushMode - The flushMode that was updated.
101
- */
102
- onFlushModeUpdated(flushMode: FlushMode): void;
103
83
  /**
104
84
  * Called when flush() is called on the ContainerRuntime to manually flush messages.
105
85
  */
@@ -131,7 +111,7 @@ export declare class PendingStateManager implements IDisposable {
131
111
  private peekNextPendingState;
132
112
  /**
133
113
  * Called when the Container's connection state changes. If the Container gets connected, it replays all the pending
134
- * states in its queue. This includes setting the FlushMode and triggering resubmission of unacked ops.
114
+ * states in its queue. This includes triggering resubmission of unacked ops.
135
115
  */
136
116
  replayPendingStates(): void;
137
117
  }
@@ -1 +1 @@
1
- {"version":3,"file":"pendingStateManager.d.ts","sourceRoot":"","sources":["../src/pendingStateManager.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"pendingStateManager.d.ts","sourceRoot":"","sources":["../src/pendingStateManager.ts"],"names":[],"mappings":"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"}
@@ -10,20 +10,19 @@ Object.defineProperty(exports, "__esModule", { value: true });
10
10
  exports.PendingStateManager = void 0;
11
11
  const common_utils_1 = require("@fluidframework/common-utils");
12
12
  const container_utils_1 = require("@fluidframework/container-utils");
13
- const runtime_definitions_1 = require("@fluidframework/runtime-definitions");
14
13
  const double_ended_queue_1 = __importDefault(require("double-ended-queue"));
15
14
  const packageVersion_1 = require("./packageVersion");
16
15
  /**
17
16
  * PendingStateManager is responsible for maintaining the messages that have not been sent or have not yet been
18
17
  * acknowledged by the server. It also maintains the batch information for both automatically and manually flushed
19
18
  * batches along with the messages.
20
- * When the Container reconnects, it replays the pending states, which includes setting the FlushMode, manual flushing
19
+ * When the Container reconnects, it replays the pending states, which includes manual flushing
21
20
  * of messages and triggering resubmission of unacked ops.
22
21
  *
23
22
  * It verifies that all the ops are acked, are received in the right order and batch information is correct.
24
23
  */
25
24
  class PendingStateManager {
26
- constructor(stateHandler, initialFlushMode, initialLocalState) {
25
+ constructor(stateHandler, initialLocalState) {
27
26
  var _a;
28
27
  this.stateHandler = stateHandler;
29
28
  this.pendingStates = new double_ended_queue_1.default();
@@ -37,8 +36,6 @@ class PendingStateManager {
37
36
  this.isProcessingBatch = false;
38
37
  this.dispose = () => this.disposeOnce.value;
39
38
  this.initialStates = new double_ended_queue_1.default((_a = initialLocalState === null || initialLocalState === void 0 ? void 0 : initialLocalState.pendingStates) !== null && _a !== void 0 ? _a : []);
40
- this.flushModeForNextMessage = initialFlushMode;
41
- this.onFlushModeUpdated(initialFlushMode);
42
39
  }
43
40
  get pendingMessagesCount() {
44
41
  return this._pendingMessagesCount;
@@ -83,22 +80,10 @@ class PendingStateManager {
83
80
  this.pendingStates.push(pendingMessage);
84
81
  this._pendingMessagesCount++;
85
82
  }
86
- /**
87
- * Called when the FlushMode is updated. Adds the FlushMode to the pending state queue.
88
- * @param flushMode - The flushMode that was updated.
89
- */
90
- onFlushModeUpdated(flushMode) {
91
- this.pendingStates.push({ type: "flushMode", flushMode });
92
- }
93
83
  /**
94
84
  * Called when flush() is called on the ContainerRuntime to manually flush messages.
95
85
  */
96
86
  onFlush() {
97
- // If the FlushMode is Immediate, we don't need to track an explicit flush call because every message is
98
- // automatically flushed. So, flush is a no-op.
99
- if (this.stateHandler.flushMode() === runtime_definitions_1.FlushMode.Immediate) {
100
- return;
101
- }
102
87
  // If the previous state is not a message, flush is a no-op.
103
88
  const previousState = this.pendingStates.peekBack();
104
89
  if ((previousState === null || previousState === void 0 ? void 0 : previousState.type) !== "message") {
@@ -169,10 +154,7 @@ class PendingStateManager {
169
154
  * @param message - The message that is being processed.
170
155
  */
171
156
  maybeProcessBatchBegin(message) {
172
- // Tracks the last FlushMode that was set before this message was sent.
173
- let pendingFlushMode;
174
- // Tracks whether a flush was called before this message was sent.
175
- let pendingFlush = false;
157
+ var _a;
176
158
  /**
177
159
  * We are checking if the next message is the start of a batch. It can happen in the following scenarios:
178
160
  *
@@ -184,31 +166,11 @@ class PendingStateManager {
184
166
  * Keep reading pending states from the queue until we encounter a message. It's possible that the FlushMode was
185
167
  * updated a bunch of times without sending any messages.
186
168
  */
187
- let nextPendingState = this.peekNextPendingState();
188
- while (nextPendingState.type !== "message") {
189
- if (nextPendingState.type === "flushMode") {
190
- pendingFlushMode = nextPendingState.flushMode;
191
- }
192
- if (nextPendingState.type === "flush") {
193
- pendingFlush = true;
194
- }
169
+ while (this.peekNextPendingState().type !== "message") {
195
170
  this.pendingStates.shift();
196
- nextPendingState = this.peekNextPendingState();
197
- }
198
- if (pendingFlushMode !== undefined) {
199
- this.flushModeForNextMessage = pendingFlushMode;
200
- }
201
- // If the FlushMode was set to Immediate before this message was sent, this message won't be a batch message
202
- // because in Immediate mode, every message is flushed individually.
203
- if (pendingFlushMode === runtime_definitions_1.FlushMode.Immediate) {
204
- return;
205
171
  }
206
- /**
207
- * This message is the first in a batch if before it was sent either the FlushMode was set to TurnBased or there
208
- * was an explicit flush call. Note that a flush call is tracked only in TurnBased mode and it indicates the end
209
- * of one batch and beginning of another.
210
- */
211
- if (pendingFlushMode === runtime_definitions_1.FlushMode.TurnBased || pendingFlush) {
172
+ // This message is the first in a batch if the "batch" property on the metadata is set to true
173
+ if ((_a = message.metadata) === null || _a === void 0 ? void 0 : _a.batch) {
212
174
  // We should not already be processing a batch and there should be no pending batch begin message.
213
175
  (0, common_utils_1.assert)(!this.isProcessingBatch && this.pendingBatchBeginMessage === undefined, 0x16b /* "The pending batch state indicates we are already processing a batch" */);
214
176
  // Set the pending batch state indicating we have started processing a batch.
@@ -229,12 +191,6 @@ class PendingStateManager {
229
191
  if (nextPendingState.type === "message") {
230
192
  return;
231
193
  }
232
- /**
233
- * We are in the middle of processing a batch. The batch ends when we see an explicit flush. We should never see
234
- * a FlushMode before flush. This is true because we track batches only when FlushMode is TurnBased and in this
235
- * mode, a batch ends either by calling flush or by changing the mode to Immediate which also triggers a flush.
236
- */
237
- (0, common_utils_1.assert)(nextPendingState.type !== "flushMode", 0x2bd /* "We should not see a pending FlushMode until we see a flush when processing a batch" */);
238
194
  // There should be a pending batch begin message.
239
195
  (0, common_utils_1.assert)(this.pendingBatchBeginMessage !== undefined, 0x16d /* "There is no pending batch begin message" */);
240
196
  // Get the batch begin metadata from the first message in the batch.
@@ -276,9 +232,10 @@ class PendingStateManager {
276
232
  }
277
233
  /**
278
234
  * Called when the Container's connection state changes. If the Container gets connected, it replays all the pending
279
- * states in its queue. This includes setting the FlushMode and triggering resubmission of unacked ops.
235
+ * states in its queue. This includes triggering resubmission of unacked ops.
280
236
  */
281
237
  replayPendingStates() {
238
+ var _a, _b;
282
239
  (0, common_utils_1.assert)(this.stateHandler.connected(), 0x172 /* "The connection state is not consistent with the runtime" */);
283
240
  // This assert suggests we are about to send same ops twice, which will result in data loss.
284
241
  (0, common_utils_1.assert)(this.clientId !== this.stateHandler.clientId(), 0x173 /* "replayPendingStates called twice for same clientId!" */);
@@ -290,11 +247,7 @@ class PendingStateManager {
290
247
  }
291
248
  // Reset the pending message count because all these messages will be removed from the queue.
292
249
  this._pendingMessagesCount = 0;
293
- // Save the current FlushMode so that we can revert it back after replaying the states.
294
- const savedFlushMode = this.stateHandler.flushMode();
295
- // Set the flush mode for the next message. This step is important because the flush mode may have been changed
296
- // after the next pending message was sent.
297
- this.stateHandler.setFlushMode(this.flushModeForNextMessage);
250
+ const messageBatchQueue = new double_ended_queue_1.default();
298
251
  // Process exactly `pendingStatesCount` items in the queue as it represents the number of states that were
299
252
  // pending when we connected. This is important because the `reSubmitFn` might add more items in the queue
300
253
  // which must not be replayed.
@@ -303,12 +256,35 @@ class PendingStateManager {
303
256
  const pendingState = this.pendingStates.shift();
304
257
  switch (pendingState.type) {
305
258
  case "message":
306
- this.stateHandler.reSubmit(pendingState.messageType, pendingState.content, pendingState.localOpMetadata, pendingState.opMetadata);
307
- break;
308
- case "flushMode":
309
- this.stateHandler.setFlushMode(pendingState.flushMode);
259
+ (0, common_utils_1.assert)(((_a = pendingState.opMetadata) === null || _a === void 0 ? void 0 : _a.batch) !== false || messageBatchQueue.length > 0, 0x41b /* We cannot process batches in chunks */);
260
+ /**
261
+ * We want to ensure grouped messages get processed in a batch.
262
+ * Note: It is not possible for the PendingStateManager to receive a partially acked batch. It will
263
+ * either receive the whole batch ack or nothing at all.
264
+ */
265
+ if (messageBatchQueue.length > 0 || ((_b = pendingState.opMetadata) === null || _b === void 0 ? void 0 : _b.batch)) {
266
+ messageBatchQueue.enqueue(pendingState);
267
+ }
268
+ else {
269
+ this.stateHandler.reSubmit(pendingState.messageType, pendingState.content, pendingState.localOpMetadata, pendingState.opMetadata);
270
+ }
310
271
  break;
311
272
  case "flush":
273
+ /**
274
+ * A "flush" call can indicate the end of a batch.
275
+ * We can't rely on the "batch" property in the message metadata as it gets
276
+ * updated elsewhere and it is not the same object instance that gets updated.
277
+ */
278
+ if (messageBatchQueue.length > 0) {
279
+ this.stateHandler.orderSequentially(() => {
280
+ while (messageBatchQueue.length > 0) {
281
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
282
+ const message = messageBatchQueue.dequeue();
283
+ this.stateHandler.reSubmit(message.messageType, message.content, message.localOpMetadata, message.opMetadata);
284
+ }
285
+ });
286
+ }
287
+ (0, common_utils_1.assert)(messageBatchQueue.length === 0, 0x41c /* cannot flush in the middle of a batch */);
312
288
  this.stateHandler.flush();
313
289
  break;
314
290
  default:
@@ -316,8 +292,12 @@ class PendingStateManager {
316
292
  }
317
293
  pendingStatesCount--;
318
294
  }
319
- // Revert the FlushMode.
320
- this.stateHandler.setFlushMode(savedFlushMode);
295
+ // There are some cases where ops are stashed but not flushed. We need to ensure they are resubmitted
296
+ while (messageBatchQueue.length > 0) {
297
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
298
+ const message = messageBatchQueue.dequeue();
299
+ this.stateHandler.reSubmit(message.messageType, message.content, message.localOpMetadata, message.opMetadata);
300
+ }
321
301
  }
322
302
  }
323
303
  exports.PendingStateManager = PendingStateManager;
@@ -1 +1 @@
1
- {"version":3,"file":"pendingStateManager.js","sourceRoot":"","sources":["../src/pendingStateManager.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;;;;AAGH,+DAA4D;AAE5D,qEAAsE;AAItE,6EAAgE;AAChE,4EAAuC;AAEvC,qDAA8C;AAyD9C;;;;;;;;GAQG;AACH,MAAa,mBAAmB;IAkD5B,YACqB,YAAkC,EACnD,gBAA2B,EAC3B,iBAAiD;;QAFhC,iBAAY,GAAZ,YAAY,CAAsB;QAlDtC,kBAAa,GAAG,IAAI,4BAAK,EAAiB,CAAC;QAE3C,gBAAW,GAAG,IAAI,mBAAI,CAAO,GAAG,EAAE;YAC/C,IAAI,CAAC,aAAa,CAAC,KAAK,EAAE,CAAC;YAC3B,IAAI,CAAC,aAAa,CAAC,KAAK,EAAE,CAAC;QAC/B,CAAC,CAAC,CAAC;QAEH,8DAA8D;QACtD,0BAAqB,GAAW,CAAC,CAAC;QAK1C,+CAA+C;QACvC,sBAAiB,GAAY,KAAK,CAAC;QA+C3B,YAAO,GAAG,GAAG,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC;QAPnD,IAAI,CAAC,aAAa,GAAG,IAAI,4BAAK,CAAgB,MAAA,iBAAiB,aAAjB,iBAAiB,uBAAjB,iBAAiB,CAAE,aAAa,mCAAI,EAAE,CAAC,CAAC;QAEtF,IAAI,CAAC,uBAAuB,GAAG,gBAAgB,CAAC;QAChD,IAAI,CAAC,kBAAkB,CAAC,gBAAgB,CAAC,CAAC;IAC9C,CAAC;IAjDD,IAAW,oBAAoB;QAC3B,OAAO,IAAI,CAAC,qBAAqB,CAAC;IACtC,CAAC;IAkBD;;;OAGG;IACI,kBAAkB;QACrB,OAAO,IAAI,CAAC,qBAAqB,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,OAAO,EAAE,CAAC;IAC7E,CAAC;IAEM,aAAa;QAChB,IAAA,qBAAM,EAAC,IAAI,CAAC,aAAa,CAAC,OAAO,EAAE,EAAE,KAAK,CAAC,+DAA+D,CAAC,CAAC;QAC5G,IAAI,IAAI,CAAC,kBAAkB,EAAE,EAAE;YAC3B,OAAO;gBACH,aAAa,EAAE,IAAI,CAAC,aAAa,CAAC,OAAO,EAAE,CAAC,GAAG;gBAC3C,0DAA0D;gBAC1D,8CAA8C;gBAC9C,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,iCAAM,KAAK,KAAE,eAAe,EAAE,SAAS,IAAG,CAAC,CAAC,KAAK,CAAC;aAC9F,CAAC;SACL;IACL,CAAC;IAaD,IAAW,QAAQ,KAAK,OAAO,IAAI,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC,CAAC;IAG5D;;;;;;;OAOG;IACI,eAAe,CAClB,IAA0B,EAC1B,oBAA4B,EAC5B,uBAA+B,EAC/B,OAAY,EACZ,eAAwB,EACxB,UAA+C;QAE/C,MAAM,cAAc,GAAoB;YACpC,IAAI,EAAE,SAAS;YACf,WAAW,EAAE,IAAI;YACjB,oBAAoB;YACpB,uBAAuB;YACvB,OAAO;YACP,eAAe;YACf,UAAU;SACb,CAAC;QAEF,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QAExC,IAAI,CAAC,qBAAqB,EAAE,CAAC;IACjC,CAAC;IAED;;;OAGG;IACI,kBAAkB,CAAC,SAAoB;QAC1C,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,SAAS,EAAE,CAAC,CAAC;IAC9D,CAAC;IAED;;OAEG;IACI,OAAO;QACV,wGAAwG;QACxG,+CAA+C;QAC/C,IAAI,IAAI,CAAC,YAAY,CAAC,SAAS,EAAE,KAAK,+BAAS,CAAC,SAAS,EAAE;YACvD,OAAO;SACV;QAED,4DAA4D;QAC5D,MAAM,aAAa,GAAG,IAAI,CAAC,aAAa,CAAC,QAAQ,EAAE,CAAC;QACpD,IAAI,CAAA,aAAa,aAAb,aAAa,uBAAb,aAAa,CAAE,IAAI,MAAK,SAAS,EAAE;YACnC,OAAO;SACV;QAED,qGAAqG;QACrG,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;IAC/C,CAAC;IAED;;;OAGG;IACI,KAAK,CAAC,iBAAiB,CAAC,MAAe;QAC1C,uCAAuC;QACvC,OAAO,CAAC,IAAI,CAAC,aAAa,CAAC,OAAO,EAAE,EAAE;YAClC,oEAAoE;YACpE,MAAM,SAAS,GAAG,IAAI,CAAC,aAAa,CAAC,SAAS,EAAG,CAAC;YAClD,IAAI,SAAS,CAAC,IAAI,KAAK,SAAS,EAAE;gBAC9B,IAAI,MAAM,KAAK,SAAS,EAAE;oBACtB,IAAI,SAAS,CAAC,uBAAuB,GAAG,MAAM,EAAE;wBAC5C,MAAM,CAAC,6CAA6C;qBACvD;yBAAM,IAAI,SAAS,CAAC,uBAAuB,GAAG,MAAM,EAAE;wBACnD,MAAM,IAAI,KAAK,CAAC,sDAAsD,CAAC,CAAC;qBAC3E;iBACJ;gBAED,gGAAgG;gBAChG,MAAM,eAAe,GACjB,MAAM,IAAI,CAAC,YAAY,CAAC,cAAc,CAAC,SAAS,CAAC,WAAW,EAAE,SAAS,CAAC,OAAO,CAAC,CAAC;gBACrF,SAAS,CAAC,eAAe,GAAG,eAAe,CAAC;aAC/C;YAED,mGAAmG;YACnG,oEAAoE;YACpE,MAAM,iBAAiB,GAAG,IAAI,CAAC,aAAa,CAAC,KAAK,EAAG,CAAC;YACtD,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;YAC3C,IAAI,iBAAiB,CAAC,IAAI,KAAK,SAAS,EAAE;gBACtC,IAAI,CAAC,qBAAqB,EAAE,CAAC;aAChC;SACJ;IACL,CAAC;IAED;;;;OAIG;IACI,0BAA0B,CAAC,OAAkC;QAChE,0DAA0D;QAC1D,IAAI,CAAC,sBAAsB,CAAC,OAAO,CAAC,CAAC;QAErC,qFAAqF;QACrF,MAAM,YAAY,GAAG,IAAI,CAAC,oBAAoB,EAAE,CAAC;QACjD,IAAA,qBAAM,EAAC,YAAY,CAAC,IAAI,KAAK,SAAS,EAAE,KAAK,CAAC,wDAAwD,CAAC,CAAC;QACxG,IAAI,CAAC,aAAa,CAAC,KAAK,EAAE,CAAC;QAE3B,mEAAmE;QACnE,2FAA2F;QAC3F,IAAI,YAAY,CAAC,oBAAoB,KAAK,OAAO,CAAC,oBAAoB,EAAE;YACpE,mEAAmE;YACnE,MAAM,KAAK,GAAG,qCAAmB,CAAC,MAAM,CACpC,qDAAqD,EACrD,uBAAuB,EACvB,OAAO,EACP,EAAE,4BAA4B,EAAE,YAAY,CAAC,oBAAoB,EAAE,CACtE,CAAC;YAEF,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YAC/B,OAAO;SACV;QAED,IAAI,CAAC,qBAAqB,EAAE,CAAC;QAC7B,IAAA,qBAAM,EAAC,IAAI,CAAC,qBAAqB,IAAI,CAAC,EAAE,KAAK,CAAC,cAAc,CAAC,CAAC;QAE9D,wGAAwG;QACxG,IAAI,CAAC,oBAAoB,CAAC,OAAO,CAAC,CAAC;QAEnC,OAAO,YAAY,CAAC,eAAe,CAAC;IACxC,CAAC;IAED;;;OAGG;IACK,sBAAsB,CAAC,OAAkC;QAC7D,uEAAuE;QACvE,IAAI,gBAAuC,CAAC;QAC5C,kEAAkE;QAClE,IAAI,YAAY,GAAY,KAAK,CAAC;QAElC;;;;;;;;;;WAUG;QACH,IAAI,gBAAgB,GAAG,IAAI,CAAC,oBAAoB,EAAE,CAAC;QACnD,OAAO,gBAAgB,CAAC,IAAI,KAAK,SAAS,EAAE;YACxC,IAAI,gBAAgB,CAAC,IAAI,KAAK,WAAW,EAAE;gBACvC,gBAAgB,GAAG,gBAAgB,CAAC,SAAS,CAAC;aACjD;YACD,IAAI,gBAAgB,CAAC,IAAI,KAAK,OAAO,EAAE;gBACnC,YAAY,GAAG,IAAI,CAAC;aACvB;YACD,IAAI,CAAC,aAAa,CAAC,KAAK,EAAE,CAAC;YAC3B,gBAAgB,GAAG,IAAI,CAAC,oBAAoB,EAAE,CAAC;SAClD;QAED,IAAI,gBAAgB,KAAK,SAAS,EAAE;YAChC,IAAI,CAAC,uBAAuB,GAAG,gBAAgB,CAAC;SACnD;QAED,4GAA4G;QAC5G,oEAAoE;QACpE,IAAI,gBAAgB,KAAK,+BAAS,CAAC,SAAS,EAAE;YAC1C,OAAO;SACV;QAED;;;;WAIG;QACH,IAAI,gBAAgB,KAAK,+BAAS,CAAC,SAAS,IAAI,YAAY,EAAE;YAC1D,kGAAkG;YAClG,IAAA,qBAAM,EAAC,CAAC,IAAI,CAAC,iBAAiB,IAAI,IAAI,CAAC,wBAAwB,KAAK,SAAS,EACzE,KAAK,CAAC,2EAA2E,CAAC,CAAC;YAEvF,6EAA6E;YAC7E,IAAI,CAAC,wBAAwB,GAAG,OAAO,CAAC;YACxC,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC;SACjC;IACL,CAAC;IAED;;;OAGG;IACK,oBAAoB,CAAC,OAAkC;;QAC3D,IAAI,CAAC,IAAI,CAAC,iBAAiB,EAAE;YACzB,OAAO;SACV;QAED,MAAM,gBAAgB,GAAG,IAAI,CAAC,oBAAoB,EAAE,CAAC;QACrD,IAAI,gBAAgB,CAAC,IAAI,KAAK,SAAS,EAAE;YACrC,OAAO;SACV;QAED;;;;WAIG;QACH,IAAA,qBAAM,EACF,gBAAgB,CAAC,IAAI,KAAK,WAAW,EACrC,KAAK,CAAC,0FAA0F,CACnG,CAAC;QAEF,iDAAiD;QACjD,IAAA,qBAAM,EAAC,IAAI,CAAC,wBAAwB,KAAK,SAAS,EAAE,KAAK,CAAC,+CAA+C,CAAC,CAAC;QAE3G,oEAAoE;QACpE,MAAM,kBAAkB,GAAG,MAAA,IAAI,CAAC,wBAAwB,CAAC,QAAQ,0CAAE,KAAK,CAAC;QAEzE,4GAA4G;QAC5G,mGAAmG;QACnG,IAAI,IAAI,CAAC,wBAAwB,KAAK,OAAO,EAAE;YAC3C,IAAA,qBAAM,EAAC,kBAAkB,KAAK,SAAS,EACnC,KAAK,CAAC,gEAAgE,CAAC,CAAC;SAC/E;aAAM;YACH,6DAA6D;YAC7D,MAAM,gBAAgB,GAAG,MAAA,OAAO,CAAC,QAAQ,0CAAE,KAAK,CAAC;YACjD,IAAI,kBAAkB,KAAK,IAAI,IAAI,gBAAgB,KAAK,KAAK,EAAE;gBAC3D,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,qCAAmB,CAAC,MAAM,CAC9C,6BAA6B,EAAE,4CAA4C;gBAC3E,4BAA4B,EAC5B,OAAO,EACP;oBACI,cAAc,EAAE,2BAAU;oBAC1B,aAAa,EAAE,IAAI,CAAC,wBAAwB,CAAC,QAAQ;oBACrD,QAAQ,EAAE,IAAI,CAAC,YAAY,CAAC,QAAQ,EAAE;oBACtC,aAAa,EAAE,kBAAkB,KAAK,IAAI;oBAC1C,WAAW,EAAE,gBAAgB,KAAK,KAAK;oBACvC,WAAW,EAAE,OAAO,CAAC,IAAI;oBACzB,wBAAwB,EAAE,IAAI,CAAC,wBAAwB,CAAC,oBAAoB;oBAC5E,oBAAoB,EAAE,IAAI,CAAC,oBAAoB;oBAC/C,gBAAgB,EAAE,gBAAgB,CAAC,IAAI;iBAC1C,CAAC,CAAC,CAAC;aACX;SACJ;QAED,6EAA6E;QAC7E,IAAI,CAAC,wBAAwB,GAAG,SAAS,CAAC;QAC1C,IAAI,CAAC,iBAAiB,GAAG,KAAK,CAAC;IACnC,CAAC;IAED;;OAEG;IACK,oBAAoB;QACxB,MAAM,gBAAgB,GAAG,IAAI,CAAC,aAAa,CAAC,SAAS,EAAE,CAAC;QACxD,IAAA,qBAAM,EAAC,CAAC,CAAC,gBAAgB,EAAE,KAAK,CAAC,qDAAqD,CAAC,CAAC;QACxF,OAAO,gBAAgB,CAAC;IAC5B,CAAC;IAED;;;OAGG;IACI,mBAAmB;QACtB,IAAA,qBAAM,EAAC,IAAI,CAAC,YAAY,CAAC,SAAS,EAAE,EAAE,KAAK,CAAC,+DAA+D,CAAC,CAAC;QAE7G,4FAA4F;QAC5F,IAAA,qBAAM,EAAC,IAAI,CAAC,QAAQ,KAAK,IAAI,CAAC,YAAY,CAAC,QAAQ,EAAE,EACjD,KAAK,CAAC,2DAA2D,CAAC,CAAC;QACvE,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,YAAY,CAAC,QAAQ,EAAE,CAAC;QAE7C,IAAA,qBAAM,EAAC,IAAI,CAAC,aAAa,CAAC,OAAO,EAAE,EAAE,KAAK,CAAC,+DAA+D,CAAC,CAAC;QAE5G,IAAI,kBAAkB,GAAG,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC;QACnD,IAAI,kBAAkB,KAAK,CAAC,EAAE;YAC1B,OAAO;SACV;QAED,6FAA6F;QAC7F,IAAI,CAAC,qBAAqB,GAAG,CAAC,CAAC;QAE/B,uFAAuF;QACvF,MAAM,cAAc,GAAG,IAAI,CAAC,YAAY,CAAC,SAAS,EAAE,CAAC;QAErD,+GAA+G;QAC/G,2CAA2C;QAC3C,IAAI,CAAC,YAAY,CAAC,YAAY,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC;QAE7D,0GAA0G;QAC1G,0GAA0G;QAC1G,8BAA8B;QAC9B,OAAO,kBAAkB,GAAG,CAAC,EAAE;YAC3B,oEAAoE;YACpE,MAAM,YAAY,GAAG,IAAI,CAAC,aAAa,CAAC,KAAK,EAAG,CAAC;YACjD,QAAQ,YAAY,CAAC,IAAI,EAAE;gBACvB,KAAK,SAAS;oBACV,IAAI,CAAC,YAAY,CAAC,QAAQ,CACtB,YAAY,CAAC,WAAW,EACxB,YAAY,CAAC,OAAO,EACpB,YAAY,CAAC,eAAe,EAC5B,YAAY,CAAC,UAAU,CAAC,CAAC;oBAC7B,MAAM;gBACV,KAAK,WAAW;oBACZ,IAAI,CAAC,YAAY,CAAC,YAAY,CAAC,YAAY,CAAC,SAAS,CAAC,CAAC;oBACvD,MAAM;gBACV,KAAK,OAAO;oBACR,IAAI,CAAC,YAAY,CAAC,KAAK,EAAE,CAAC;oBAC1B,MAAM;gBACV;oBACI,MAAM;aACb;YACD,kBAAkB,EAAE,CAAC;SACxB;QAED,wBAAwB;QACxB,IAAI,CAAC,YAAY,CAAC,YAAY,CAAC,cAAc,CAAC,CAAC;IACnD,CAAC;CACJ;AA/XD,kDA+XC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { IDisposable } from \"@fluidframework/common-definitions\";\nimport { assert, Lazy } from \"@fluidframework/common-utils\";\nimport { ICriticalContainerError } from \"@fluidframework/container-definitions\";\nimport { DataProcessingError } from \"@fluidframework/container-utils\";\nimport {\n ISequencedDocumentMessage,\n} from \"@fluidframework/protocol-definitions\";\nimport { FlushMode } from \"@fluidframework/runtime-definitions\";\nimport Deque from \"double-ended-queue\";\nimport { ContainerMessageType } from \"./containerRuntime\";\nimport { pkgVersion } from \"./packageVersion\";\n\n/**\n * This represents a message that has been submitted and is added to the pending queue when `submit` is called on the\n * ContainerRuntime. This message has either not been ack'd by the server or has not been submitted to the server yet.\n */\nexport interface IPendingMessage {\n type: \"message\";\n messageType: ContainerMessageType;\n clientSequenceNumber: number;\n referenceSequenceNumber: number;\n content: any;\n localOpMetadata: unknown;\n opMetadata: Record<string, unknown> | undefined;\n}\n\n/**\n * This represents a FlushMode update and is added to the pending queue when `setFlushMode` is called on the\n * ContainerRuntime and the FlushMode changes.\n */\nexport interface IPendingFlushMode {\n type: \"flushMode\";\n flushMode: FlushMode;\n}\n\n/**\n * This represents an explicit flush call and is added to the pending queue when flush is called on the ContainerRuntime\n * to flush pending messages.\n */\nexport interface IPendingFlush {\n type: \"flush\";\n}\n\nexport type IPendingState = IPendingMessage | IPendingFlushMode | IPendingFlush;\n\nexport interface IPendingLocalState {\n /**\n * list of pending states, including ops and batch information\n */\n pendingStates: IPendingState[];\n}\n\nexport interface IRuntimeStateHandler{\n connected(): boolean;\n clientId(): string | undefined;\n flushMode(): FlushMode;\n setFlushMode(mode: FlushMode): void;\n close(error?: ICriticalContainerError): void;\n applyStashedOp: (type: ContainerMessageType, content: ISequencedDocumentMessage) => Promise<unknown>;\n flush(): void;\n reSubmit(\n type: ContainerMessageType,\n content: any,\n localOpMetadata: unknown,\n opMetadata: Record<string, unknown> | undefined): void;\n}\n\n/**\n * PendingStateManager is responsible for maintaining the messages that have not been sent or have not yet been\n * acknowledged by the server. It also maintains the batch information for both automatically and manually flushed\n * batches along with the messages.\n * When the Container reconnects, it replays the pending states, which includes setting the FlushMode, manual flushing\n * of messages and triggering resubmission of unacked ops.\n *\n * It verifies that all the ops are acked, are received in the right order and batch information is correct.\n */\nexport class PendingStateManager implements IDisposable {\n private readonly pendingStates = new Deque<IPendingState>();\n private readonly initialStates: Deque<IPendingState>;\n private readonly disposeOnce = new Lazy<void>(() => {\n this.initialStates.clear();\n this.pendingStates.clear();\n });\n\n // Maintains the count of messages that are currently unacked.\n private _pendingMessagesCount: number = 0;\n public get pendingMessagesCount(): number {\n return this._pendingMessagesCount;\n }\n\n // Indicates whether we are processing a batch.\n private isProcessingBatch: boolean = false;\n\n // This stores the first message in the batch that we are processing. This is used to verify that we get\n // the correct batch metadata.\n private pendingBatchBeginMessage: ISequencedDocumentMessage | undefined;\n\n /**\n * This tracks the flush mode for the next message in the pending state queue. When replaying messages, we need to\n * first set the flush mode to this value and then send ops. It is important to do this info because the flush\n * mode could have been updated.\n */\n private flushModeForNextMessage: FlushMode;\n\n private clientId: string | undefined;\n\n /**\n * Called to check if there are any pending messages in the pending state queue.\n * @returns A boolean indicating whether there are messages or not.\n */\n public hasPendingMessages(): boolean {\n return this._pendingMessagesCount !== 0 || !this.initialStates.isEmpty();\n }\n\n public getLocalState(): IPendingLocalState | undefined {\n assert(this.initialStates.isEmpty(), 0x2e9 /* \"Must call getLocalState() after applying initial states\" */);\n if (this.hasPendingMessages()) {\n return {\n pendingStates: this.pendingStates.toArray().map(\n // delete localOpMetadata since it may not be serializable\n // and will be regenerated by applyStashedOp()\n (state) => state.type === \"message\" ? { ...state, localOpMetadata: undefined } : state),\n };\n }\n }\n\n constructor(\n private readonly stateHandler: IRuntimeStateHandler,\n initialFlushMode: FlushMode,\n initialLocalState: IPendingLocalState | undefined,\n ) {\n this.initialStates = new Deque<IPendingState>(initialLocalState?.pendingStates ?? []);\n\n this.flushModeForNextMessage = initialFlushMode;\n this.onFlushModeUpdated(initialFlushMode);\n }\n\n public get disposed() { return this.disposeOnce.evaluated; }\n public readonly dispose = () => this.disposeOnce.value;\n\n /**\n * Called when a message is submitted locally. Adds the message and the associated details to the pending state\n * queue.\n * @param type - The container message type.\n * @param clientSequenceNumber - The clientSequenceNumber associated with the message.\n * @param content - The message content.\n * @param localOpMetadata - The local metadata associated with the message.\n */\n public onSubmitMessage(\n type: ContainerMessageType,\n clientSequenceNumber: number,\n referenceSequenceNumber: number,\n content: any,\n localOpMetadata: unknown,\n opMetadata: Record<string, unknown> | undefined,\n ) {\n const pendingMessage: IPendingMessage = {\n type: \"message\",\n messageType: type,\n clientSequenceNumber,\n referenceSequenceNumber,\n content,\n localOpMetadata,\n opMetadata,\n };\n\n this.pendingStates.push(pendingMessage);\n\n this._pendingMessagesCount++;\n }\n\n /**\n * Called when the FlushMode is updated. Adds the FlushMode to the pending state queue.\n * @param flushMode - The flushMode that was updated.\n */\n public onFlushModeUpdated(flushMode: FlushMode) {\n this.pendingStates.push({ type: \"flushMode\", flushMode });\n }\n\n /**\n * Called when flush() is called on the ContainerRuntime to manually flush messages.\n */\n public onFlush() {\n // If the FlushMode is Immediate, we don't need to track an explicit flush call because every message is\n // automatically flushed. So, flush is a no-op.\n if (this.stateHandler.flushMode() === FlushMode.Immediate) {\n return;\n }\n\n // If the previous state is not a message, flush is a no-op.\n const previousState = this.pendingStates.peekBack();\n if (previousState?.type !== \"message\") {\n return;\n }\n\n // An explicit flush is interesting and is tracked only if there are messages sent in TurnBased mode.\n this.pendingStates.push({ type: \"flush\" });\n }\n\n /**\n * Applies stashed ops at their reference sequence number so they are ready to be ACKed or resubmitted\n * @param seqNum - Sequence number at which to apply ops. Will apply all ops if seqNum is undefined.\n */\n public async applyStashedOpsAt(seqNum?: number) {\n // apply stashed ops at sequence number\n while (!this.initialStates.isEmpty()) {\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const nextState = this.initialStates.peekFront()!;\n if (nextState.type === \"message\") {\n if (seqNum !== undefined) {\n if (nextState.referenceSequenceNumber > seqNum) {\n break; // nothing left to do at this sequence number\n } else if (nextState.referenceSequenceNumber < seqNum) {\n throw new Error(\"loaded from snapshot too recent to apply stashed ops\");\n }\n }\n\n // applyStashedOp will cause the DDS to behave as if it has sent the op but not actually send it\n const localOpMetadata =\n await this.stateHandler.applyStashedOp(nextState.messageType, nextState.content);\n nextState.localOpMetadata = localOpMetadata;\n }\n\n // then we push onto pendingStates which will cause PendingStateManager to resubmit when we connect\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const firstPendingState = this.initialStates.shift()!;\n this.pendingStates.push(firstPendingState);\n if (firstPendingState.type === \"message\") {\n this._pendingMessagesCount++;\n }\n }\n }\n\n /**\n * Processes a local message once its ack'd by the server. It verifies that there was no data corruption and that\n * the batch information was preserved for batch messages.\n * @param message - The message that got ack'd and needs to be processed.\n */\n public processPendingLocalMessage(message: ISequencedDocumentMessage): unknown {\n // Pre-processing part - This may be the start of a batch.\n this.maybeProcessBatchBegin(message);\n\n // Get the next state from the pending queue and verify that it is of type \"message\".\n const pendingState = this.peekNextPendingState();\n assert(pendingState.type === \"message\", 0x169 /* \"No pending message found for this remote message\" */);\n this.pendingStates.shift();\n\n // Processing part - Verify that there has been no data corruption.\n // The clientSequenceNumber of the incoming message must match that of the pending message.\n if (pendingState.clientSequenceNumber !== message.clientSequenceNumber) {\n // Close the container because this could indicate data corruption.\n const error = DataProcessingError.create(\n \"pending local message clientSequenceNumber mismatch\",\n \"unexpectedAckReceived\",\n message,\n { expectedClientSequenceNumber: pendingState.clientSequenceNumber },\n );\n\n this.stateHandler.close(error);\n return;\n }\n\n this._pendingMessagesCount--;\n assert(this._pendingMessagesCount >= 0, 0x3d6 /* positive */);\n\n // Post-processing part - If we are processing a batch then this could be the last message in the batch.\n this.maybeProcessBatchEnd(message);\n\n return pendingState.localOpMetadata;\n }\n\n /**\n * This message could be the first message in batch. If so, set batch state marking the beginning of a batch.\n * @param message - The message that is being processed.\n */\n private maybeProcessBatchBegin(message: ISequencedDocumentMessage) {\n // Tracks the last FlushMode that was set before this message was sent.\n let pendingFlushMode: FlushMode | undefined;\n // Tracks whether a flush was called before this message was sent.\n let pendingFlush: boolean = false;\n\n /**\n * We are checking if the next message is the start of a batch. It can happen in the following scenarios:\n *\n * 1. The FlushMode was set to TurnBased before this message was sent.\n *\n * 2. The FlushMode was already TurnBased and a flush was called before this message was sent. This essentially\n * means that the flush marked the end of a previous batch and beginning of a new batch.\n *\n * Keep reading pending states from the queue until we encounter a message. It's possible that the FlushMode was\n * updated a bunch of times without sending any messages.\n */\n let nextPendingState = this.peekNextPendingState();\n while (nextPendingState.type !== \"message\") {\n if (nextPendingState.type === \"flushMode\") {\n pendingFlushMode = nextPendingState.flushMode;\n }\n if (nextPendingState.type === \"flush\") {\n pendingFlush = true;\n }\n this.pendingStates.shift();\n nextPendingState = this.peekNextPendingState();\n }\n\n if (pendingFlushMode !== undefined) {\n this.flushModeForNextMessage = pendingFlushMode;\n }\n\n // If the FlushMode was set to Immediate before this message was sent, this message won't be a batch message\n // because in Immediate mode, every message is flushed individually.\n if (pendingFlushMode === FlushMode.Immediate) {\n return;\n }\n\n /**\n * This message is the first in a batch if before it was sent either the FlushMode was set to TurnBased or there\n * was an explicit flush call. Note that a flush call is tracked only in TurnBased mode and it indicates the end\n * of one batch and beginning of another.\n */\n if (pendingFlushMode === FlushMode.TurnBased || pendingFlush) {\n // We should not already be processing a batch and there should be no pending batch begin message.\n assert(!this.isProcessingBatch && this.pendingBatchBeginMessage === undefined,\n 0x16b /* \"The pending batch state indicates we are already processing a batch\" */);\n\n // Set the pending batch state indicating we have started processing a batch.\n this.pendingBatchBeginMessage = message;\n this.isProcessingBatch = true;\n }\n }\n\n /**\n * This message could be the last message in batch. If so, clear batch state since the batch is complete.\n * @param message - The message that is being processed.\n */\n private maybeProcessBatchEnd(message: ISequencedDocumentMessage) {\n if (!this.isProcessingBatch) {\n return;\n }\n\n const nextPendingState = this.peekNextPendingState();\n if (nextPendingState.type === \"message\") {\n return;\n }\n\n /**\n * We are in the middle of processing a batch. The batch ends when we see an explicit flush. We should never see\n * a FlushMode before flush. This is true because we track batches only when FlushMode is TurnBased and in this\n * mode, a batch ends either by calling flush or by changing the mode to Immediate which also triggers a flush.\n */\n assert(\n nextPendingState.type !== \"flushMode\",\n 0x2bd /* \"We should not see a pending FlushMode until we see a flush when processing a batch\" */,\n );\n\n // There should be a pending batch begin message.\n assert(this.pendingBatchBeginMessage !== undefined, 0x16d /* \"There is no pending batch begin message\" */);\n\n // Get the batch begin metadata from the first message in the batch.\n const batchBeginMetadata = this.pendingBatchBeginMessage.metadata?.batch;\n\n // There could be just a single message in the batch. If so, it should not have any batch metadata. If there\n // are multiple messages in the batch, verify that we got the correct batch begin and end metadata.\n if (this.pendingBatchBeginMessage === message) {\n assert(batchBeginMetadata === undefined,\n 0x16e /* \"Batch with single message should not have batch metadata\" */);\n } else {\n // Get the batch metadata from the last message in the batch.\n const batchEndMetadata = message.metadata?.batch;\n if (batchBeginMetadata !== true || batchEndMetadata !== false) {\n this.stateHandler.close(DataProcessingError.create(\n \"Pending batch inconsistency\", // Formerly known as asserts 0x16f and 0x170\n \"processPendingLocalMessage\",\n message,\n {\n runtimeVersion: pkgVersion,\n batchClientId: this.pendingBatchBeginMessage.clientId,\n clientId: this.stateHandler.clientId(),\n hasBatchStart: batchBeginMetadata === true,\n hasBatchEnd: batchEndMetadata === false,\n messageType: message.type,\n batchStartSequenceNumber: this.pendingBatchBeginMessage.clientSequenceNumber,\n pendingMessagesCount: this.pendingMessagesCount,\n nextPendingState: nextPendingState.type,\n }));\n }\n }\n\n // Clear the pending batch state now that we have processed the entire batch.\n this.pendingBatchBeginMessage = undefined;\n this.isProcessingBatch = false;\n }\n\n /**\n * Returns the next pending state from the pending state queue.\n */\n private peekNextPendingState(): IPendingState {\n const nextPendingState = this.pendingStates.peekFront();\n assert(!!nextPendingState, 0x171 /* \"No pending state found for the remote message\" */);\n return nextPendingState;\n }\n\n /**\n * Called when the Container's connection state changes. If the Container gets connected, it replays all the pending\n * states in its queue. This includes setting the FlushMode and triggering resubmission of unacked ops.\n */\n public replayPendingStates() {\n assert(this.stateHandler.connected(), 0x172 /* \"The connection state is not consistent with the runtime\" */);\n\n // This assert suggests we are about to send same ops twice, which will result in data loss.\n assert(this.clientId !== this.stateHandler.clientId(),\n 0x173 /* \"replayPendingStates called twice for same clientId!\" */);\n this.clientId = this.stateHandler.clientId();\n\n assert(this.initialStates.isEmpty(), 0x174 /* \"initial states should be empty before replaying pending\" */);\n\n let pendingStatesCount = this.pendingStates.length;\n if (pendingStatesCount === 0) {\n return;\n }\n\n // Reset the pending message count because all these messages will be removed from the queue.\n this._pendingMessagesCount = 0;\n\n // Save the current FlushMode so that we can revert it back after replaying the states.\n const savedFlushMode = this.stateHandler.flushMode();\n\n // Set the flush mode for the next message. This step is important because the flush mode may have been changed\n // after the next pending message was sent.\n this.stateHandler.setFlushMode(this.flushModeForNextMessage);\n\n // Process exactly `pendingStatesCount` items in the queue as it represents the number of states that were\n // pending when we connected. This is important because the `reSubmitFn` might add more items in the queue\n // which must not be replayed.\n while (pendingStatesCount > 0) {\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const pendingState = this.pendingStates.shift()!;\n switch (pendingState.type) {\n case \"message\":\n this.stateHandler.reSubmit(\n pendingState.messageType,\n pendingState.content,\n pendingState.localOpMetadata,\n pendingState.opMetadata);\n break;\n case \"flushMode\":\n this.stateHandler.setFlushMode(pendingState.flushMode);\n break;\n case \"flush\":\n this.stateHandler.flush();\n break;\n default:\n break;\n }\n pendingStatesCount--;\n }\n\n // Revert the FlushMode.\n this.stateHandler.setFlushMode(savedFlushMode);\n }\n}\n"]}
1
+ {"version":3,"file":"pendingStateManager.js","sourceRoot":"","sources":["../src/pendingStateManager.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { IDisposable } from \"@fluidframework/common-definitions\";\nimport { assert, Lazy } from \"@fluidframework/common-utils\";\nimport { ICriticalContainerError } from \"@fluidframework/container-definitions\";\nimport { DataProcessingError } from \"@fluidframework/container-utils\";\nimport {\n ISequencedDocumentMessage,\n} from \"@fluidframework/protocol-definitions\";\nimport Deque from \"double-ended-queue\";\nimport { ContainerMessageType } from \"./containerRuntime\";\nimport { pkgVersion } from \"./packageVersion\";\n\n/**\n * This represents a message that has been submitted and is added to the pending queue when `submit` is called on the\n * ContainerRuntime. This message has either not been ack'd by the server or has not been submitted to the server yet.\n */\nexport interface IPendingMessage {\n type: \"message\";\n messageType: ContainerMessageType;\n clientSequenceNumber: number;\n referenceSequenceNumber: number;\n content: any;\n localOpMetadata: unknown;\n opMetadata: Record<string, unknown> | undefined;\n}\n\n/**\n * This represents an explicit flush call and is added to the pending queue when flush is called on the ContainerRuntime\n * to flush pending messages.\n */\nexport interface IPendingFlush {\n type: \"flush\";\n}\n\nexport type IPendingState = IPendingMessage | IPendingFlush;\n\nexport interface IPendingLocalState {\n /**\n * list of pending states, including ops and batch information\n */\n pendingStates: IPendingState[];\n}\n\nexport interface IRuntimeStateHandler{\n connected(): boolean;\n clientId(): string | undefined;\n close(error?: ICriticalContainerError): void;\n applyStashedOp: (type: ContainerMessageType, content: ISequencedDocumentMessage) => Promise<unknown>;\n flush(): void;\n reSubmit(\n type: ContainerMessageType,\n content: any,\n localOpMetadata: unknown,\n opMetadata: Record<string, unknown> | undefined): void;\n rollback(\n type: ContainerMessageType,\n content: any,\n localOpMetadata: unknown): void;\n orderSequentially(callback: () => void): void;\n}\n\n/**\n * PendingStateManager is responsible for maintaining the messages that have not been sent or have not yet been\n * acknowledged by the server. It also maintains the batch information for both automatically and manually flushed\n * batches along with the messages.\n * When the Container reconnects, it replays the pending states, which includes manual flushing\n * of messages and triggering resubmission of unacked ops.\n *\n * It verifies that all the ops are acked, are received in the right order and batch information is correct.\n */\nexport class PendingStateManager implements IDisposable {\n private readonly pendingStates = new Deque<IPendingState>();\n private readonly initialStates: Deque<IPendingState>;\n private readonly disposeOnce = new Lazy<void>(() => {\n this.initialStates.clear();\n this.pendingStates.clear();\n });\n\n // Maintains the count of messages that are currently unacked.\n private _pendingMessagesCount: number = 0;\n public get pendingMessagesCount(): number {\n return this._pendingMessagesCount;\n }\n\n // Indicates whether we are processing a batch.\n private isProcessingBatch: boolean = false;\n\n // This stores the first message in the batch that we are processing. This is used to verify that we get\n // the correct batch metadata.\n private pendingBatchBeginMessage: ISequencedDocumentMessage | undefined;\n\n private clientId: string | undefined;\n\n /**\n * Called to check if there are any pending messages in the pending state queue.\n * @returns A boolean indicating whether there are messages or not.\n */\n public hasPendingMessages(): boolean {\n return this._pendingMessagesCount !== 0 || !this.initialStates.isEmpty();\n }\n\n public getLocalState(): IPendingLocalState | undefined {\n assert(this.initialStates.isEmpty(), 0x2e9 /* \"Must call getLocalState() after applying initial states\" */);\n if (this.hasPendingMessages()) {\n return {\n pendingStates: this.pendingStates.toArray().map(\n // delete localOpMetadata since it may not be serializable\n // and will be regenerated by applyStashedOp()\n (state) => state.type === \"message\" ? { ...state, localOpMetadata: undefined } : state),\n };\n }\n }\n\n constructor(\n private readonly stateHandler: IRuntimeStateHandler,\n initialLocalState: IPendingLocalState | undefined,\n ) {\n this.initialStates = new Deque<IPendingState>(initialLocalState?.pendingStates ?? []);\n }\n\n public get disposed() { return this.disposeOnce.evaluated; }\n public readonly dispose = () => this.disposeOnce.value;\n\n /**\n * Called when a message is submitted locally. Adds the message and the associated details to the pending state\n * queue.\n * @param type - The container message type.\n * @param clientSequenceNumber - The clientSequenceNumber associated with the message.\n * @param content - The message content.\n * @param localOpMetadata - The local metadata associated with the message.\n */\n public onSubmitMessage(\n type: ContainerMessageType,\n clientSequenceNumber: number,\n referenceSequenceNumber: number,\n content: any,\n localOpMetadata: unknown,\n opMetadata: Record<string, unknown> | undefined,\n ) {\n const pendingMessage: IPendingMessage = {\n type: \"message\",\n messageType: type,\n clientSequenceNumber,\n referenceSequenceNumber,\n content,\n localOpMetadata,\n opMetadata,\n };\n\n this.pendingStates.push(pendingMessage);\n\n this._pendingMessagesCount++;\n }\n\n /**\n * Called when flush() is called on the ContainerRuntime to manually flush messages.\n */\n public onFlush() {\n // If the previous state is not a message, flush is a no-op.\n const previousState = this.pendingStates.peekBack();\n if (previousState?.type !== \"message\") {\n return;\n }\n\n // An explicit flush is interesting and is tracked only if there are messages sent in TurnBased mode.\n this.pendingStates.push({ type: \"flush\" });\n }\n\n /**\n * Applies stashed ops at their reference sequence number so they are ready to be ACKed or resubmitted\n * @param seqNum - Sequence number at which to apply ops. Will apply all ops if seqNum is undefined.\n */\n public async applyStashedOpsAt(seqNum?: number) {\n // apply stashed ops at sequence number\n while (!this.initialStates.isEmpty()) {\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const nextState = this.initialStates.peekFront()!;\n if (nextState.type === \"message\") {\n if (seqNum !== undefined) {\n if (nextState.referenceSequenceNumber > seqNum) {\n break; // nothing left to do at this sequence number\n } else if (nextState.referenceSequenceNumber < seqNum) {\n throw new Error(\"loaded from snapshot too recent to apply stashed ops\");\n }\n }\n\n // applyStashedOp will cause the DDS to behave as if it has sent the op but not actually send it\n const localOpMetadata =\n await this.stateHandler.applyStashedOp(nextState.messageType, nextState.content);\n nextState.localOpMetadata = localOpMetadata;\n }\n\n // then we push onto pendingStates which will cause PendingStateManager to resubmit when we connect\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const firstPendingState = this.initialStates.shift()!;\n this.pendingStates.push(firstPendingState);\n if (firstPendingState.type === \"message\") {\n this._pendingMessagesCount++;\n }\n }\n }\n\n /**\n * Processes a local message once its ack'd by the server. It verifies that there was no data corruption and that\n * the batch information was preserved for batch messages.\n * @param message - The message that got ack'd and needs to be processed.\n */\n public processPendingLocalMessage(message: ISequencedDocumentMessage): unknown {\n // Pre-processing part - This may be the start of a batch.\n this.maybeProcessBatchBegin(message);\n\n // Get the next state from the pending queue and verify that it is of type \"message\".\n const pendingState = this.peekNextPendingState();\n assert(pendingState.type === \"message\", 0x169 /* \"No pending message found for this remote message\" */);\n this.pendingStates.shift();\n\n // Processing part - Verify that there has been no data corruption.\n // The clientSequenceNumber of the incoming message must match that of the pending message.\n if (pendingState.clientSequenceNumber !== message.clientSequenceNumber) {\n // Close the container because this could indicate data corruption.\n const error = DataProcessingError.create(\n \"pending local message clientSequenceNumber mismatch\",\n \"unexpectedAckReceived\",\n message,\n { expectedClientSequenceNumber: pendingState.clientSequenceNumber },\n );\n\n this.stateHandler.close(error);\n return;\n }\n\n this._pendingMessagesCount--;\n assert(this._pendingMessagesCount >= 0, 0x3d6 /* positive */);\n\n // Post-processing part - If we are processing a batch then this could be the last message in the batch.\n this.maybeProcessBatchEnd(message);\n\n return pendingState.localOpMetadata;\n }\n\n /**\n * This message could be the first message in batch. If so, set batch state marking the beginning of a batch.\n * @param message - The message that is being processed.\n */\n private maybeProcessBatchBegin(message: ISequencedDocumentMessage) {\n /**\n * We are checking if the next message is the start of a batch. It can happen in the following scenarios:\n *\n * 1. The FlushMode was set to TurnBased before this message was sent.\n *\n * 2. The FlushMode was already TurnBased and a flush was called before this message was sent. This essentially\n * means that the flush marked the end of a previous batch and beginning of a new batch.\n *\n * Keep reading pending states from the queue until we encounter a message. It's possible that the FlushMode was\n * updated a bunch of times without sending any messages.\n */\n while (this.peekNextPendingState().type !== \"message\") {\n this.pendingStates.shift();\n }\n\n // This message is the first in a batch if the \"batch\" property on the metadata is set to true\n if (message.metadata?.batch) {\n // We should not already be processing a batch and there should be no pending batch begin message.\n assert(!this.isProcessingBatch && this.pendingBatchBeginMessage === undefined,\n 0x16b /* \"The pending batch state indicates we are already processing a batch\" */);\n\n // Set the pending batch state indicating we have started processing a batch.\n this.pendingBatchBeginMessage = message;\n this.isProcessingBatch = true;\n }\n }\n\n /**\n * This message could be the last message in batch. If so, clear batch state since the batch is complete.\n * @param message - The message that is being processed.\n */\n private maybeProcessBatchEnd(message: ISequencedDocumentMessage) {\n if (!this.isProcessingBatch) {\n return;\n }\n\n const nextPendingState = this.peekNextPendingState();\n if (nextPendingState.type === \"message\") {\n return;\n }\n\n // There should be a pending batch begin message.\n assert(this.pendingBatchBeginMessage !== undefined, 0x16d /* \"There is no pending batch begin message\" */);\n\n // Get the batch begin metadata from the first message in the batch.\n const batchBeginMetadata = this.pendingBatchBeginMessage.metadata?.batch;\n\n // There could be just a single message in the batch. If so, it should not have any batch metadata. If there\n // are multiple messages in the batch, verify that we got the correct batch begin and end metadata.\n if (this.pendingBatchBeginMessage === message) {\n assert(batchBeginMetadata === undefined,\n 0x16e /* \"Batch with single message should not have batch metadata\" */);\n } else {\n // Get the batch metadata from the last message in the batch.\n const batchEndMetadata = message.metadata?.batch;\n if (batchBeginMetadata !== true || batchEndMetadata !== false) {\n this.stateHandler.close(DataProcessingError.create(\n \"Pending batch inconsistency\", // Formerly known as asserts 0x16f and 0x170\n \"processPendingLocalMessage\",\n message,\n {\n runtimeVersion: pkgVersion,\n batchClientId: this.pendingBatchBeginMessage.clientId,\n clientId: this.stateHandler.clientId(),\n hasBatchStart: batchBeginMetadata === true,\n hasBatchEnd: batchEndMetadata === false,\n messageType: message.type,\n batchStartSequenceNumber: this.pendingBatchBeginMessage.clientSequenceNumber,\n pendingMessagesCount: this.pendingMessagesCount,\n nextPendingState: nextPendingState.type,\n }));\n }\n }\n\n // Clear the pending batch state now that we have processed the entire batch.\n this.pendingBatchBeginMessage = undefined;\n this.isProcessingBatch = false;\n }\n\n /**\n * Returns the next pending state from the pending state queue.\n */\n private peekNextPendingState(): IPendingState {\n const nextPendingState = this.pendingStates.peekFront();\n assert(!!nextPendingState, 0x171 /* \"No pending state found for the remote message\" */);\n return nextPendingState;\n }\n\n /**\n * Called when the Container's connection state changes. If the Container gets connected, it replays all the pending\n * states in its queue. This includes triggering resubmission of unacked ops.\n */\n public replayPendingStates() {\n assert(this.stateHandler.connected(), 0x172 /* \"The connection state is not consistent with the runtime\" */);\n\n // This assert suggests we are about to send same ops twice, which will result in data loss.\n assert(this.clientId !== this.stateHandler.clientId(),\n 0x173 /* \"replayPendingStates called twice for same clientId!\" */);\n this.clientId = this.stateHandler.clientId();\n\n assert(this.initialStates.isEmpty(), 0x174 /* \"initial states should be empty before replaying pending\" */);\n\n let pendingStatesCount = this.pendingStates.length;\n if (pendingStatesCount === 0) {\n return;\n }\n\n // Reset the pending message count because all these messages will be removed from the queue.\n this._pendingMessagesCount = 0;\n\n const messageBatchQueue = new Deque<IPendingMessage>();\n\n // Process exactly `pendingStatesCount` items in the queue as it represents the number of states that were\n // pending when we connected. This is important because the `reSubmitFn` might add more items in the queue\n // which must not be replayed.\n while (pendingStatesCount > 0) {\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const pendingState = this.pendingStates.shift()!;\n switch (pendingState.type) {\n case \"message\":\n assert(pendingState.opMetadata?.batch !== false || messageBatchQueue.length > 0,\n 0x41b /* We cannot process batches in chunks */);\n /**\n * We want to ensure grouped messages get processed in a batch.\n * Note: It is not possible for the PendingStateManager to receive a partially acked batch. It will\n * either receive the whole batch ack or nothing at all.\n */\n if (messageBatchQueue.length > 0 || pendingState.opMetadata?.batch) {\n messageBatchQueue.enqueue(pendingState);\n } else {\n this.stateHandler.reSubmit(\n pendingState.messageType,\n pendingState.content,\n pendingState.localOpMetadata,\n pendingState.opMetadata);\n }\n break;\n case \"flush\":\n /**\n * A \"flush\" call can indicate the end of a batch.\n * We can't rely on the \"batch\" property in the message metadata as it gets\n * updated elsewhere and it is not the same object instance that gets updated.\n */\n if (messageBatchQueue.length > 0) {\n this.stateHandler.orderSequentially(() => {\n while (messageBatchQueue.length > 0) {\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const message = messageBatchQueue.dequeue()!;\n this.stateHandler.reSubmit(\n message.messageType,\n message.content,\n message.localOpMetadata,\n message.opMetadata);\n }\n });\n }\n assert(messageBatchQueue.length === 0, 0x41c /* cannot flush in the middle of a batch */);\n this.stateHandler.flush();\n break;\n default:\n break;\n }\n pendingStatesCount--;\n }\n\n // There are some cases where ops are stashed but not flushed. We need to ensure they are resubmitted\n while (messageBatchQueue.length > 0) {\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const message = messageBatchQueue.dequeue()!;\n this.stateHandler.reSubmit(\n message.messageType,\n message.content,\n message.localOpMetadata,\n message.opMetadata);\n }\n }\n}\n"]}