@fluidframework/container-loader 2.0.0-dev.2.3.0.115467 → 2.0.0-dev.4.1.0.148229

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 (168) hide show
  1. package/.eslintrc.js +18 -21
  2. package/.mocharc.js +2 -2
  3. package/README.md +65 -44
  4. package/api-extractor.json +2 -2
  5. package/closeAndGetPendingLocalState.md +51 -0
  6. package/dist/audience.d.ts +0 -1
  7. package/dist/audience.d.ts.map +1 -1
  8. package/dist/audience.js.map +1 -1
  9. package/dist/catchUpMonitor.d.ts.map +1 -1
  10. package/dist/catchUpMonitor.js.map +1 -1
  11. package/dist/collabWindowTracker.d.ts.map +1 -1
  12. package/dist/collabWindowTracker.js.map +1 -1
  13. package/dist/connectionManager.d.ts +5 -5
  14. package/dist/connectionManager.d.ts.map +1 -1
  15. package/dist/connectionManager.js +107 -44
  16. package/dist/connectionManager.js.map +1 -1
  17. package/dist/connectionState.d.ts.map +1 -1
  18. package/dist/connectionState.js.map +1 -1
  19. package/dist/connectionStateHandler.d.ts +7 -7
  20. package/dist/connectionStateHandler.d.ts.map +1 -1
  21. package/dist/connectionStateHandler.js +50 -21
  22. package/dist/connectionStateHandler.js.map +1 -1
  23. package/dist/container.d.ts +64 -5
  24. package/dist/container.d.ts.map +1 -1
  25. package/dist/container.js +329 -137
  26. package/dist/container.js.map +1 -1
  27. package/dist/containerContext.d.ts +19 -8
  28. package/dist/containerContext.d.ts.map +1 -1
  29. package/dist/containerContext.js +58 -14
  30. package/dist/containerContext.js.map +1 -1
  31. package/dist/containerStorageAdapter.d.ts +41 -2
  32. package/dist/containerStorageAdapter.d.ts.map +1 -1
  33. package/dist/containerStorageAdapter.js +88 -14
  34. package/dist/containerStorageAdapter.js.map +1 -1
  35. package/dist/contracts.d.ts +3 -3
  36. package/dist/contracts.d.ts.map +1 -1
  37. package/dist/contracts.js.map +1 -1
  38. package/dist/deltaManager.d.ts +21 -8
  39. package/dist/deltaManager.d.ts.map +1 -1
  40. package/dist/deltaManager.js +112 -37
  41. package/dist/deltaManager.js.map +1 -1
  42. package/dist/deltaManagerProxy.d.ts +10 -22
  43. package/dist/deltaManagerProxy.d.ts.map +1 -1
  44. package/dist/deltaManagerProxy.js +14 -50
  45. package/dist/deltaManagerProxy.js.map +1 -1
  46. package/dist/deltaQueue.d.ts.map +1 -1
  47. package/dist/deltaQueue.js +4 -2
  48. package/dist/deltaQueue.js.map +1 -1
  49. package/dist/index.d.ts +4 -3
  50. package/dist/index.d.ts.map +1 -1
  51. package/dist/index.js +1 -3
  52. package/dist/index.js.map +1 -1
  53. package/dist/loader.d.ts +13 -4
  54. package/dist/loader.d.ts.map +1 -1
  55. package/dist/loader.js +38 -24
  56. package/dist/loader.js.map +1 -1
  57. package/dist/packageVersion.d.ts +1 -1
  58. package/dist/packageVersion.js +1 -1
  59. package/dist/packageVersion.js.map +1 -1
  60. package/dist/protocol.d.ts.map +1 -1
  61. package/dist/protocol.js +2 -1
  62. package/dist/protocol.js.map +1 -1
  63. package/dist/protocolTreeDocumentStorageService.d.ts +6 -2
  64. package/dist/protocolTreeDocumentStorageService.d.ts.map +1 -1
  65. package/dist/protocolTreeDocumentStorageService.js +7 -4
  66. package/dist/protocolTreeDocumentStorageService.js.map +1 -1
  67. package/dist/quorum.d.ts.map +1 -1
  68. package/dist/quorum.js.map +1 -1
  69. package/dist/retriableDocumentStorageService.d.ts.map +1 -1
  70. package/dist/retriableDocumentStorageService.js +6 -2
  71. package/dist/retriableDocumentStorageService.js.map +1 -1
  72. package/dist/utils.d.ts.map +1 -1
  73. package/dist/utils.js +8 -5
  74. package/dist/utils.js.map +1 -1
  75. package/lib/audience.d.ts +0 -1
  76. package/lib/audience.d.ts.map +1 -1
  77. package/lib/audience.js.map +1 -1
  78. package/lib/catchUpMonitor.d.ts.map +1 -1
  79. package/lib/catchUpMonitor.js.map +1 -1
  80. package/lib/collabWindowTracker.d.ts.map +1 -1
  81. package/lib/collabWindowTracker.js.map +1 -1
  82. package/lib/connectionManager.d.ts +5 -5
  83. package/lib/connectionManager.d.ts.map +1 -1
  84. package/lib/connectionManager.js +110 -47
  85. package/lib/connectionManager.js.map +1 -1
  86. package/lib/connectionState.d.ts.map +1 -1
  87. package/lib/connectionState.js.map +1 -1
  88. package/lib/connectionStateHandler.d.ts +7 -7
  89. package/lib/connectionStateHandler.d.ts.map +1 -1
  90. package/lib/connectionStateHandler.js +50 -21
  91. package/lib/connectionStateHandler.js.map +1 -1
  92. package/lib/container.d.ts +64 -5
  93. package/lib/container.d.ts.map +1 -1
  94. package/lib/container.js +336 -144
  95. package/lib/container.js.map +1 -1
  96. package/lib/containerContext.d.ts +19 -8
  97. package/lib/containerContext.d.ts.map +1 -1
  98. package/lib/containerContext.js +59 -15
  99. package/lib/containerContext.js.map +1 -1
  100. package/lib/containerStorageAdapter.d.ts +41 -2
  101. package/lib/containerStorageAdapter.d.ts.map +1 -1
  102. package/lib/containerStorageAdapter.js +86 -14
  103. package/lib/containerStorageAdapter.js.map +1 -1
  104. package/lib/contracts.d.ts +3 -3
  105. package/lib/contracts.d.ts.map +1 -1
  106. package/lib/contracts.js.map +1 -1
  107. package/lib/deltaManager.d.ts +21 -8
  108. package/lib/deltaManager.d.ts.map +1 -1
  109. package/lib/deltaManager.js +114 -39
  110. package/lib/deltaManager.js.map +1 -1
  111. package/lib/deltaManagerProxy.d.ts +10 -22
  112. package/lib/deltaManagerProxy.d.ts.map +1 -1
  113. package/lib/deltaManagerProxy.js +14 -50
  114. package/lib/deltaManagerProxy.js.map +1 -1
  115. package/lib/deltaQueue.d.ts.map +1 -1
  116. package/lib/deltaQueue.js +4 -2
  117. package/lib/deltaQueue.js.map +1 -1
  118. package/lib/index.d.ts +4 -3
  119. package/lib/index.d.ts.map +1 -1
  120. package/lib/index.js +2 -2
  121. package/lib/index.js.map +1 -1
  122. package/lib/loader.d.ts +13 -4
  123. package/lib/loader.d.ts.map +1 -1
  124. package/lib/loader.js +37 -24
  125. package/lib/loader.js.map +1 -1
  126. package/lib/packageVersion.d.ts +1 -1
  127. package/lib/packageVersion.js +1 -1
  128. package/lib/packageVersion.js.map +1 -1
  129. package/lib/protocol.d.ts.map +1 -1
  130. package/lib/protocol.js +2 -1
  131. package/lib/protocol.js.map +1 -1
  132. package/lib/protocolTreeDocumentStorageService.d.ts +6 -2
  133. package/lib/protocolTreeDocumentStorageService.d.ts.map +1 -1
  134. package/lib/protocolTreeDocumentStorageService.js +7 -4
  135. package/lib/protocolTreeDocumentStorageService.js.map +1 -1
  136. package/lib/quorum.d.ts.map +1 -1
  137. package/lib/quorum.js.map +1 -1
  138. package/lib/retriableDocumentStorageService.d.ts.map +1 -1
  139. package/lib/retriableDocumentStorageService.js +6 -2
  140. package/lib/retriableDocumentStorageService.js.map +1 -1
  141. package/lib/utils.d.ts.map +1 -1
  142. package/lib/utils.js +8 -5
  143. package/lib/utils.js.map +1 -1
  144. package/package.json +67 -56
  145. package/prettier.config.cjs +1 -1
  146. package/src/audience.ts +51 -46
  147. package/src/catchUpMonitor.ts +39 -37
  148. package/src/collabWindowTracker.ts +75 -70
  149. package/src/connectionManager.ts +1040 -941
  150. package/src/connectionState.ts +19 -19
  151. package/src/connectionStateHandler.ts +557 -463
  152. package/src/container.ts +2147 -1784
  153. package/src/containerContext.ts +417 -345
  154. package/src/containerStorageAdapter.ts +268 -154
  155. package/src/contracts.ts +155 -153
  156. package/src/deltaManager.ts +1074 -945
  157. package/src/deltaManagerProxy.ts +88 -137
  158. package/src/deltaQueue.ts +155 -151
  159. package/src/index.ts +13 -17
  160. package/src/loader.ts +434 -427
  161. package/src/packageVersion.ts +1 -1
  162. package/src/protocol.ts +93 -87
  163. package/src/protocolTreeDocumentStorageService.ts +34 -34
  164. package/src/quorum.ts +34 -34
  165. package/src/retriableDocumentStorageService.ts +118 -102
  166. package/src/utils.ts +93 -83
  167. package/tsconfig.esnext.json +6 -6
  168. package/tsconfig.json +8 -12
@@ -4,155 +4,106 @@
4
4
  */
5
5
 
6
6
  import {
7
- IDeltaManager,
8
- IDeltaManagerEvents,
9
- IDeltaQueue,
10
- IDeltaSender,
11
- IDeltaQueueEvents,
12
- ReadOnlyInfo,
7
+ IDeltaManager,
8
+ IDeltaQueue,
9
+ IDeltaQueueEvents,
13
10
  } from "@fluidframework/container-definitions";
14
11
  import { EventForwarder } from "@fluidframework/common-utils";
15
12
  import {
16
- IClientConfiguration,
17
- IClientDetails,
18
- IDocumentMessage,
19
- ISequencedDocumentMessage,
20
- ISignalMessage,
13
+ IDocumentMessage,
14
+ ISequencedDocumentMessage,
15
+ ISignalMessage,
21
16
  } from "@fluidframework/protocol-definitions";
17
+ import { DeltaManagerProxyBase } from "@fluidframework/container-utils";
22
18
 
23
19
  /**
24
20
  * Proxy to the real IDeltaQueue - used to restrict access
25
21
  */
26
- export class DeltaQueueProxy<T> extends EventForwarder<IDeltaQueueEvents<T>> implements IDeltaQueue<T> {
27
- public get paused(): boolean {
28
- return this.queue.paused;
29
- }
30
-
31
- public get length(): number {
32
- return this.queue.length;
33
- }
34
-
35
- public get idle(): boolean {
36
- return this.queue.idle;
37
- }
38
-
39
- constructor(private readonly queue: IDeltaQueue<T>) {
40
- super(queue);
41
- }
42
-
43
- public peek(): T | undefined {
44
- return this.queue.peek();
45
- }
46
-
47
- public toArray(): T[] {
48
- return this.queue.toArray();
49
- }
50
-
51
- // back-compat: usage removed in 0.33, remove in future versions
52
- public async systemPause(): Promise<void> {
53
- return this.pause();
54
- }
55
-
56
- public async pause(): Promise<void> {
57
- return this.queue.pause();
58
- }
59
-
60
- // back-compat: usage removed in 0.33, remove in future versions
61
- public async systemResume(): Promise<void> {
62
- return this.resume();
63
- }
64
-
65
- public async resume(): Promise<void> {
66
- this.queue.resume();
67
- }
68
-
69
- public async waitTillProcessingDone() {
70
- return this.queue.waitTillProcessingDone();
71
- }
22
+ export class DeltaQueueProxy<T>
23
+ extends EventForwarder<IDeltaQueueEvents<T>>
24
+ implements IDeltaQueue<T>
25
+ {
26
+ public get paused(): boolean {
27
+ return this.queue.paused;
28
+ }
29
+
30
+ public get length(): number {
31
+ return this.queue.length;
32
+ }
33
+
34
+ public get idle(): boolean {
35
+ return this.queue.idle;
36
+ }
37
+
38
+ constructor(private readonly queue: IDeltaQueue<T>) {
39
+ super(queue);
40
+ }
41
+
42
+ public peek(): T | undefined {
43
+ return this.queue.peek();
44
+ }
45
+
46
+ public toArray(): T[] {
47
+ return this.queue.toArray();
48
+ }
49
+
50
+ // back-compat: usage removed in 0.33, remove in future versions
51
+ public async systemPause(): Promise<void> {
52
+ return this.pause();
53
+ }
54
+
55
+ public async pause(): Promise<void> {
56
+ return this.queue.pause();
57
+ }
58
+
59
+ // back-compat: usage removed in 0.33, remove in future versions
60
+ public async systemResume(): Promise<void> {
61
+ return this.resume();
62
+ }
63
+
64
+ public async resume(): Promise<void> {
65
+ this.queue.resume();
66
+ }
67
+
68
+ public async waitTillProcessingDone() {
69
+ return this.queue.waitTillProcessingDone();
70
+ }
72
71
  }
73
72
 
74
73
  /**
75
74
  * Proxy to the real IDeltaManager - used to restrict access
76
75
  */
77
76
  export class DeltaManagerProxy
78
- extends EventForwarder<IDeltaManagerEvents>
79
- implements IDeltaManager<ISequencedDocumentMessage, IDocumentMessage> {
80
- public readonly inbound: IDeltaQueue<ISequencedDocumentMessage>;
81
- public readonly outbound: IDeltaQueue<IDocumentMessage[]>;
82
- public readonly inboundSignal: IDeltaQueue<ISignalMessage>;
83
-
84
- public get IDeltaSender(): IDeltaSender {
85
- return this;
86
- }
87
-
88
- public get minimumSequenceNumber(): number {
89
- return this.deltaManager.minimumSequenceNumber;
90
- }
91
-
92
- public get lastSequenceNumber(): number {
93
- return this.deltaManager.lastSequenceNumber;
94
- }
95
-
96
- public get lastMessage() {
97
- return this.deltaManager.lastMessage;
98
- }
99
-
100
- public get lastKnownSeqNumber() {
101
- return this.deltaManager.lastKnownSeqNumber;
102
- }
103
-
104
- public get initialSequenceNumber(): number {
105
- return this.deltaManager.initialSequenceNumber;
106
- }
107
-
108
- public get hasCheckpointSequenceNumber() {
109
- return this.deltaManager.hasCheckpointSequenceNumber;
110
- }
111
-
112
- public get clientDetails(): IClientDetails {
113
- return this.deltaManager.clientDetails;
114
- }
115
-
116
- public get version(): string {
117
- return this.deltaManager.version;
118
- }
119
-
120
- public get maxMessageSize(): number {
121
- return this.deltaManager.maxMessageSize;
122
- }
123
-
124
- public get serviceConfiguration(): IClientConfiguration | undefined {
125
- return this.deltaManager.serviceConfiguration;
126
- }
127
-
128
- public get active(): boolean {
129
- return this.deltaManager.active;
130
- }
131
-
132
- public get readOnlyInfo(): ReadOnlyInfo {
133
- return this.deltaManager.readOnlyInfo;
134
- }
135
-
136
- constructor(private readonly deltaManager: IDeltaManager<ISequencedDocumentMessage, IDocumentMessage>) {
137
- super(deltaManager);
138
-
139
- this.inbound = new DeltaQueueProxy(deltaManager.inbound);
140
- this.outbound = new DeltaQueueProxy(deltaManager.outbound);
141
- this.inboundSignal = new DeltaQueueProxy(deltaManager.inboundSignal);
142
- }
143
-
144
- public dispose(): void {
145
- this.inbound.dispose();
146
- this.outbound.dispose();
147
- this.inboundSignal.dispose();
148
- super.dispose();
149
- }
150
-
151
- public submitSignal(content: any): void {
152
- return this.deltaManager.submitSignal(content);
153
- }
154
-
155
- public flush(): void {
156
- return this.deltaManager.flush();
157
- }
77
+ extends DeltaManagerProxyBase
78
+ implements IDeltaManager<ISequencedDocumentMessage, IDocumentMessage>
79
+ {
80
+ public get inbound(): IDeltaQueue<ISequencedDocumentMessage> {
81
+ return this._inbound;
82
+ }
83
+ private readonly _inbound: IDeltaQueue<ISequencedDocumentMessage>;
84
+
85
+ public get outbound(): IDeltaQueue<IDocumentMessage[]> {
86
+ return this._outbound;
87
+ }
88
+ private readonly _outbound: IDeltaQueue<IDocumentMessage[]>;
89
+
90
+ public get inboundSignal(): IDeltaQueue<ISignalMessage> {
91
+ return this._inboundSignal;
92
+ }
93
+ private readonly _inboundSignal: IDeltaQueue<ISignalMessage>;
94
+
95
+ constructor(deltaManager: IDeltaManager<ISequencedDocumentMessage, IDocumentMessage>) {
96
+ super(deltaManager);
97
+
98
+ this._inbound = new DeltaQueueProxy(deltaManager.inbound);
99
+ this._outbound = new DeltaQueueProxy(deltaManager.outbound);
100
+ this._inboundSignal = new DeltaQueueProxy(deltaManager.inboundSignal);
101
+ }
102
+
103
+ public dispose(): void {
104
+ this._inbound.dispose();
105
+ this._outbound.dispose();
106
+ this._inboundSignal.dispose();
107
+ super.dispose();
108
+ }
158
109
  }
package/src/deltaQueue.ts CHANGED
@@ -8,158 +8,162 @@ import { assert, performance, TypedEventEmitter } from "@fluidframework/common-u
8
8
  import Deque from "double-ended-queue";
9
9
 
10
10
  export interface IDeltaQueueWriter<T> {
11
- push(task: T): void;
12
- clear(): void;
11
+ push(task: T): void;
12
+ clear(): void;
13
13
  }
14
14
 
15
15
  export class DeltaQueue<T>
16
- extends TypedEventEmitter<IDeltaQueueEvents<T>>
17
- implements IDeltaQueue<T>, IDeltaQueueWriter<T> {
18
- private isDisposed: boolean = false;
19
- private readonly q = new Deque<T>();
20
-
21
- /**
22
- * Tracks the number of pause requests for the queue
23
- * The DeltaQueue is create initially paused.
24
- */
25
- private pauseCount = 1;
26
-
27
- private error: any | undefined;
28
-
29
- /**
30
- * When processing is ongoing, holds a deferred that will resolve once processing stops.
31
- * Undefined when not processing.
32
- */
33
- private processingPromise: Promise<{ count: number; duration: number; }> | undefined;
34
-
35
- public get disposed(): boolean {
36
- return this.isDisposed;
37
- }
38
-
39
- /**
40
- * @returns True if the queue is paused, false if not.
41
- */
42
- public get paused(): boolean {
43
- return this.pauseCount !== 0;
44
- }
45
-
46
- public get length(): number {
47
- return this.q.length;
48
- }
49
-
50
- public get idle(): boolean {
51
- return this.processingPromise === undefined && this.q.length === 0;
52
- }
53
-
54
- public async waitTillProcessingDone() {
55
- return this.processingPromise ?? { count: 0, duration: 0 };
56
- }
57
-
58
- /**
59
- * @param worker - A callback to process a delta.
60
- * @param logger - For logging telemetry.
61
- */
62
- constructor(
63
- private readonly worker: (delta: T) => void,
64
- ) {
65
- super();
66
- }
67
-
68
- public dispose() {
69
- throw new Error("Not implemented.");
70
- this.isDisposed = true;
71
- }
72
-
73
- public clear(): void {
74
- this.q.clear();
75
- }
76
-
77
- public peek(): T | undefined {
78
- return this.q.peekFront();
79
- }
80
-
81
- public toArray(): T[] {
82
- return this.q.toArray();
83
- }
84
-
85
- public push(task: T) {
86
- try {
87
- this.q.push(task);
88
- this.emit("push", task);
89
- this.ensureProcessing();
90
- } catch (error) {
91
- this.emit("error", error);
92
- }
93
- }
94
-
95
- public async pause(): Promise<void> {
96
- this.pauseCount++;
97
- // If called from within the processing loop, we are in the middle of processing an op. Return a promise
98
- // that will resolve when processing has actually stopped.
99
- await this.waitTillProcessingDone();
100
- }
101
-
102
- public resume(): void {
103
- assert(this.pauseCount > 0, 0x0f4 /* "Nonzero pause-count on resume()" */);
104
- this.pauseCount--;
105
- this.ensureProcessing();
106
- }
107
-
108
- /**
109
- * There are several actions that may need to kick off delta processing, so we want to guard against
110
- * accidental reentrancy. ensureProcessing can be called safely to start the processing loop if it is
111
- * not already started.
112
- */
113
- private ensureProcessing() {
114
- if (this.anythingToProcess() && this.processingPromise === undefined) {
115
- // Use a resolved promise to start the processing on a separate stack.
116
- this.processingPromise = Promise.resolve().then(() => {
117
- assert(this.processingPromise !== undefined, 0x37f /* reentrancy? */);
118
- const result = this.processDeltas();
119
- assert(this.processingPromise !== undefined, 0x380 /* reentrancy? */);
120
- // WARNING: Do not move next line to .finally() clause!
121
- // It runs async and creates a race condition where incoming ensureProcessing() call observes
122
- // from previous run while previous run is over (but finally clause was not scheduled yet)
123
- this.processingPromise = undefined;
124
- return result;
125
- }).catch((error) => {
126
- this.error = error;
127
- this.processingPromise = undefined;
128
- this.emit("error", error);
129
- return { count: 0, duration: 0 };
130
- });
131
- assert(this.processingPromise !== undefined, 0x381 /* processDeltas() should run async */);
132
- }
133
- }
134
-
135
- private anythingToProcess() {
136
- return this.q.length !== 0 && !this.paused && this.error === undefined;
137
- }
138
-
139
- /**
140
- * Executes the delta processing loop until a stop condition is reached.
141
- */
142
- private processDeltas() {
143
- const start = performance.now();
144
- let count = 0;
145
-
146
- // For grouping to work we must process all local messages immediately and in the single turn.
147
- // So loop over them until no messages to process, we have become paused, or hit an error.
148
- while (this.anythingToProcess()) {
149
- // Get the next message in the queue
150
- const next = this.q.shift();
151
- count++;
152
- // Process the message.
153
- // We know next is defined since we did a length check just prior to shifting.
154
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
155
- this.worker(next!);
156
- this.emit("op", next);
157
- }
158
-
159
- const duration = performance.now() - start;
160
- if (this.q.length === 0) {
161
- this.emit("idle", count, duration);
162
- }
163
- return { count, duration };
164
- }
16
+ extends TypedEventEmitter<IDeltaQueueEvents<T>>
17
+ implements IDeltaQueue<T>, IDeltaQueueWriter<T>
18
+ {
19
+ private isDisposed: boolean = false;
20
+ private readonly q = new Deque<T>();
21
+
22
+ /**
23
+ * Tracks the number of pause requests for the queue
24
+ * The DeltaQueue is create initially paused.
25
+ */
26
+ private pauseCount = 1;
27
+
28
+ private error: any | undefined;
29
+
30
+ /**
31
+ * When processing is ongoing, holds a deferred that will resolve once processing stops.
32
+ * Undefined when not processing.
33
+ */
34
+ private processingPromise: Promise<{ count: number; duration: number }> | undefined;
35
+
36
+ public get disposed(): boolean {
37
+ return this.isDisposed;
38
+ }
39
+
40
+ /**
41
+ * @returns True if the queue is paused, false if not.
42
+ */
43
+ public get paused(): boolean {
44
+ return this.pauseCount !== 0;
45
+ }
46
+
47
+ public get length(): number {
48
+ return this.q.length;
49
+ }
50
+
51
+ public get idle(): boolean {
52
+ return this.processingPromise === undefined && this.q.length === 0;
53
+ }
54
+
55
+ public async waitTillProcessingDone() {
56
+ return this.processingPromise ?? { count: 0, duration: 0 };
57
+ }
58
+
59
+ /**
60
+ * @param worker - A callback to process a delta.
61
+ * @param logger - For logging telemetry.
62
+ */
63
+ constructor(private readonly worker: (delta: T) => void) {
64
+ super();
65
+ }
66
+
67
+ public dispose() {
68
+ throw new Error("Not implemented.");
69
+ this.isDisposed = true;
70
+ }
71
+
72
+ public clear(): void {
73
+ this.q.clear();
74
+ }
75
+
76
+ public peek(): T | undefined {
77
+ return this.q.peekFront();
78
+ }
79
+
80
+ public toArray(): T[] {
81
+ return this.q.toArray();
82
+ }
83
+
84
+ public push(task: T) {
85
+ try {
86
+ this.q.push(task);
87
+ this.emit("push", task);
88
+ this.ensureProcessing();
89
+ } catch (error) {
90
+ this.emit("error", error);
91
+ }
92
+ }
93
+
94
+ public async pause(): Promise<void> {
95
+ this.pauseCount++;
96
+ // If called from within the processing loop, we are in the middle of processing an op. Return a promise
97
+ // that will resolve when processing has actually stopped.
98
+ await this.waitTillProcessingDone();
99
+ }
100
+
101
+ public resume(): void {
102
+ assert(this.pauseCount > 0, 0x0f4 /* "Nonzero pause-count on resume()" */);
103
+ this.pauseCount--;
104
+ this.ensureProcessing();
105
+ }
106
+
107
+ /**
108
+ * There are several actions that may need to kick off delta processing, so we want to guard against
109
+ * accidental reentrancy. ensureProcessing can be called safely to start the processing loop if it is
110
+ * not already started.
111
+ */
112
+ private ensureProcessing() {
113
+ if (this.anythingToProcess() && this.processingPromise === undefined) {
114
+ // Use a resolved promise to start the processing on a separate stack.
115
+ this.processingPromise = Promise.resolve()
116
+ .then(() => {
117
+ assert(this.processingPromise !== undefined, 0x37f /* reentrancy? */);
118
+ const result = this.processDeltas();
119
+ assert(this.processingPromise !== undefined, 0x380 /* reentrancy? */);
120
+ // WARNING: Do not move next line to .finally() clause!
121
+ // It runs async and creates a race condition where incoming ensureProcessing() call observes
122
+ // from previous run while previous run is over (but finally clause was not scheduled yet)
123
+ this.processingPromise = undefined;
124
+ return result;
125
+ })
126
+ .catch((error) => {
127
+ this.error = error;
128
+ this.processingPromise = undefined;
129
+ this.emit("error", error);
130
+ return { count: 0, duration: 0 };
131
+ });
132
+ assert(
133
+ this.processingPromise !== undefined,
134
+ 0x381 /* processDeltas() should run async */,
135
+ );
136
+ }
137
+ }
138
+
139
+ private anythingToProcess() {
140
+ return this.q.length !== 0 && !this.paused && this.error === undefined;
141
+ }
142
+
143
+ /**
144
+ * Executes the delta processing loop until a stop condition is reached.
145
+ */
146
+ private processDeltas() {
147
+ const start = performance.now();
148
+ let count = 0;
149
+
150
+ // For grouping to work we must process all local messages immediately and in the single turn.
151
+ // So loop over them until no messages to process, we have become paused, or hit an error.
152
+ while (this.anythingToProcess()) {
153
+ // Get the next message in the queue
154
+ const next = this.q.shift();
155
+ count++;
156
+ // Process the message.
157
+ // We know next is defined since we did a length check just prior to shifting.
158
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
159
+ this.worker(next!);
160
+ this.emit("op", next);
161
+ }
162
+
163
+ const duration = performance.now() - start;
164
+ if (this.q.length === 0) {
165
+ this.emit("idle", count, duration);
166
+ }
167
+ return { count, duration };
168
+ }
165
169
  }
package/src/index.ts CHANGED
@@ -5,23 +5,19 @@
5
5
 
6
6
  export { ConnectionState } from "./connectionState";
7
7
  export {
8
- Container,
9
- IContainerLoadOptions,
10
- IContainerConfig,
11
- IPendingContainerState,
12
- waitContainerToCatchUp,
8
+ IContainerConfig,
9
+ IContainerLoadOptions,
10
+ IPendingContainerState,
11
+ waitContainerToCatchUp,
13
12
  } from "./container";
13
+ export { ISerializableBlobContents } from "./containerStorageAdapter";
14
14
  export {
15
- ICodeDetailsLoader,
16
- IDetachedBlobStorage,
17
- IFluidModuleWithDetails,
18
- ILoaderOptions,
19
- ILoaderProps,
20
- ILoaderServices,
21
- Loader,
22
- RelativeLoader,
15
+ ICodeDetailsLoader,
16
+ IDetachedBlobStorage,
17
+ IFluidModuleWithDetails,
18
+ ILoaderOptions,
19
+ ILoaderProps,
20
+ ILoaderServices,
21
+ Loader,
23
22
  } from "./loader";
24
- export {
25
- IProtocolHandler,
26
- ProtocolHandlerBuilder,
27
- } from "./protocol";
23
+ export { IProtocolHandler, ProtocolHandlerBuilder } from "./protocol";