@fluidframework/container-runtime 2.33.0-333010 → 2.33.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.
- package/CHANGELOG.md +4 -0
- package/api-report/container-runtime.legacy.alpha.api.md +71 -67
- package/container-runtime.test-files.tar +0 -0
- package/dist/blobManager/blobManager.d.ts +7 -4
- package/dist/blobManager/blobManager.d.ts.map +1 -1
- package/dist/blobManager/blobManager.js +38 -12
- package/dist/blobManager/blobManager.js.map +1 -1
- package/dist/channelCollection.d.ts +4 -0
- package/dist/channelCollection.d.ts.map +1 -1
- package/dist/channelCollection.js +24 -0
- package/dist/channelCollection.js.map +1 -1
- package/dist/compatUtils.d.ts +74 -0
- package/dist/compatUtils.d.ts.map +1 -0
- package/dist/compatUtils.js +151 -0
- package/dist/compatUtils.js.map +1 -0
- package/dist/compressionDefinitions.d.ts +39 -0
- package/dist/compressionDefinitions.d.ts.map +1 -0
- package/dist/compressionDefinitions.js +30 -0
- package/dist/compressionDefinitions.js.map +1 -0
- package/dist/containerRuntime.d.ts +78 -52
- package/dist/containerRuntime.d.ts.map +1 -1
- package/dist/containerRuntime.js +141 -54
- package/dist/containerRuntime.js.map +1 -1
- package/dist/dataStoreContext.d.ts +3 -0
- package/dist/dataStoreContext.d.ts.map +1 -1
- package/dist/dataStoreContext.js +122 -66
- package/dist/dataStoreContext.js.map +1 -1
- package/dist/deltaManagerProxies.d.ts +55 -12
- package/dist/deltaManagerProxies.d.ts.map +1 -1
- package/dist/deltaManagerProxies.js +63 -55
- package/dist/deltaManagerProxies.js.map +1 -1
- package/dist/gc/gcDefinitions.d.ts +2 -0
- package/dist/gc/gcDefinitions.d.ts.map +1 -1
- package/dist/gc/gcDefinitions.js.map +1 -1
- package/dist/index.d.ts +4 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -2
- package/dist/index.js.map +1 -1
- package/dist/legacy.d.ts +1 -0
- package/dist/opLifecycle/batchManager.d.ts +1 -1
- package/dist/opLifecycle/batchManager.d.ts.map +1 -1
- package/dist/opLifecycle/batchManager.js +4 -1
- package/dist/opLifecycle/batchManager.js.map +1 -1
- package/dist/opLifecycle/definitions.d.ts +35 -4
- package/dist/opLifecycle/definitions.d.ts.map +1 -1
- package/dist/opLifecycle/definitions.js.map +1 -1
- package/dist/opLifecycle/index.d.ts +1 -1
- package/dist/opLifecycle/index.d.ts.map +1 -1
- package/dist/opLifecycle/index.js.map +1 -1
- package/dist/opLifecycle/opCompressor.js +2 -2
- package/dist/opLifecycle/opCompressor.js.map +1 -1
- package/dist/opLifecycle/opDecompressor.js +3 -3
- package/dist/opLifecycle/opDecompressor.js.map +1 -1
- package/dist/opLifecycle/opGroupingManager.d.ts +2 -2
- package/dist/opLifecycle/opGroupingManager.d.ts.map +1 -1
- package/dist/opLifecycle/opGroupingManager.js +1 -2
- package/dist/opLifecycle/opGroupingManager.js.map +1 -1
- package/dist/opLifecycle/opSerialization.d.ts +3 -1
- package/dist/opLifecycle/opSerialization.d.ts.map +1 -1
- package/dist/opLifecycle/opSerialization.js +4 -2
- package/dist/opLifecycle/opSerialization.js.map +1 -1
- package/dist/opLifecycle/outbox.d.ts +6 -3
- package/dist/opLifecycle/outbox.d.ts.map +1 -1
- package/dist/opLifecycle/outbox.js +46 -20
- package/dist/opLifecycle/outbox.js.map +1 -1
- package/dist/packageVersion.d.ts +1 -1
- package/dist/packageVersion.d.ts.map +1 -1
- package/dist/packageVersion.js +1 -1
- package/dist/packageVersion.js.map +1 -1
- package/dist/pendingStateManager.d.ts +36 -7
- package/dist/pendingStateManager.d.ts.map +1 -1
- package/dist/pendingStateManager.js +83 -16
- package/dist/pendingStateManager.js.map +1 -1
- package/dist/runtimeLayerCompatState.d.ts.map +1 -1
- package/dist/runtimeLayerCompatState.js +1 -1
- package/dist/runtimeLayerCompatState.js.map +1 -1
- package/dist/summary/documentSchema.d.ts +1 -0
- package/dist/summary/documentSchema.d.ts.map +1 -1
- package/dist/summary/documentSchema.js +2 -0
- package/dist/summary/documentSchema.js.map +1 -1
- package/lib/blobManager/blobManager.d.ts +7 -4
- package/lib/blobManager/blobManager.d.ts.map +1 -1
- package/lib/blobManager/blobManager.js +38 -12
- package/lib/blobManager/blobManager.js.map +1 -1
- package/lib/channelCollection.d.ts +4 -0
- package/lib/channelCollection.d.ts.map +1 -1
- package/lib/channelCollection.js +24 -0
- package/lib/channelCollection.js.map +1 -1
- package/lib/compatUtils.d.ts +74 -0
- package/lib/compatUtils.d.ts.map +1 -0
- package/lib/compatUtils.js +142 -0
- package/lib/compatUtils.js.map +1 -0
- package/lib/compressionDefinitions.d.ts +39 -0
- package/lib/compressionDefinitions.d.ts.map +1 -0
- package/lib/compressionDefinitions.js +27 -0
- package/lib/compressionDefinitions.js.map +1 -0
- package/lib/containerRuntime.d.ts +78 -52
- package/lib/containerRuntime.d.ts.map +1 -1
- package/lib/containerRuntime.js +143 -56
- package/lib/containerRuntime.js.map +1 -1
- package/lib/dataStoreContext.d.ts +3 -0
- package/lib/dataStoreContext.d.ts.map +1 -1
- package/lib/dataStoreContext.js +57 -1
- package/lib/dataStoreContext.js.map +1 -1
- package/lib/deltaManagerProxies.d.ts +55 -12
- package/lib/deltaManagerProxies.d.ts.map +1 -1
- package/lib/deltaManagerProxies.js +63 -55
- package/lib/deltaManagerProxies.js.map +1 -1
- package/lib/gc/gcDefinitions.d.ts +2 -0
- package/lib/gc/gcDefinitions.d.ts.map +1 -1
- package/lib/gc/gcDefinitions.js.map +1 -1
- package/lib/index.d.ts +4 -2
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +2 -1
- package/lib/index.js.map +1 -1
- package/lib/legacy.d.ts +1 -0
- package/lib/opLifecycle/batchManager.d.ts +1 -1
- package/lib/opLifecycle/batchManager.d.ts.map +1 -1
- package/lib/opLifecycle/batchManager.js +4 -1
- package/lib/opLifecycle/batchManager.js.map +1 -1
- package/lib/opLifecycle/definitions.d.ts +35 -4
- package/lib/opLifecycle/definitions.d.ts.map +1 -1
- package/lib/opLifecycle/definitions.js.map +1 -1
- package/lib/opLifecycle/index.d.ts +1 -1
- package/lib/opLifecycle/index.d.ts.map +1 -1
- package/lib/opLifecycle/index.js.map +1 -1
- package/lib/opLifecycle/opCompressor.js +1 -1
- package/lib/opLifecycle/opCompressor.js.map +1 -1
- package/lib/opLifecycle/opDecompressor.js +1 -1
- package/lib/opLifecycle/opDecompressor.js.map +1 -1
- package/lib/opLifecycle/opGroupingManager.d.ts +2 -2
- package/lib/opLifecycle/opGroupingManager.d.ts.map +1 -1
- package/lib/opLifecycle/opGroupingManager.js +1 -2
- package/lib/opLifecycle/opGroupingManager.js.map +1 -1
- package/lib/opLifecycle/opSerialization.d.ts +3 -1
- package/lib/opLifecycle/opSerialization.d.ts.map +1 -1
- package/lib/opLifecycle/opSerialization.js +4 -2
- package/lib/opLifecycle/opSerialization.js.map +1 -1
- package/lib/opLifecycle/outbox.d.ts +6 -3
- package/lib/opLifecycle/outbox.d.ts.map +1 -1
- package/lib/opLifecycle/outbox.js +46 -20
- package/lib/opLifecycle/outbox.js.map +1 -1
- package/lib/packageVersion.d.ts +1 -1
- package/lib/packageVersion.d.ts.map +1 -1
- package/lib/packageVersion.js +1 -1
- package/lib/packageVersion.js.map +1 -1
- package/lib/pendingStateManager.d.ts +36 -7
- package/lib/pendingStateManager.d.ts.map +1 -1
- package/lib/pendingStateManager.js +84 -17
- package/lib/pendingStateManager.js.map +1 -1
- package/lib/runtimeLayerCompatState.d.ts.map +1 -1
- package/lib/runtimeLayerCompatState.js +2 -2
- package/lib/runtimeLayerCompatState.js.map +1 -1
- package/lib/summary/documentSchema.d.ts +1 -0
- package/lib/summary/documentSchema.d.ts.map +1 -1
- package/lib/summary/documentSchema.js +2 -0
- package/lib/summary/documentSchema.js.map +1 -1
- package/lib/tsdoc-metadata.json +1 -1
- package/package.json +21 -20
- package/src/blobManager/blobManager.ts +48 -15
- package/src/channelCollection.ts +27 -0
- package/src/compatUtils.ts +211 -0
- package/src/compressionDefinitions.ts +47 -0
- package/src/containerRuntime.ts +259 -108
- package/src/dataStoreContext.ts +82 -2
- package/src/deltaManagerProxies.ts +132 -70
- package/src/gc/gcDefinitions.ts +2 -0
- package/src/index.ts +5 -3
- package/src/opLifecycle/batchManager.ts +5 -4
- package/src/opLifecycle/definitions.ts +34 -4
- package/src/opLifecycle/index.ts +1 -0
- package/src/opLifecycle/opCompressor.ts +1 -1
- package/src/opLifecycle/opDecompressor.ts +1 -1
- package/src/opLifecycle/opGroupingManager.ts +7 -5
- package/src/opLifecycle/opSerialization.ts +6 -2
- package/src/opLifecycle/outbox.ts +65 -30
- package/src/packageVersion.ts +1 -1
- package/src/pendingStateManager.ts +135 -21
- package/src/runtimeLayerCompatState.ts +5 -2
- package/src/summary/documentSchema.ts +3 -0
package/src/dataStoreContext.ts
CHANGED
|
@@ -5,11 +5,17 @@
|
|
|
5
5
|
|
|
6
6
|
import { TypedEventEmitter, type ILayerCompatDetails } from "@fluid-internal/client-utils";
|
|
7
7
|
import { AttachState, IAudience } from "@fluidframework/container-definitions";
|
|
8
|
-
import {
|
|
8
|
+
import {
|
|
9
|
+
IDeltaManager,
|
|
10
|
+
isIDeltaManagerFull,
|
|
11
|
+
type IDeltaManagerFull,
|
|
12
|
+
type ReadOnlyInfo,
|
|
13
|
+
} from "@fluidframework/container-definitions/internal";
|
|
9
14
|
import {
|
|
10
15
|
FluidObject,
|
|
11
16
|
IDisposable,
|
|
12
17
|
ITelemetryBaseProperties,
|
|
18
|
+
type IErrorBase,
|
|
13
19
|
type IEvent,
|
|
14
20
|
} from "@fluidframework/core-interfaces";
|
|
15
21
|
import {
|
|
@@ -75,6 +81,7 @@ import {
|
|
|
75
81
|
tagCodeArtifacts,
|
|
76
82
|
} from "@fluidframework/telemetry-utils/internal";
|
|
77
83
|
|
|
84
|
+
import { BaseDeltaManagerProxy } from "./deltaManagerProxies.js";
|
|
78
85
|
import {
|
|
79
86
|
runtimeCompatDetailsForDataStore,
|
|
80
87
|
validateDatastoreCompatibility,
|
|
@@ -188,6 +195,58 @@ export interface IFluidDataStoreContextEvents extends IEvent {
|
|
|
188
195
|
(event: "attaching" | "attached", listener: () => void);
|
|
189
196
|
}
|
|
190
197
|
|
|
198
|
+
/**
|
|
199
|
+
* Eventually we should remove the delta manger from being exposed to Datastore runtimes via the context. However to remove that exposure we need to add new
|
|
200
|
+
* features, and those features themselves need forward and back compat. This proxy is here to enable that back compat. Each feature this proxy is used to
|
|
201
|
+
* support should be listed below, and as layer compat support goes away for those feature, we should also remove them from this proxy, with the eventual goal
|
|
202
|
+
* of completely removing this proxy.
|
|
203
|
+
*
|
|
204
|
+
* - Everything regarding readonly is to support older datastore runtimes which do not have the setReadonly function, so they must get their readonly state via the delta manager.
|
|
205
|
+
*
|
|
206
|
+
*/
|
|
207
|
+
class ContextDeltaManagerProxy extends BaseDeltaManagerProxy {
|
|
208
|
+
constructor(
|
|
209
|
+
base: IDeltaManagerFull,
|
|
210
|
+
private readonly isReadOnly: () => boolean,
|
|
211
|
+
) {
|
|
212
|
+
super(base, {
|
|
213
|
+
onReadonly: (): void => {
|
|
214
|
+
/* readonly is controlled from the context which calls setReadonly */
|
|
215
|
+
},
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
public get readOnlyInfo(): ReadOnlyInfo {
|
|
220
|
+
const readonly = this.isReadOnly();
|
|
221
|
+
if (readonly === this.deltaManager.readOnlyInfo.readonly) {
|
|
222
|
+
return this.deltaManager.readOnlyInfo;
|
|
223
|
+
} else {
|
|
224
|
+
return readonly === true
|
|
225
|
+
? {
|
|
226
|
+
readonly,
|
|
227
|
+
forced: false,
|
|
228
|
+
permissions: undefined,
|
|
229
|
+
storageOnly: false,
|
|
230
|
+
}
|
|
231
|
+
: { readonly };
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* Called by the owning datastore context to configure the readonly
|
|
237
|
+
* state of the delta manger that is project down to the datastore
|
|
238
|
+
* runtime. This state may not align with that of the true delta
|
|
239
|
+
* manager if the context wishes to control the read only state
|
|
240
|
+
* differently than the delta manager itself.
|
|
241
|
+
*/
|
|
242
|
+
public setReadonly(
|
|
243
|
+
readonly: boolean,
|
|
244
|
+
readonlyConnectionReason?: { reason: string; error?: IErrorBase },
|
|
245
|
+
): void {
|
|
246
|
+
this.emit("readonly", readonly, readonlyConnectionReason);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
191
250
|
/**
|
|
192
251
|
* Represents the context for the store. This context is passed to the store runtime.
|
|
193
252
|
* @internal
|
|
@@ -217,10 +276,13 @@ export abstract class FluidDataStoreContext
|
|
|
217
276
|
return this.parentContext.baseLogger;
|
|
218
277
|
}
|
|
219
278
|
|
|
279
|
+
private readonly _contextDeltaManagerProxy: ContextDeltaManagerProxy;
|
|
220
280
|
public get deltaManager(): IDeltaManager<ISequencedDocumentMessage, IDocumentMessage> {
|
|
221
|
-
return this.
|
|
281
|
+
return this._contextDeltaManagerProxy;
|
|
222
282
|
}
|
|
223
283
|
|
|
284
|
+
public isReadOnly = (): boolean => this.parentContext.isReadOnly?.() ?? false;
|
|
285
|
+
|
|
224
286
|
public get connected(): boolean {
|
|
225
287
|
return this.parentContext.connected;
|
|
226
288
|
}
|
|
@@ -420,6 +482,16 @@ export abstract class FluidDataStoreContext
|
|
|
420
482
|
// By default, a data store can log maximum 10 local changes telemetry in summarizer.
|
|
421
483
|
this.localChangesTelemetryCount =
|
|
422
484
|
this.mc.config.getNumber("Fluid.Telemetry.LocalChangesTelemetryCount") ?? 10;
|
|
485
|
+
|
|
486
|
+
assert(
|
|
487
|
+
isIDeltaManagerFull(this.parentContext.deltaManager),
|
|
488
|
+
0xb83 /* Invalid delta manager */,
|
|
489
|
+
);
|
|
490
|
+
|
|
491
|
+
this._contextDeltaManagerProxy = new ContextDeltaManagerProxy(
|
|
492
|
+
this.parentContext.deltaManager,
|
|
493
|
+
() => this.isReadOnly(),
|
|
494
|
+
);
|
|
423
495
|
}
|
|
424
496
|
|
|
425
497
|
public dispose(): void {
|
|
@@ -437,6 +509,7 @@ export abstract class FluidDataStoreContext
|
|
|
437
509
|
})
|
|
438
510
|
.catch((error) => {});
|
|
439
511
|
}
|
|
512
|
+
this._contextDeltaManagerProxy.dispose();
|
|
440
513
|
}
|
|
441
514
|
|
|
442
515
|
/**
|
|
@@ -615,6 +688,13 @@ export abstract class FluidDataStoreContext
|
|
|
615
688
|
this.channel!.setConnectionState(connected, clientId);
|
|
616
689
|
}
|
|
617
690
|
|
|
691
|
+
public notifyReadOnlyState(readonly: boolean): void {
|
|
692
|
+
this.verifyNotClosed("notifyReadOnlyState", false /* checkTombstone */);
|
|
693
|
+
|
|
694
|
+
this.channel?.notifyReadOnlyState?.(readonly);
|
|
695
|
+
this._contextDeltaManagerProxy.setReadonly(readonly);
|
|
696
|
+
}
|
|
697
|
+
|
|
618
698
|
/**
|
|
619
699
|
* Process messages for this data store. The messages here are contiguous messages for this data store in a batch.
|
|
620
700
|
* @param messageCollection - The collection of messages to process.
|
|
@@ -25,13 +25,68 @@ import {
|
|
|
25
25
|
import type { PendingStateManager } from "./pendingStateManager.js";
|
|
26
26
|
import { summarizerClientType } from "./summary/index.js";
|
|
27
27
|
|
|
28
|
+
/**
|
|
29
|
+
* Interface defining event handlers for the BaseDeltaManagerProxy.
|
|
30
|
+
* These handlers allow customization of behavior for various DeltaManager events.
|
|
31
|
+
*/
|
|
32
|
+
export interface BaseDeltaManagerProxyEventHandlers {
|
|
33
|
+
/**
|
|
34
|
+
* Event handler triggered when the readonly state changes.
|
|
35
|
+
* @param readonly - Indicates if the connection is readonly.
|
|
36
|
+
* @param readonlyConnectionReason - Optional reason and error details for the readonly state.
|
|
37
|
+
*/
|
|
38
|
+
onReadonly: (
|
|
39
|
+
readonly: boolean,
|
|
40
|
+
readonlyConnectionReason?: { reason: string; error?: IErrorBase },
|
|
41
|
+
) => void;
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Event handler triggered before sending a message.
|
|
45
|
+
* @param messageBuffer - The buffer of messages to be sent.
|
|
46
|
+
*/
|
|
47
|
+
onPrepareSend: (messageBuffer: unknown[]) => void;
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Event handler triggered when an operation is submitted.
|
|
51
|
+
* @param message - The document message being submitted.
|
|
52
|
+
*/
|
|
53
|
+
onSubmitOp: (message: IDocumentMessage) => void;
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Event handler triggered when an operation is received.
|
|
57
|
+
* @param message - The sequenced document message received.
|
|
58
|
+
* @param processingTime - The time taken to process the message.
|
|
59
|
+
*/
|
|
60
|
+
onOp: (message: ISequencedDocumentMessage, processingTime: number) => void;
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Event handler triggered when a pong response is received.
|
|
64
|
+
* @param latency - The latency of the pong response.
|
|
65
|
+
*/
|
|
66
|
+
onPong: (latency: number) => void;
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Event handler triggered when a connection is established.
|
|
70
|
+
* @param details - The connection details.
|
|
71
|
+
* @param opsBehind - Optional number of operations behind the latest state.
|
|
72
|
+
*/
|
|
73
|
+
onConnect: (details: IConnectionDetails, opsBehind?: number) => void;
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Event handler triggered when a disconnection occurs.
|
|
77
|
+
* @param reason - The reason for the disconnection.
|
|
78
|
+
* @param error - Optional error details for the disconnection.
|
|
79
|
+
*/
|
|
80
|
+
onDisconnect: (reason: string, error?: IAnyDriverError) => void;
|
|
81
|
+
}
|
|
82
|
+
|
|
28
83
|
/**
|
|
29
84
|
* Base class for DeltaManager proxy that proxy's access to the real DeltaManager.
|
|
30
85
|
*
|
|
31
86
|
* This class allows us to build proxy functionality without actually having to implement all the methods
|
|
32
87
|
* of the DeltaManager.
|
|
33
88
|
*/
|
|
34
|
-
export
|
|
89
|
+
export class BaseDeltaManagerProxy
|
|
35
90
|
extends TypedEventEmitter<IDeltaManagerEvents>
|
|
36
91
|
implements IDeltaManagerFull
|
|
37
92
|
{
|
|
@@ -99,29 +154,64 @@ export abstract class BaseDeltaManagerProxy
|
|
|
99
154
|
return this.deltaManager.readOnlyInfo;
|
|
100
155
|
}
|
|
101
156
|
|
|
102
|
-
|
|
157
|
+
private readonly eventHandlers: BaseDeltaManagerProxyEventHandlers;
|
|
158
|
+
|
|
159
|
+
constructor(
|
|
160
|
+
protected readonly deltaManager: IDeltaManagerFull,
|
|
161
|
+
overrides?: Partial<BaseDeltaManagerProxyEventHandlers>,
|
|
162
|
+
) {
|
|
103
163
|
super();
|
|
104
164
|
|
|
165
|
+
this.eventHandlers = {
|
|
166
|
+
onPrepareSend: (messageBuffer: unknown[]): void => {
|
|
167
|
+
this.emit("prepareSend", messageBuffer);
|
|
168
|
+
},
|
|
169
|
+
onSubmitOp: (message: IDocumentMessage): void => {
|
|
170
|
+
this.emit("submitOp", message);
|
|
171
|
+
},
|
|
172
|
+
onOp: (message: ISequencedDocumentMessage, processingTime: number): void => {
|
|
173
|
+
this.emit("op", message, processingTime);
|
|
174
|
+
},
|
|
175
|
+
onPong: (latency: number): void => {
|
|
176
|
+
this.emit("pong", latency);
|
|
177
|
+
},
|
|
178
|
+
onConnect: (details: IConnectionDetails, opsBehind?: number): void => {
|
|
179
|
+
this.emit("connect", details, opsBehind);
|
|
180
|
+
},
|
|
181
|
+
onDisconnect: (reason: string, error?: IAnyDriverError): void => {
|
|
182
|
+
this.emit("disconnect", reason, error);
|
|
183
|
+
},
|
|
184
|
+
onReadonly: (
|
|
185
|
+
readonly: boolean,
|
|
186
|
+
readonlyConnectionReason?: { reason: string; error?: IErrorBase },
|
|
187
|
+
): void => {
|
|
188
|
+
this.emit("readonly", readonly, readonlyConnectionReason);
|
|
189
|
+
},
|
|
190
|
+
|
|
191
|
+
...overrides,
|
|
192
|
+
};
|
|
193
|
+
|
|
105
194
|
// We are expecting this class to have many listeners, so we suppress noisy "MaxListenersExceededWarning" logging.
|
|
106
195
|
super.setMaxListeners(0);
|
|
107
196
|
|
|
108
|
-
this.deltaManager.on("prepareSend", this.onPrepareSend);
|
|
109
|
-
this.deltaManager.on("submitOp", this.onSubmitOp);
|
|
110
|
-
this.deltaManager.on("op", this.onOp);
|
|
111
|
-
this.deltaManager.on("pong", this.onPong);
|
|
112
|
-
this.deltaManager.on("connect", this.onConnect);
|
|
113
|
-
this.deltaManager.on("disconnect", this.onDisconnect);
|
|
114
|
-
this.deltaManager.on("readonly", this.onReadonly);
|
|
197
|
+
this.deltaManager.on("prepareSend", this.eventHandlers.onPrepareSend);
|
|
198
|
+
this.deltaManager.on("submitOp", this.eventHandlers.onSubmitOp);
|
|
199
|
+
this.deltaManager.on("op", this.eventHandlers.onOp);
|
|
200
|
+
this.deltaManager.on("pong", this.eventHandlers.onPong);
|
|
201
|
+
this.deltaManager.on("connect", this.eventHandlers.onConnect);
|
|
202
|
+
this.deltaManager.on("disconnect", this.eventHandlers.onDisconnect);
|
|
203
|
+
this.deltaManager.on("readonly", this.eventHandlers.onReadonly);
|
|
115
204
|
}
|
|
116
205
|
|
|
117
206
|
public dispose(): void {
|
|
118
|
-
this.deltaManager.off("prepareSend", this.onPrepareSend);
|
|
119
|
-
this.deltaManager.off("submitOp", this.onSubmitOp);
|
|
120
|
-
this.deltaManager.off("op", this.onOp);
|
|
121
|
-
this.deltaManager.off("pong", this.onPong);
|
|
122
|
-
this.deltaManager.off("connect", this.onConnect);
|
|
123
|
-
this.deltaManager.off("disconnect", this.onDisconnect);
|
|
124
|
-
this.deltaManager.off("readonly", this.onReadonly);
|
|
207
|
+
this.deltaManager.off("prepareSend", this.eventHandlers.onPrepareSend);
|
|
208
|
+
this.deltaManager.off("submitOp", this.eventHandlers.onSubmitOp);
|
|
209
|
+
this.deltaManager.off("op", this.eventHandlers.onOp);
|
|
210
|
+
this.deltaManager.off("pong", this.eventHandlers.onPong);
|
|
211
|
+
this.deltaManager.off("connect", this.eventHandlers.onConnect);
|
|
212
|
+
this.deltaManager.off("disconnect", this.eventHandlers.onDisconnect);
|
|
213
|
+
this.deltaManager.off("readonly", this.eventHandlers.onReadonly);
|
|
214
|
+
this.removeAllListeners();
|
|
125
215
|
}
|
|
126
216
|
|
|
127
217
|
public submitSignal(content: string, targetClientId?: string): void {
|
|
@@ -131,34 +221,6 @@ export abstract class BaseDeltaManagerProxy
|
|
|
131
221
|
public flush(): void {
|
|
132
222
|
return this.deltaManager.flush();
|
|
133
223
|
}
|
|
134
|
-
|
|
135
|
-
private readonly onPrepareSend = (messageBuffer: unknown[]): void => {
|
|
136
|
-
this.emit("prepareSend", messageBuffer);
|
|
137
|
-
};
|
|
138
|
-
private readonly onSubmitOp = (message: IDocumentMessage): void => {
|
|
139
|
-
this.emit("submitOp", message);
|
|
140
|
-
};
|
|
141
|
-
protected readonly onOp = (
|
|
142
|
-
message: ISequencedDocumentMessage,
|
|
143
|
-
processingTime: number,
|
|
144
|
-
): void => {
|
|
145
|
-
this.emit("op", message, processingTime);
|
|
146
|
-
};
|
|
147
|
-
private readonly onPong = (latency: number): void => {
|
|
148
|
-
this.emit("pong", latency);
|
|
149
|
-
};
|
|
150
|
-
private readonly onConnect = (details: IConnectionDetails, opsBehind?: number): void => {
|
|
151
|
-
this.emit("connect", details, opsBehind);
|
|
152
|
-
};
|
|
153
|
-
private readonly onDisconnect = (reason: string, error?: IAnyDriverError): void => {
|
|
154
|
-
this.emit("disconnect", reason, error);
|
|
155
|
-
};
|
|
156
|
-
private readonly onReadonly = (
|
|
157
|
-
readonly: boolean,
|
|
158
|
-
readonlyConnectionReason?: { reason: string; error?: IErrorBase },
|
|
159
|
-
): void => {
|
|
160
|
-
this.emit("readonly", readonly, readonlyConnectionReason);
|
|
161
|
-
};
|
|
162
224
|
}
|
|
163
225
|
|
|
164
226
|
/**
|
|
@@ -167,31 +229,34 @@ export abstract class BaseDeltaManagerProxy
|
|
|
167
229
|
* - Summarizer client should not be active to layers below the container runtime to restrict local changes.
|
|
168
230
|
*/
|
|
169
231
|
export class DeltaManagerSummarizerProxy extends BaseDeltaManagerProxy {
|
|
232
|
+
public static wrapIfSummarizer(deltaManager: IDeltaManagerFull): IDeltaManagerFull {
|
|
233
|
+
if (deltaManager.clientDetails.type === summarizerClientType) {
|
|
234
|
+
return new DeltaManagerSummarizerProxy(deltaManager);
|
|
235
|
+
}
|
|
236
|
+
return deltaManager;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
// eslint-disable-next-line @typescript-eslint/class-literal-property-style
|
|
170
240
|
public get active(): boolean {
|
|
171
241
|
// Summarize clients should not be active. There shouldn't be any local changes (writes) in the summarizer
|
|
172
242
|
// except for the SummarizeOp which is generated by the runtime.
|
|
173
|
-
return
|
|
243
|
+
return false;
|
|
174
244
|
}
|
|
175
245
|
|
|
176
246
|
public get readOnlyInfo(): ReadOnlyInfo {
|
|
177
247
|
// Summarizer clients should be read-only as far as the runtime and layers below are concerned. There shouldn't
|
|
178
248
|
// be any local changes (writes) in the summarizer except for the summarize op which is generated by the runtime.
|
|
179
|
-
if (this.isSummarizerClient) {
|
|
180
|
-
return {
|
|
181
|
-
readonly: true,
|
|
182
|
-
forced: false,
|
|
183
|
-
permissions: undefined,
|
|
184
|
-
storageOnly: false,
|
|
185
|
-
};
|
|
186
|
-
}
|
|
187
|
-
return this.deltaManager.readOnlyInfo;
|
|
188
|
-
}
|
|
189
249
|
|
|
190
|
-
|
|
250
|
+
return {
|
|
251
|
+
readonly: true,
|
|
252
|
+
forced: false,
|
|
253
|
+
permissions: undefined,
|
|
254
|
+
storageOnly: false,
|
|
255
|
+
};
|
|
256
|
+
}
|
|
191
257
|
|
|
192
258
|
constructor(protected readonly deltaManager: IDeltaManagerFull) {
|
|
193
|
-
super(deltaManager);
|
|
194
|
-
this.isSummarizerClient = this.deltaManager.clientDetails.type === summarizerClientType;
|
|
259
|
+
super(deltaManager, { onReadonly: () => {} });
|
|
195
260
|
}
|
|
196
261
|
}
|
|
197
262
|
|
|
@@ -228,17 +293,6 @@ export class DeltaManagerPendingOpsProxy extends BaseDeltaManagerProxy {
|
|
|
228
293
|
};
|
|
229
294
|
}
|
|
230
295
|
|
|
231
|
-
protected readonly onOp = (
|
|
232
|
-
message: ISequencedDocumentMessage,
|
|
233
|
-
processingTime: number,
|
|
234
|
-
): void => {
|
|
235
|
-
const messageIntercept = {
|
|
236
|
-
...message,
|
|
237
|
-
minimumSequenceNumber: this.minimumSequenceNumber,
|
|
238
|
-
};
|
|
239
|
-
this.emit("op", messageIntercept, processingTime);
|
|
240
|
-
};
|
|
241
|
-
|
|
242
296
|
constructor(
|
|
243
297
|
protected readonly deltaManager: IDeltaManagerFull,
|
|
244
298
|
private readonly pendingStateManager: Pick<
|
|
@@ -246,6 +300,14 @@ export class DeltaManagerPendingOpsProxy extends BaseDeltaManagerProxy {
|
|
|
246
300
|
"minimumPendingMessageSequenceNumber"
|
|
247
301
|
>,
|
|
248
302
|
) {
|
|
249
|
-
super(deltaManager
|
|
303
|
+
super(deltaManager, {
|
|
304
|
+
onOp: (message: ISequencedDocumentMessage, processingTime: number): void => {
|
|
305
|
+
const messageIntercept = {
|
|
306
|
+
...message,
|
|
307
|
+
minimumSequenceNumber: this.minimumSequenceNumber,
|
|
308
|
+
};
|
|
309
|
+
this.emit("op", messageIntercept, processingTime);
|
|
310
|
+
},
|
|
311
|
+
});
|
|
250
312
|
}
|
|
251
313
|
}
|
package/src/gc/gcDefinitions.ts
CHANGED
|
@@ -333,6 +333,8 @@ export type GarbageCollectionMessage = ISweepMessage | ITombstoneLoadedMessage;
|
|
|
333
333
|
|
|
334
334
|
/**
|
|
335
335
|
* Defines the APIs for the runtime object to be passed to the garbage collector.
|
|
336
|
+
*
|
|
337
|
+
* @internal
|
|
336
338
|
*/
|
|
337
339
|
export interface IGarbageCollectionRuntime {
|
|
338
340
|
/**
|
package/src/index.ts
CHANGED
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
export {
|
|
7
|
+
ContainerRuntimeOptions,
|
|
8
|
+
ContainerRuntimeOptionsInternal,
|
|
7
9
|
ISummaryRuntimeOptions,
|
|
8
10
|
IContainerRuntimeOptions,
|
|
9
11
|
IContainerRuntimeOptionsInternal,
|
|
@@ -14,11 +16,10 @@ export {
|
|
|
14
16
|
DeletedResponseHeaderKey,
|
|
15
17
|
TombstoneResponseHeaderKey,
|
|
16
18
|
InactiveResponseHeaderKey,
|
|
17
|
-
ICompressionRuntimeOptions,
|
|
18
|
-
CompressionAlgorithms,
|
|
19
19
|
RuntimeHeaderData,
|
|
20
|
-
disabledCompressionConfig,
|
|
21
20
|
} from "./containerRuntime.js";
|
|
21
|
+
export type { ICompressionRuntimeOptions } from "./compressionDefinitions.js";
|
|
22
|
+
export { CompressionAlgorithms, disabledCompressionConfig } from "./compressionDefinitions.js";
|
|
22
23
|
export {
|
|
23
24
|
ContainerMessageType,
|
|
24
25
|
UnknownContainerRuntimeMessage,
|
|
@@ -35,6 +36,7 @@ export {
|
|
|
35
36
|
IGCMetadata,
|
|
36
37
|
GCFeatureMatrix,
|
|
37
38
|
GCVersion,
|
|
39
|
+
IGarbageCollectionRuntime,
|
|
38
40
|
IGCRuntimeOptions,
|
|
39
41
|
IMarkPhaseStats,
|
|
40
42
|
ISweepPhaseStats,
|
|
@@ -10,11 +10,12 @@ import {
|
|
|
10
10
|
TelemetryDataTag,
|
|
11
11
|
} from "@fluidframework/telemetry-utils/internal";
|
|
12
12
|
|
|
13
|
-
import { ICompressionRuntimeOptions } from "../
|
|
13
|
+
import { ICompressionRuntimeOptions } from "../compressionDefinitions.js";
|
|
14
14
|
import { asBatchMetadata, type IBatchMetadata } from "../metadata.js";
|
|
15
15
|
import type { IPendingMessage } from "../pendingStateManager.js";
|
|
16
16
|
|
|
17
17
|
import { LocalBatchMessage, IBatchCheckpoint, type LocalBatch } from "./definitions.js";
|
|
18
|
+
import { serializeOp } from "./opSerialization.js";
|
|
18
19
|
import type { BatchStartInfo } from "./remoteMessageProcessor.js";
|
|
19
20
|
|
|
20
21
|
export interface IBatchManagerOptions {
|
|
@@ -127,10 +128,12 @@ export class BatchManager {
|
|
|
127
128
|
* Gets the pending batch and clears state for the next batch.
|
|
128
129
|
*/
|
|
129
130
|
public popBatch(batchId?: BatchId): LocalBatch {
|
|
131
|
+
assert(this.pendingBatch[0] !== undefined, 0xb8a /* expected non-empty batch */);
|
|
130
132
|
const batch: LocalBatch = {
|
|
131
133
|
messages: this.pendingBatch,
|
|
132
134
|
referenceSequenceNumber: this.referenceSequenceNumber,
|
|
133
135
|
hasReentrantOps: this.hasReentrantOps,
|
|
136
|
+
staged: this.pendingBatch[0].staged,
|
|
134
137
|
};
|
|
135
138
|
|
|
136
139
|
this.pendingBatch = [];
|
|
@@ -158,9 +161,7 @@ export class BatchManager {
|
|
|
158
161
|
throw new LoggingError("Ops generated during rollback", {
|
|
159
162
|
count,
|
|
160
163
|
...tagData(TelemetryDataTag.UserData, {
|
|
161
|
-
ops:
|
|
162
|
-
this.pendingBatch.slice(startPoint).map((b) => b.serializedOp),
|
|
163
|
-
),
|
|
164
|
+
ops: serializeOp(this.pendingBatch.slice(startPoint).map((b) => b.runtimeOp)),
|
|
164
165
|
}),
|
|
165
166
|
});
|
|
166
167
|
}
|
|
@@ -5,17 +5,33 @@
|
|
|
5
5
|
|
|
6
6
|
import type { IBatchMessage } from "@fluidframework/container-definitions/internal";
|
|
7
7
|
|
|
8
|
-
import { CompressionAlgorithms } from "../
|
|
8
|
+
import { CompressionAlgorithms } from "../compressionDefinitions.js";
|
|
9
|
+
import type { LocalContainerRuntimeMessage } from "../messageTypes.js";
|
|
9
10
|
|
|
10
11
|
/**
|
|
11
12
|
* Local Batch message, before it is virtualized and sent to the ordering service
|
|
12
13
|
*/
|
|
13
14
|
export interface LocalBatchMessage {
|
|
14
|
-
|
|
15
|
+
/**
|
|
16
|
+
* The original local op
|
|
17
|
+
*/
|
|
18
|
+
runtimeOp: LocalContainerRuntimeMessage;
|
|
19
|
+
/**
|
|
20
|
+
* Optional metadata which is not to be serialized with the op, and is visible to the ordering service
|
|
21
|
+
*/
|
|
15
22
|
metadata?: Record<string, unknown>;
|
|
23
|
+
/**
|
|
24
|
+
* Metadata used by this local client in flows such as rebase
|
|
25
|
+
*/
|
|
16
26
|
localOpMetadata?: unknown;
|
|
27
|
+
/**
|
|
28
|
+
* Reference sequence number this op is based on
|
|
29
|
+
*/
|
|
17
30
|
referenceSequenceNumber: number;
|
|
18
|
-
|
|
31
|
+
/**
|
|
32
|
+
* If true, this op is not to be submitted to the ordering service yet, since it was submitted during Staging Mode
|
|
33
|
+
*/
|
|
34
|
+
staged?: boolean;
|
|
19
35
|
|
|
20
36
|
/**
|
|
21
37
|
* @deprecated Use serializedOp
|
|
@@ -23,6 +39,15 @@ export interface LocalBatchMessage {
|
|
|
23
39
|
contents?: never; // To ensure we don't leave this one when converting from OutboundBatchMessage
|
|
24
40
|
}
|
|
25
41
|
|
|
42
|
+
/**
|
|
43
|
+
* Placeholder for an empty batch, for tracking the pending local empty batch
|
|
44
|
+
*/
|
|
45
|
+
export interface LocalEmptyBatchPlaceholder {
|
|
46
|
+
metadata?: Record<string, unknown>;
|
|
47
|
+
localOpMetadata: { emptyBatch: true };
|
|
48
|
+
referenceSequenceNumber: number;
|
|
49
|
+
}
|
|
50
|
+
|
|
26
51
|
/**
|
|
27
52
|
* Virtualized Batch message, on its way out the door to the ordering service
|
|
28
53
|
*/
|
|
@@ -40,7 +65,12 @@ export type OutboundBatchMessage = IBatchMessage & {
|
|
|
40
65
|
/**
|
|
41
66
|
* A batch of messages we have accumulated locally, but haven't sent to the ordering service yet.
|
|
42
67
|
*/
|
|
43
|
-
export
|
|
68
|
+
export interface LocalBatch extends IBatch<LocalBatchMessage[]> {
|
|
69
|
+
/**
|
|
70
|
+
* If true, this batch is not to be submitted to the ordering service yet, since it was submitted during Staging Mode
|
|
71
|
+
*/
|
|
72
|
+
staged?: boolean;
|
|
73
|
+
}
|
|
44
74
|
|
|
45
75
|
/**
|
|
46
76
|
* A batch of messages that has been virtualized as needed (grouped, compressed, chunked)
|
package/src/opLifecycle/index.ts
CHANGED
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
} from "@fluidframework/telemetry-utils/internal";
|
|
14
14
|
import { compress } from "lz4js";
|
|
15
15
|
|
|
16
|
-
import { CompressionAlgorithms } from "../
|
|
16
|
+
import { CompressionAlgorithms } from "../compressionDefinitions.js";
|
|
17
17
|
|
|
18
18
|
import { type OutboundBatchMessage, type OutboundSingletonBatch } from "./definitions.js";
|
|
19
19
|
import { estimateSocketSize } from "./outbox.js";
|
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
} from "@fluidframework/telemetry-utils/internal";
|
|
14
14
|
import { decompress } from "lz4js";
|
|
15
15
|
|
|
16
|
-
import { CompressionAlgorithms } from "../
|
|
16
|
+
import { CompressionAlgorithms } from "../compressionDefinitions.js";
|
|
17
17
|
import { IBatchMetadata } from "../metadata.js";
|
|
18
18
|
|
|
19
19
|
/**
|
|
@@ -12,8 +12,8 @@ import {
|
|
|
12
12
|
} from "@fluidframework/telemetry-utils/internal";
|
|
13
13
|
|
|
14
14
|
import {
|
|
15
|
+
type LocalEmptyBatchPlaceholder,
|
|
15
16
|
type OutboundBatch,
|
|
16
|
-
type OutboundBatchMessage,
|
|
17
17
|
type OutboundSingletonBatch,
|
|
18
18
|
} from "./definitions.js";
|
|
19
19
|
|
|
@@ -67,7 +67,10 @@ export class OpGroupingManager {
|
|
|
67
67
|
public createEmptyGroupedBatch(
|
|
68
68
|
resubmittingBatchId: string,
|
|
69
69
|
referenceSequenceNumber: number,
|
|
70
|
-
): {
|
|
70
|
+
): {
|
|
71
|
+
outboundBatch: OutboundSingletonBatch;
|
|
72
|
+
placeholderMessage: LocalEmptyBatchPlaceholder;
|
|
73
|
+
} {
|
|
71
74
|
assert(
|
|
72
75
|
this.config.groupedBatchingEnabled,
|
|
73
76
|
0xa00 /* cannot create empty grouped batch when grouped batching is disabled */,
|
|
@@ -77,15 +80,14 @@ export class OpGroupingManager {
|
|
|
77
80
|
contents: [],
|
|
78
81
|
});
|
|
79
82
|
|
|
80
|
-
const placeholderMessage:
|
|
83
|
+
const placeholderMessage: LocalEmptyBatchPlaceholder = {
|
|
81
84
|
metadata: { batchId: resubmittingBatchId },
|
|
82
85
|
localOpMetadata: { emptyBatch: true },
|
|
83
86
|
referenceSequenceNumber,
|
|
84
|
-
contents: serializedOp,
|
|
85
87
|
};
|
|
86
88
|
const outboundBatch: OutboundSingletonBatch = {
|
|
87
89
|
contentSizeInBytes: 0,
|
|
88
|
-
messages: [placeholderMessage],
|
|
90
|
+
messages: [{ ...placeholderMessage, contents: serializedOp }],
|
|
89
91
|
referenceSequenceNumber,
|
|
90
92
|
};
|
|
91
93
|
return { outboundBatch, placeholderMessage };
|
|
@@ -30,10 +30,14 @@ export function ensureContentsDeserialized(mutableMessage: ISequencedDocumentMes
|
|
|
30
30
|
/**
|
|
31
31
|
* Before submitting an op to the Outbox, its contents must be serialized using this function.
|
|
32
32
|
* @remarks - The deserialization on process happens via the function {@link ensureContentsDeserialized}.
|
|
33
|
+
*
|
|
34
|
+
* @param toSerialize - op message to serialize. Also supports an array of ops.
|
|
33
35
|
*/
|
|
34
|
-
export function serializeOp(
|
|
36
|
+
export function serializeOp(
|
|
37
|
+
toSerialize: LocalContainerRuntimeMessage | LocalContainerRuntimeMessage[],
|
|
38
|
+
): string {
|
|
35
39
|
return JSON.stringify(
|
|
36
|
-
|
|
40
|
+
toSerialize,
|
|
37
41
|
// replacer:
|
|
38
42
|
(key, value: unknown) => {
|
|
39
43
|
// If 'value' is an IFluidHandle return its encoded form.
|