@fluidframework/container-runtime 2.0.0-rc.3.0.3 → 2.0.0-rc.4.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +46 -0
- package/api-report/container-runtime.api.md +72 -34
- package/dist/batchTracker.d.ts +1 -1
- package/dist/batchTracker.d.ts.map +1 -1
- package/dist/batchTracker.js.map +1 -1
- package/dist/blobManager.d.ts +7 -7
- package/dist/blobManager.d.ts.map +1 -1
- package/dist/blobManager.js +2 -4
- package/dist/blobManager.js.map +1 -1
- package/dist/channelCollection.d.ts +6 -4
- package/dist/channelCollection.d.ts.map +1 -1
- package/dist/channelCollection.js +20 -7
- package/dist/channelCollection.js.map +1 -1
- package/dist/connectionTelemetry.d.ts +2 -2
- package/dist/connectionTelemetry.d.ts.map +1 -1
- package/dist/connectionTelemetry.js +54 -5
- package/dist/connectionTelemetry.js.map +1 -1
- package/dist/containerRuntime.d.ts +17 -35
- package/dist/containerRuntime.d.ts.map +1 -1
- package/dist/containerRuntime.js +194 -163
- package/dist/containerRuntime.js.map +1 -1
- package/dist/dataStore.d.ts +1 -1
- package/dist/dataStore.d.ts.map +1 -1
- package/dist/dataStore.js.map +1 -1
- package/dist/dataStoreContext.d.ts +9 -6
- package/dist/dataStoreContext.d.ts.map +1 -1
- package/dist/dataStoreContext.js +19 -5
- package/dist/dataStoreContext.js.map +1 -1
- package/dist/dataStoreContexts.d.ts.map +1 -1
- package/dist/dataStoreContexts.js.map +1 -1
- package/dist/deltaManagerProxies.d.ts +81 -0
- package/dist/deltaManagerProxies.d.ts.map +1 -0
- package/dist/{deltaManagerSummarizerProxy.js → deltaManagerProxies.js} +75 -20
- package/dist/deltaManagerProxies.js.map +1 -0
- package/dist/deltaScheduler.d.ts +2 -2
- package/dist/deltaScheduler.d.ts.map +1 -1
- package/dist/deltaScheduler.js.map +1 -1
- package/dist/gc/garbageCollection.d.ts +1 -1
- package/dist/gc/garbageCollection.d.ts.map +1 -1
- package/dist/gc/garbageCollection.js.map +1 -1
- package/dist/gc/gcDefinitions.d.ts +1 -1
- package/dist/gc/gcDefinitions.d.ts.map +1 -1
- package/dist/gc/gcDefinitions.js.map +1 -1
- package/dist/gc/gcTelemetry.d.ts +1 -2
- package/dist/gc/gcTelemetry.d.ts.map +1 -1
- package/dist/gc/gcTelemetry.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/legacy.d.ts +6 -1
- package/dist/messageTypes.d.ts +5 -2
- package/dist/messageTypes.d.ts.map +1 -1
- package/dist/messageTypes.js.map +1 -1
- package/dist/metadata.d.ts +2 -2
- package/dist/metadata.d.ts.map +1 -1
- package/dist/metadata.js.map +1 -1
- package/dist/opLifecycle/batchManager.d.ts +4 -1
- package/dist/opLifecycle/batchManager.d.ts.map +1 -1
- package/dist/opLifecycle/batchManager.js +0 -10
- package/dist/opLifecycle/batchManager.js.map +1 -1
- package/dist/opLifecycle/outbox.d.ts +0 -4
- package/dist/opLifecycle/outbox.d.ts.map +1 -1
- package/dist/opLifecycle/outbox.js +7 -38
- package/dist/opLifecycle/outbox.js.map +1 -1
- package/dist/packageVersion.d.ts +1 -1
- package/dist/packageVersion.js +1 -1
- package/dist/packageVersion.js.map +1 -1
- package/dist/pendingStateManager.d.ts +9 -2
- package/dist/pendingStateManager.d.ts.map +1 -1
- package/dist/pendingStateManager.js +26 -10
- package/dist/pendingStateManager.js.map +1 -1
- package/dist/scheduleManager.d.ts +2 -2
- package/dist/scheduleManager.d.ts.map +1 -1
- package/dist/scheduleManager.js.map +1 -1
- package/dist/summary/documentSchema.d.ts +3 -1
- package/dist/summary/documentSchema.d.ts.map +1 -1
- package/dist/summary/documentSchema.js +25 -7
- package/dist/summary/documentSchema.js.map +1 -1
- package/dist/summary/index.d.ts +1 -1
- package/dist/summary/index.d.ts.map +1 -1
- package/dist/summary/index.js.map +1 -1
- package/dist/summary/orderedClientElection.d.ts +2 -2
- package/dist/summary/orderedClientElection.d.ts.map +1 -1
- package/dist/summary/orderedClientElection.js.map +1 -1
- package/dist/summary/runningSummarizer.js +10 -10
- package/dist/summary/runningSummarizer.js.map +1 -1
- package/dist/summary/summarizer.d.ts +1 -2
- package/dist/summary/summarizer.d.ts.map +1 -1
- package/dist/summary/summarizer.js.map +1 -1
- package/dist/summary/summarizerClientElection.d.ts +1 -1
- package/dist/summary/summarizerClientElection.d.ts.map +1 -1
- package/dist/summary/summarizerClientElection.js.map +1 -1
- package/dist/summary/summarizerHeuristics.d.ts +1 -1
- package/dist/summary/summarizerHeuristics.d.ts.map +1 -1
- package/dist/summary/summarizerHeuristics.js.map +1 -1
- package/dist/summary/summarizerNode/summarizerNode.d.ts +4 -3
- package/dist/summary/summarizerNode/summarizerNode.d.ts.map +1 -1
- package/dist/summary/summarizerNode/summarizerNode.js +4 -10
- package/dist/summary/summarizerNode/summarizerNode.js.map +1 -1
- package/dist/summary/summarizerNode/summarizerNodeUtils.d.ts +2 -3
- package/dist/summary/summarizerNode/summarizerNodeUtils.d.ts.map +1 -1
- package/dist/summary/summarizerNode/summarizerNodeUtils.js.map +1 -1
- package/dist/summary/summarizerNode/summarizerNodeWithGc.d.ts +1 -2
- package/dist/summary/summarizerNode/summarizerNodeWithGc.d.ts.map +1 -1
- package/dist/summary/summarizerNode/summarizerNodeWithGc.js +2 -9
- package/dist/summary/summarizerNode/summarizerNodeWithGc.js.map +1 -1
- package/dist/summary/summarizerTypes.d.ts +3 -5
- package/dist/summary/summarizerTypes.d.ts.map +1 -1
- package/dist/summary/summarizerTypes.js.map +1 -1
- package/dist/summary/summaryCollection.d.ts +2 -2
- package/dist/summary/summaryCollection.d.ts.map +1 -1
- package/dist/summary/summaryCollection.js.map +1 -1
- package/dist/summary/summaryFormat.d.ts +25 -5
- package/dist/summary/summaryFormat.d.ts.map +1 -1
- package/dist/summary/summaryFormat.js.map +1 -1
- package/dist/summary/summaryGenerator.d.ts +1 -2
- package/dist/summary/summaryGenerator.d.ts.map +1 -1
- package/dist/summary/summaryGenerator.js +12 -11
- package/dist/summary/summaryGenerator.js.map +1 -1
- package/dist/summary/summaryManager.d.ts.map +1 -1
- package/dist/summary/summaryManager.js +5 -5
- package/dist/summary/summaryManager.js.map +1 -1
- package/lib/batchTracker.d.ts +1 -1
- package/lib/batchTracker.d.ts.map +1 -1
- package/lib/batchTracker.js.map +1 -1
- package/lib/blobManager.d.ts +7 -7
- package/lib/blobManager.d.ts.map +1 -1
- package/lib/blobManager.js +3 -5
- package/lib/blobManager.js.map +1 -1
- package/lib/channelCollection.d.ts +6 -4
- package/lib/channelCollection.d.ts.map +1 -1
- package/lib/channelCollection.js +21 -8
- package/lib/channelCollection.js.map +1 -1
- package/lib/connectionTelemetry.d.ts +2 -2
- package/lib/connectionTelemetry.d.ts.map +1 -1
- package/lib/connectionTelemetry.js +49 -0
- package/lib/connectionTelemetry.js.map +1 -1
- package/lib/containerRuntime.d.ts +17 -35
- package/lib/containerRuntime.d.ts.map +1 -1
- package/lib/containerRuntime.js +195 -164
- package/lib/containerRuntime.js.map +1 -1
- package/lib/dataStore.d.ts +1 -1
- package/lib/dataStore.d.ts.map +1 -1
- package/lib/dataStore.js +1 -1
- package/lib/dataStore.js.map +1 -1
- package/lib/dataStoreContext.d.ts +9 -6
- package/lib/dataStoreContext.d.ts.map +1 -1
- package/lib/dataStoreContext.js +21 -7
- package/lib/dataStoreContext.js.map +1 -1
- package/lib/dataStoreContexts.d.ts.map +1 -1
- package/lib/dataStoreContexts.js.map +1 -1
- package/lib/deltaManagerProxies.d.ts +81 -0
- package/lib/deltaManagerProxies.d.ts.map +1 -0
- package/lib/{deltaManagerSummarizerProxy.js → deltaManagerProxies.js} +72 -19
- package/lib/deltaManagerProxies.js.map +1 -0
- package/lib/deltaScheduler.d.ts +2 -2
- package/lib/deltaScheduler.d.ts.map +1 -1
- package/lib/deltaScheduler.js.map +1 -1
- package/lib/gc/garbageCollection.d.ts +1 -1
- package/lib/gc/garbageCollection.d.ts.map +1 -1
- package/lib/gc/garbageCollection.js.map +1 -1
- package/lib/gc/gcDefinitions.d.ts +1 -1
- package/lib/gc/gcDefinitions.d.ts.map +1 -1
- package/lib/gc/gcDefinitions.js.map +1 -1
- package/lib/gc/gcTelemetry.d.ts +1 -2
- package/lib/gc/gcTelemetry.d.ts.map +1 -1
- package/lib/gc/gcTelemetry.js.map +1 -1
- package/lib/index.d.ts +1 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js.map +1 -1
- package/lib/legacy.d.ts +6 -1
- package/lib/messageTypes.d.ts +5 -2
- package/lib/messageTypes.d.ts.map +1 -1
- package/lib/messageTypes.js.map +1 -1
- package/lib/metadata.d.ts +2 -2
- package/lib/metadata.d.ts.map +1 -1
- package/lib/metadata.js.map +1 -1
- package/lib/opLifecycle/batchManager.d.ts +4 -1
- package/lib/opLifecycle/batchManager.d.ts.map +1 -1
- package/lib/opLifecycle/batchManager.js +0 -10
- package/lib/opLifecycle/batchManager.js.map +1 -1
- package/lib/opLifecycle/outbox.d.ts +0 -4
- package/lib/opLifecycle/outbox.d.ts.map +1 -1
- package/lib/opLifecycle/outbox.js +7 -38
- package/lib/opLifecycle/outbox.js.map +1 -1
- package/lib/packageVersion.d.ts +1 -1
- package/lib/packageVersion.js +1 -1
- package/lib/packageVersion.js.map +1 -1
- package/lib/pendingStateManager.d.ts +9 -2
- package/lib/pendingStateManager.d.ts.map +1 -1
- package/lib/pendingStateManager.js +27 -11
- package/lib/pendingStateManager.js.map +1 -1
- package/lib/scheduleManager.d.ts +2 -2
- package/lib/scheduleManager.d.ts.map +1 -1
- package/lib/scheduleManager.js.map +1 -1
- package/lib/summary/documentSchema.d.ts +3 -1
- package/lib/summary/documentSchema.d.ts.map +1 -1
- package/lib/summary/documentSchema.js +25 -7
- package/lib/summary/documentSchema.js.map +1 -1
- package/lib/summary/index.d.ts +1 -1
- package/lib/summary/index.d.ts.map +1 -1
- package/lib/summary/index.js.map +1 -1
- package/lib/summary/orderedClientElection.d.ts +2 -2
- package/lib/summary/orderedClientElection.d.ts.map +1 -1
- package/lib/summary/orderedClientElection.js +1 -1
- package/lib/summary/orderedClientElection.js.map +1 -1
- package/lib/summary/runningSummarizer.js +1 -1
- package/lib/summary/runningSummarizer.js.map +1 -1
- package/lib/summary/summarizer.d.ts +1 -2
- package/lib/summary/summarizer.d.ts.map +1 -1
- package/lib/summary/summarizer.js.map +1 -1
- package/lib/summary/summarizerClientElection.d.ts +1 -1
- package/lib/summary/summarizerClientElection.d.ts.map +1 -1
- package/lib/summary/summarizerClientElection.js.map +1 -1
- package/lib/summary/summarizerHeuristics.d.ts +1 -1
- package/lib/summary/summarizerHeuristics.d.ts.map +1 -1
- package/lib/summary/summarizerHeuristics.js.map +1 -1
- package/lib/summary/summarizerNode/summarizerNode.d.ts +4 -3
- package/lib/summary/summarizerNode/summarizerNode.d.ts.map +1 -1
- package/lib/summary/summarizerNode/summarizerNode.js +4 -10
- package/lib/summary/summarizerNode/summarizerNode.js.map +1 -1
- package/lib/summary/summarizerNode/summarizerNodeUtils.d.ts +2 -3
- package/lib/summary/summarizerNode/summarizerNodeUtils.d.ts.map +1 -1
- package/lib/summary/summarizerNode/summarizerNodeUtils.js.map +1 -1
- package/lib/summary/summarizerNode/summarizerNodeWithGc.d.ts +1 -2
- package/lib/summary/summarizerNode/summarizerNodeWithGc.d.ts.map +1 -1
- package/lib/summary/summarizerNode/summarizerNodeWithGc.js +2 -9
- package/lib/summary/summarizerNode/summarizerNodeWithGc.js.map +1 -1
- package/lib/summary/summarizerTypes.d.ts +3 -5
- package/lib/summary/summarizerTypes.d.ts.map +1 -1
- package/lib/summary/summarizerTypes.js.map +1 -1
- package/lib/summary/summaryCollection.d.ts +2 -2
- package/lib/summary/summaryCollection.d.ts.map +1 -1
- package/lib/summary/summaryCollection.js.map +1 -1
- package/lib/summary/summaryFormat.d.ts +25 -5
- package/lib/summary/summaryFormat.d.ts.map +1 -1
- package/lib/summary/summaryFormat.js.map +1 -1
- package/lib/summary/summaryGenerator.d.ts +1 -2
- package/lib/summary/summaryGenerator.d.ts.map +1 -1
- package/lib/summary/summaryGenerator.js +5 -4
- package/lib/summary/summaryGenerator.js.map +1 -1
- package/lib/summary/summaryManager.d.ts.map +1 -1
- package/lib/summary/summaryManager.js +2 -2
- package/lib/summary/summaryManager.js.map +1 -1
- package/lib/tsdoc-metadata.json +1 -1
- package/package.json +28 -50
- package/src/batchTracker.ts +1 -2
- package/src/blobManager.ts +11 -10
- package/src/channelCollection.ts +30 -12
- package/src/connectionTelemetry.ts +59 -4
- package/src/containerRuntime.ts +262 -239
- package/src/dataStore.ts +7 -4
- package/src/dataStoreContext.ts +57 -16
- package/src/dataStoreContexts.ts +1 -2
- package/src/{deltaManagerSummarizerProxy.ts → deltaManagerProxies.ts} +98 -24
- package/src/deltaScheduler.ts +2 -3
- package/src/gc/garbageCollection.ts +1 -1
- package/src/gc/gcDefinitions.ts +1 -1
- package/src/gc/gcTelemetry.ts +1 -3
- package/src/index.ts +5 -0
- package/src/messageTypes.ts +4 -2
- package/src/metadata.ts +2 -2
- package/src/opLifecycle/README.md +4 -4
- package/src/opLifecycle/batchManager.ts +5 -14
- package/src/opLifecycle/outbox.ts +7 -53
- package/src/packageVersion.ts +1 -1
- package/src/pendingStateManager.ts +38 -15
- package/src/scheduleManager.ts +2 -2
- package/src/summary/documentSchema.ts +37 -12
- package/src/summary/index.ts +4 -0
- package/src/summary/orderedClientElection.ts +6 -3
- package/src/summary/runningSummarizer.ts +1 -1
- package/src/summary/summarizer.ts +1 -1
- package/src/summary/summarizerClientElection.ts +1 -1
- package/src/summary/summarizerHeuristics.ts +1 -1
- package/src/summary/summarizerNode/summarizerNode.ts +3 -12
- package/src/summary/summarizerNode/summarizerNodeUtils.ts +2 -3
- package/src/summary/summarizerNode/summarizerNodeWithGc.ts +1 -10
- package/src/summary/summarizerTypes.ts +6 -5
- package/src/summary/summaryCollection.ts +2 -2
- package/src/summary/summaryFormat.ts +30 -4
- package/src/summary/summaryGenerator.ts +20 -9
- package/src/summary/summaryManager.ts +6 -3
- package/dist/deltaManagerSummarizerProxy.d.ts +0 -44
- package/dist/deltaManagerSummarizerProxy.d.ts.map +0 -1
- package/dist/deltaManagerSummarizerProxy.js.map +0 -1
- package/lib/deltaManagerSummarizerProxy.d.ts +0 -44
- package/lib/deltaManagerSummarizerProxy.d.ts.map +0 -1
- package/lib/deltaManagerSummarizerProxy.js.map +0 -1
package/src/dataStore.ts
CHANGED
|
@@ -4,15 +4,18 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import { AttachState } from "@fluidframework/container-definitions";
|
|
7
|
-
import { FluidObject,
|
|
7
|
+
import { FluidObject, type IFluidHandleInternal } from "@fluidframework/core-interfaces/internal";
|
|
8
8
|
import { assert, unreachableCase } from "@fluidframework/core-utils/internal";
|
|
9
9
|
import {
|
|
10
10
|
AliasResult,
|
|
11
11
|
IDataStore,
|
|
12
12
|
IFluidDataStoreChannel,
|
|
13
13
|
} from "@fluidframework/runtime-definitions/internal";
|
|
14
|
-
import {
|
|
15
|
-
|
|
14
|
+
import {
|
|
15
|
+
ITelemetryLoggerExt,
|
|
16
|
+
TelemetryDataTag,
|
|
17
|
+
UsageError,
|
|
18
|
+
} from "@fluidframework/telemetry-utils/internal";
|
|
16
19
|
|
|
17
20
|
import { ChannelCollection } from "./channelCollection.js";
|
|
18
21
|
import { ContainerMessageType } from "./messageTypes.js";
|
|
@@ -166,7 +169,7 @@ class DataStore implements IDataStore {
|
|
|
166
169
|
/**
|
|
167
170
|
* {@inheritDoc @fluidframework/runtime-definitions#IDataStore.entryPoint}
|
|
168
171
|
*/
|
|
169
|
-
get entryPoint():
|
|
172
|
+
get entryPoint(): IFluidHandleInternal<FluidObject> {
|
|
170
173
|
return this.fluidDataStoreChannel.entryPoint;
|
|
171
174
|
}
|
|
172
175
|
|
package/src/dataStoreContext.ts
CHANGED
|
@@ -4,19 +4,26 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import { TypedEventEmitter } from "@fluid-internal/client-utils";
|
|
7
|
-
import { AttachState, IAudience
|
|
7
|
+
import { AttachState, IAudience } from "@fluidframework/container-definitions";
|
|
8
|
+
import { IDeltaManager } from "@fluidframework/container-definitions/internal";
|
|
8
9
|
import {
|
|
9
10
|
FluidObject,
|
|
10
11
|
IDisposable,
|
|
11
|
-
IEvent,
|
|
12
|
-
IFluidHandle,
|
|
13
12
|
IRequest,
|
|
14
13
|
IResponse,
|
|
15
14
|
ITelemetryBaseProperties,
|
|
16
15
|
} from "@fluidframework/core-interfaces";
|
|
16
|
+
import { type IEvent, type IFluidHandleInternal } from "@fluidframework/core-interfaces/internal";
|
|
17
17
|
import { assert, LazyPromise, unreachableCase } from "@fluidframework/core-utils/internal";
|
|
18
|
-
import {
|
|
19
|
-
|
|
18
|
+
import {
|
|
19
|
+
IDocumentStorageService,
|
|
20
|
+
type ISnapshot,
|
|
21
|
+
} from "@fluidframework/driver-definitions/internal";
|
|
22
|
+
import {
|
|
23
|
+
BlobTreeEntry,
|
|
24
|
+
isInstanceOfISnapshot,
|
|
25
|
+
readAndParse,
|
|
26
|
+
} from "@fluidframework/driver-utils/internal";
|
|
20
27
|
import type { IIdCompressor } from "@fluidframework/id-compressor";
|
|
21
28
|
import {
|
|
22
29
|
IClientDetails,
|
|
@@ -52,7 +59,11 @@ import {
|
|
|
52
59
|
channelsTreeName,
|
|
53
60
|
gcDataBlobKey,
|
|
54
61
|
} from "@fluidframework/runtime-definitions/internal";
|
|
55
|
-
import {
|
|
62
|
+
import {
|
|
63
|
+
addBlobToSummary,
|
|
64
|
+
isSnapshotFetchRequiredForLoadingGroupId,
|
|
65
|
+
toFluidHandleInternal,
|
|
66
|
+
} from "@fluidframework/runtime-utils/internal";
|
|
56
67
|
import {
|
|
57
68
|
DataCorruptionError,
|
|
58
69
|
DataProcessingError,
|
|
@@ -67,6 +78,7 @@ import {
|
|
|
67
78
|
|
|
68
79
|
import { detectOutboundRoutesViaDDSKey, sendGCUnexpectedUsageEvent } from "./gc/index.js";
|
|
69
80
|
import {
|
|
81
|
+
// eslint-disable-next-line import/no-deprecated
|
|
70
82
|
ReadFluidDataStoreAttributes,
|
|
71
83
|
WriteFluidDataStoreAttributes,
|
|
72
84
|
dataStoreAttributesBlobName,
|
|
@@ -164,7 +176,7 @@ export interface ILocalDetachedFluidDataStoreContextProps extends ILocalFluidDat
|
|
|
164
176
|
* @internal
|
|
165
177
|
*/
|
|
166
178
|
export interface IRemoteFluidDataStoreContextProps extends IFluidDataStoreContextProps {
|
|
167
|
-
readonly
|
|
179
|
+
readonly snapshot: ISnapshotTree | ISnapshot | undefined;
|
|
168
180
|
}
|
|
169
181
|
|
|
170
182
|
// back-compat: To be removed in the future.
|
|
@@ -219,6 +231,7 @@ export abstract class FluidDataStoreContext
|
|
|
219
231
|
return this._containerRuntime;
|
|
220
232
|
}
|
|
221
233
|
|
|
234
|
+
// back-compat, to be removed in 2.0
|
|
222
235
|
public ensureNoDataModelChanges<T>(callback: () => T): T {
|
|
223
236
|
return this.parentContext.ensureNoDataModelChanges(callback);
|
|
224
237
|
}
|
|
@@ -721,11 +734,17 @@ export abstract class FluidDataStoreContext
|
|
|
721
734
|
* @param srcHandle - The handle of the node that added the reference.
|
|
722
735
|
* @param outboundHandle - The handle of the outbound node that is referenced.
|
|
723
736
|
*/
|
|
724
|
-
public addedGCOutboundReference(
|
|
737
|
+
public addedGCOutboundReference(
|
|
738
|
+
srcHandle: IFluidHandleInternal,
|
|
739
|
+
outboundHandle: IFluidHandleInternal,
|
|
740
|
+
): void {
|
|
725
741
|
// By default, skip this call since the ContainerRuntime will detect the outbound route directly.
|
|
726
742
|
if (this.mc.config.getBoolean(detectOutboundRoutesViaDDSKey) === true) {
|
|
727
743
|
// Note: The ContainerRuntime code will check this same setting to avoid double counting.
|
|
728
|
-
this.parentContext.addedGCOutboundReference?.(
|
|
744
|
+
this.parentContext.addedGCOutboundReference?.(
|
|
745
|
+
toFluidHandleInternal(srcHandle),
|
|
746
|
+
toFluidHandleInternal(outboundHandle),
|
|
747
|
+
);
|
|
729
748
|
}
|
|
730
749
|
}
|
|
731
750
|
|
|
@@ -1053,7 +1072,7 @@ export abstract class FluidDataStoreContext
|
|
|
1053
1072
|
public async uploadBlob(
|
|
1054
1073
|
blob: ArrayBufferLike,
|
|
1055
1074
|
signal?: AbortSignal,
|
|
1056
|
-
): Promise<
|
|
1075
|
+
): Promise<IFluidHandleInternal<ArrayBufferLike>> {
|
|
1057
1076
|
return this.parentContext.uploadBlob(blob, signal);
|
|
1058
1077
|
}
|
|
1059
1078
|
}
|
|
@@ -1061,23 +1080,28 @@ export abstract class FluidDataStoreContext
|
|
|
1061
1080
|
/** @internal */
|
|
1062
1081
|
export class RemoteFluidDataStoreContext extends FluidDataStoreContext {
|
|
1063
1082
|
// Tells whether we need to fetch the snapshot before use. This is to support Data Virtualization.
|
|
1064
|
-
private snapshotFetchRequired: boolean;
|
|
1083
|
+
private snapshotFetchRequired: boolean | undefined;
|
|
1065
1084
|
private readonly runtime: IContainerRuntimeBase;
|
|
1085
|
+
private readonly blobContents: Map<string, ArrayBuffer> | undefined;
|
|
1066
1086
|
|
|
1067
1087
|
constructor(props: IRemoteFluidDataStoreContextProps) {
|
|
1068
1088
|
super(props, true /* existing */, false /* isLocalDataStore */, () => {
|
|
1069
1089
|
throw new Error("Already attached");
|
|
1070
1090
|
});
|
|
1071
1091
|
|
|
1072
|
-
this._baseSnapshot = props.snapshotTree;
|
|
1073
|
-
this.snapshotFetchRequired = !!props.snapshotTree?.omitted;
|
|
1074
1092
|
this.runtime = props.parentContext.containerRuntime;
|
|
1075
|
-
if (props.
|
|
1076
|
-
this.
|
|
1093
|
+
if (isInstanceOfISnapshot(props.snapshot)) {
|
|
1094
|
+
this.blobContents = props.snapshot.blobContents;
|
|
1095
|
+
this._baseSnapshot = props.snapshot.snapshotTree;
|
|
1096
|
+
} else {
|
|
1097
|
+
this._baseSnapshot = props.snapshot;
|
|
1098
|
+
}
|
|
1099
|
+
if (this._baseSnapshot !== undefined) {
|
|
1100
|
+
this.summarizerNode.updateBaseSummaryState(this._baseSnapshot);
|
|
1077
1101
|
}
|
|
1078
1102
|
}
|
|
1079
1103
|
|
|
1080
|
-
/*
|
|
1104
|
+
/*
|
|
1081
1105
|
This API should not be called for RemoteFluidDataStoreContext. But here is one scenario where it's not the case:
|
|
1082
1106
|
The scenario (hit by stashedOps.spec.ts, "resends attach op" UT is the following (as far as I understand):
|
|
1083
1107
|
1. data store is being attached in attached container
|
|
@@ -1092,6 +1116,21 @@ export class RemoteFluidDataStoreContext extends FluidDataStoreContext {
|
|
|
1092
1116
|
private readonly initialSnapshotDetailsP = new LazyPromise<ISnapshotDetails>(async () => {
|
|
1093
1117
|
// Sequence number of the snapshot.
|
|
1094
1118
|
let sequenceNumber: number | undefined;
|
|
1119
|
+
// Check whether we need to fetch the snapshot first to load.
|
|
1120
|
+
if (this.snapshotFetchRequired === undefined && this._baseSnapshot?.groupId !== undefined) {
|
|
1121
|
+
assert(
|
|
1122
|
+
this.blobContents !== undefined,
|
|
1123
|
+
0x97a /* Blob contents should be present to evaluate */,
|
|
1124
|
+
);
|
|
1125
|
+
assert(
|
|
1126
|
+
this._baseSnapshot !== undefined,
|
|
1127
|
+
0x97b /* snapshotTree should be present to evaluate */,
|
|
1128
|
+
);
|
|
1129
|
+
this.snapshotFetchRequired = isSnapshotFetchRequiredForLoadingGroupId(
|
|
1130
|
+
this._baseSnapshot,
|
|
1131
|
+
this.blobContents,
|
|
1132
|
+
);
|
|
1133
|
+
}
|
|
1095
1134
|
if (this.snapshotFetchRequired) {
|
|
1096
1135
|
assert(
|
|
1097
1136
|
this.loadingGroupId !== undefined,
|
|
@@ -1110,6 +1149,7 @@ export class RemoteFluidDataStoreContext extends FluidDataStoreContext {
|
|
|
1110
1149
|
|
|
1111
1150
|
if (!!tree && tree.blobs[dataStoreAttributesBlobName] !== undefined) {
|
|
1112
1151
|
// Need to get through snapshot and use that to populate extraBlobs
|
|
1152
|
+
// eslint-disable-next-line import/no-deprecated
|
|
1113
1153
|
const attributes = await readAndParse<ReadFluidDataStoreAttributes>(
|
|
1114
1154
|
this.storage,
|
|
1115
1155
|
tree.blobs[dataStoreAttributesBlobName],
|
|
@@ -1286,6 +1326,7 @@ export class LocalFluidDataStoreContextBase extends FluidDataStoreContext {
|
|
|
1286
1326
|
|
|
1287
1327
|
private readonly initialSnapshotDetailsP = new LazyPromise<ISnapshotDetails>(async () => {
|
|
1288
1328
|
let snapshot = this.snapshotTree;
|
|
1329
|
+
// eslint-disable-next-line import/no-deprecated
|
|
1289
1330
|
let attributes: ReadFluidDataStoreAttributes;
|
|
1290
1331
|
let isRootDataStore = false;
|
|
1291
1332
|
if (snapshot !== undefined) {
|
package/src/dataStoreContexts.ts
CHANGED
|
@@ -5,8 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
import { IDisposable, ITelemetryBaseLogger } from "@fluidframework/core-interfaces";
|
|
7
7
|
import { assert, Deferred, Lazy } from "@fluidframework/core-utils/internal";
|
|
8
|
-
import { ITelemetryLoggerExt } from "@fluidframework/telemetry-utils";
|
|
9
|
-
import { createChildLogger } from "@fluidframework/telemetry-utils/internal";
|
|
8
|
+
import { ITelemetryLoggerExt, createChildLogger } from "@fluidframework/telemetry-utils/internal";
|
|
10
9
|
|
|
11
10
|
import { FluidDataStoreContext, LocalFluidDataStoreContext } from "./dataStoreContext.js";
|
|
12
11
|
|
|
@@ -11,9 +11,9 @@ import type {
|
|
|
11
11
|
IDeltaQueue,
|
|
12
12
|
IDeltaSender,
|
|
13
13
|
ReadOnlyInfo,
|
|
14
|
-
} from "@fluidframework/container-definitions";
|
|
14
|
+
} from "@fluidframework/container-definitions/internal";
|
|
15
15
|
import type { IErrorBase } from "@fluidframework/core-interfaces";
|
|
16
|
-
import type { IAnyDriverError } from "@fluidframework/driver-definitions";
|
|
16
|
+
import type { IAnyDriverError } from "@fluidframework/driver-definitions/internal";
|
|
17
17
|
import {
|
|
18
18
|
IClientConfiguration,
|
|
19
19
|
IClientDetails,
|
|
@@ -23,13 +23,15 @@ import {
|
|
|
23
23
|
} from "@fluidframework/protocol-definitions";
|
|
24
24
|
|
|
25
25
|
import { summarizerClientType } from "./summary/index.js";
|
|
26
|
+
import type { PendingStateManager } from "./pendingStateManager.js";
|
|
26
27
|
|
|
27
28
|
/**
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
29
|
+
* Base class for DeltaManager proxy that proxy's access to the real DeltaManager.
|
|
30
|
+
*
|
|
31
|
+
* This class allows us to build proxy functionality without actually having to implement all the methods
|
|
32
|
+
* of the DeltaManager.
|
|
31
33
|
*/
|
|
32
|
-
export class
|
|
34
|
+
export abstract class BaseDeltaManagerProxy
|
|
33
35
|
extends TypedEventEmitter<IDeltaManagerEvents>
|
|
34
36
|
implements IDeltaManager<ISequencedDocumentMessage, IDocumentMessage>
|
|
35
37
|
{
|
|
@@ -90,35 +92,20 @@ export class DeltaManagerSummarizerProxy
|
|
|
90
92
|
}
|
|
91
93
|
|
|
92
94
|
public get active(): boolean {
|
|
93
|
-
|
|
94
|
-
// except for the SummarizeOp which is generated by the runtime.
|
|
95
|
-
return !this.isSummarizerClient && this.deltaManager.active;
|
|
95
|
+
return this.deltaManager.active;
|
|
96
96
|
}
|
|
97
97
|
|
|
98
98
|
public get readOnlyInfo(): ReadOnlyInfo {
|
|
99
|
-
// Summarizer clients should be read-only as far as the runtime and layers below are concerned. There shouldn't
|
|
100
|
-
// be any local changes (writes) in the summarizer except for the summarize op which is generated by the runtime.
|
|
101
|
-
if (this.isSummarizerClient) {
|
|
102
|
-
return {
|
|
103
|
-
readonly: true,
|
|
104
|
-
forced: false,
|
|
105
|
-
permissions: undefined,
|
|
106
|
-
storageOnly: false,
|
|
107
|
-
};
|
|
108
|
-
}
|
|
109
99
|
return this.deltaManager.readOnlyInfo;
|
|
110
100
|
}
|
|
111
101
|
|
|
112
|
-
private readonly isSummarizerClient: boolean;
|
|
113
|
-
|
|
114
102
|
constructor(
|
|
115
|
-
|
|
103
|
+
protected readonly deltaManager: IDeltaManager<ISequencedDocumentMessage, IDocumentMessage>,
|
|
116
104
|
) {
|
|
117
105
|
super();
|
|
118
106
|
|
|
119
107
|
// We are expecting this class to have many listeners, so we suppress noisy "MaxListenersExceededWarning" logging.
|
|
120
108
|
super.setMaxListeners(0);
|
|
121
|
-
this.isSummarizerClient = this.deltaManager.clientDetails.type === summarizerClientType;
|
|
122
109
|
|
|
123
110
|
this.deltaManager.on("prepareSend", this.onPrepareSend);
|
|
124
111
|
this.deltaManager.on("submitOp", this.onSubmitOp);
|
|
@@ -153,7 +140,10 @@ export class DeltaManagerSummarizerProxy
|
|
|
153
140
|
private readonly onSubmitOp = (message: IDocumentMessage): void => {
|
|
154
141
|
this.emit("submitOp", message);
|
|
155
142
|
};
|
|
156
|
-
|
|
143
|
+
protected readonly onOp = (
|
|
144
|
+
message: ISequencedDocumentMessage,
|
|
145
|
+
processingTime: number,
|
|
146
|
+
): void => {
|
|
157
147
|
this.emit("op", message, processingTime);
|
|
158
148
|
};
|
|
159
149
|
private readonly onPong = (latency: number): void => {
|
|
@@ -172,3 +162,87 @@ export class DeltaManagerSummarizerProxy
|
|
|
172
162
|
this.emit("readonly", readonly, readonlyConnectionReason);
|
|
173
163
|
};
|
|
174
164
|
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Proxy to the real IDeltaManager for restricting certain access to layers below container runtime in summarizer clients:
|
|
168
|
+
* - Summarizer client should be read-only to layers below the container runtime to restrict local changes.
|
|
169
|
+
* - Summarizer client should not be active to layers below the container runtime to restrict local changes.
|
|
170
|
+
*/
|
|
171
|
+
export class DeltaManagerSummarizerProxy extends BaseDeltaManagerProxy {
|
|
172
|
+
public get active(): boolean {
|
|
173
|
+
// Summarize clients should not be active. There shouldn't be any local changes (writes) in the summarizer
|
|
174
|
+
// except for the SummarizeOp which is generated by the runtime.
|
|
175
|
+
return !this.isSummarizerClient && this.deltaManager.active;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
public get readOnlyInfo(): ReadOnlyInfo {
|
|
179
|
+
// Summarizer clients should be read-only as far as the runtime and layers below are concerned. There shouldn't
|
|
180
|
+
// be any local changes (writes) in the summarizer except for the summarize op which is generated by the runtime.
|
|
181
|
+
if (this.isSummarizerClient) {
|
|
182
|
+
return {
|
|
183
|
+
readonly: true,
|
|
184
|
+
forced: false,
|
|
185
|
+
permissions: undefined,
|
|
186
|
+
storageOnly: false,
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
return this.deltaManager.readOnlyInfo;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
private readonly isSummarizerClient: boolean;
|
|
193
|
+
|
|
194
|
+
constructor(
|
|
195
|
+
protected readonly deltaManager: IDeltaManager<ISequencedDocumentMessage, IDocumentMessage>,
|
|
196
|
+
) {
|
|
197
|
+
super(deltaManager);
|
|
198
|
+
this.isSummarizerClient = this.deltaManager.clientDetails.type === summarizerClientType;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
export class DeltaManagerPendingOpsProxy extends BaseDeltaManagerProxy {
|
|
203
|
+
public get minimumSequenceNumber(): number {
|
|
204
|
+
const minPendingSeqNum = this.pendingStateManager.minimumPendingMessageSequenceNumber;
|
|
205
|
+
// There is a chance that minPendingSeqNum is greater than minimum sequence number.
|
|
206
|
+
// minPendingSeqNum is based on the pending ops, so it's based on ref seq number.
|
|
207
|
+
// Imagine an op has just be sent while there's another client that has been lagging behind,
|
|
208
|
+
// it will likely have a ref seq number greater than the minimum seq number.
|
|
209
|
+
if (
|
|
210
|
+
minPendingSeqNum !== undefined &&
|
|
211
|
+
minPendingSeqNum < this.deltaManager.minimumSequenceNumber
|
|
212
|
+
) {
|
|
213
|
+
return minPendingSeqNum;
|
|
214
|
+
}
|
|
215
|
+
return this.deltaManager.minimumSequenceNumber;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
public get lastMessage() {
|
|
219
|
+
if (this.deltaManager.lastMessage === undefined) {
|
|
220
|
+
return this.deltaManager.lastMessage;
|
|
221
|
+
}
|
|
222
|
+
return {
|
|
223
|
+
...this.deltaManager.lastMessage,
|
|
224
|
+
minimumSequenceNumber: this.minimumSequenceNumber,
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
protected readonly onOp = (
|
|
229
|
+
message: ISequencedDocumentMessage,
|
|
230
|
+
processingTime: number,
|
|
231
|
+
): void => {
|
|
232
|
+
const messageIntercept = {
|
|
233
|
+
...message,
|
|
234
|
+
minimumSequenceNumber: this.minimumSequenceNumber,
|
|
235
|
+
};
|
|
236
|
+
this.emit("op", messageIntercept, processingTime);
|
|
237
|
+
};
|
|
238
|
+
|
|
239
|
+
constructor(
|
|
240
|
+
protected readonly deltaManager: IDeltaManager<ISequencedDocumentMessage, IDocumentMessage>,
|
|
241
|
+
private readonly pendingStateManager: Pick<
|
|
242
|
+
PendingStateManager,
|
|
243
|
+
"minimumPendingMessageSequenceNumber"
|
|
244
|
+
>,
|
|
245
|
+
) {
|
|
246
|
+
super(deltaManager);
|
|
247
|
+
}
|
|
248
|
+
}
|
package/src/deltaScheduler.ts
CHANGED
|
@@ -4,10 +4,9 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import { performance } from "@fluid-internal/client-utils";
|
|
7
|
-
import { IDeltaManager } from "@fluidframework/container-definitions";
|
|
7
|
+
import { IDeltaManager } from "@fluidframework/container-definitions/internal";
|
|
8
8
|
import { IDocumentMessage, ISequencedDocumentMessage } from "@fluidframework/protocol-definitions";
|
|
9
|
-
import { ITelemetryLoggerExt } from "@fluidframework/telemetry-utils";
|
|
10
|
-
import { formatTick } from "@fluidframework/telemetry-utils/internal";
|
|
9
|
+
import { ITelemetryLoggerExt, formatTick } from "@fluidframework/telemetry-utils/internal";
|
|
11
10
|
|
|
12
11
|
/**
|
|
13
12
|
* DeltaScheduler is responsible for the scheduling of inbound delta queue in cases where there
|
|
@@ -12,8 +12,8 @@ import {
|
|
|
12
12
|
gcTreeKey,
|
|
13
13
|
} from "@fluidframework/runtime-definitions/internal";
|
|
14
14
|
import { createResponseError, responseToException } from "@fluidframework/runtime-utils/internal";
|
|
15
|
-
import { ITelemetryLoggerExt } from "@fluidframework/telemetry-utils";
|
|
16
15
|
import {
|
|
16
|
+
ITelemetryLoggerExt,
|
|
17
17
|
DataProcessingError,
|
|
18
18
|
MonitoringContext,
|
|
19
19
|
PerformanceEvent,
|
package/src/gc/gcDefinitions.ts
CHANGED
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
ISummarizeResult,
|
|
13
13
|
} from "@fluidframework/runtime-definitions/internal";
|
|
14
14
|
import { ReadAndParseBlob } from "@fluidframework/runtime-utils/internal";
|
|
15
|
-
import { ITelemetryLoggerExt } from "@fluidframework/telemetry-utils";
|
|
15
|
+
import { ITelemetryLoggerExt } from "@fluidframework/telemetry-utils/internal";
|
|
16
16
|
|
|
17
17
|
import { RuntimeHeaderData } from "../containerRuntime.js";
|
|
18
18
|
import { ContainerRuntimeGCMessage } from "../messageTypes.js";
|
package/src/gc/gcTelemetry.ts
CHANGED
|
@@ -5,13 +5,11 @@
|
|
|
5
5
|
|
|
6
6
|
import { IGarbageCollectionData } from "@fluidframework/runtime-definitions";
|
|
7
7
|
import {
|
|
8
|
-
type ITelemetryGenericEventExt,
|
|
9
8
|
ITelemetryLoggerExt,
|
|
10
|
-
} from "@fluidframework/telemetry-utils";
|
|
11
|
-
import {
|
|
12
9
|
MonitoringContext,
|
|
13
10
|
generateStack,
|
|
14
11
|
tagCodeArtifacts,
|
|
12
|
+
type ITelemetryGenericEventExt,
|
|
15
13
|
} from "@fluidframework/telemetry-utils/internal";
|
|
16
14
|
|
|
17
15
|
import type { Tagged } from "@fluidframework/core-interfaces";
|
package/src/index.ts
CHANGED
|
@@ -107,6 +107,11 @@ export {
|
|
|
107
107
|
DocumentsSchemaController,
|
|
108
108
|
IDocumentSchemaChangeMessage,
|
|
109
109
|
IDocumentSchemaFeatures,
|
|
110
|
+
ReadFluidDataStoreAttributes,
|
|
111
|
+
IFluidDataStoreAttributes0,
|
|
112
|
+
IFluidDataStoreAttributes1,
|
|
113
|
+
IFluidDataStoreAttributes2,
|
|
114
|
+
OmitAttributesVersions,
|
|
110
115
|
} from "./summary/index.js";
|
|
111
116
|
export { IChunkedOp, unpackRuntimeMessage } from "./opLifecycle/index.js";
|
|
112
117
|
export { ChannelCollection } from "./channelCollection.js";
|
package/src/messageTypes.ts
CHANGED
|
@@ -175,11 +175,13 @@ export type InboundContainerRuntimeMessage =
|
|
|
175
175
|
| UnknownContainerRuntimeMessage
|
|
176
176
|
| ContainerRuntimeDocumentSchemaMessage;
|
|
177
177
|
|
|
178
|
-
/**
|
|
178
|
+
/**
|
|
179
|
+
* A {@link TypedContainerRuntimeMessage} that has been generated by the container runtime but is not yet being sent to the server.
|
|
180
|
+
* These are messages generated by the local runtime, before the outbox's op virtualization step.
|
|
181
|
+
*/
|
|
179
182
|
export type LocalContainerRuntimeMessage =
|
|
180
183
|
| ContainerRuntimeDataStoreOpMessage
|
|
181
184
|
| OutboundContainerRuntimeAttachMessage
|
|
182
|
-
| ContainerRuntimeChunkedOpMessage
|
|
183
185
|
| ContainerRuntimeBlobAttachMessage
|
|
184
186
|
| ContainerRuntimeRejoinMessage
|
|
185
187
|
| ContainerRuntimeAliasMessage
|
package/src/metadata.ts
CHANGED
|
@@ -19,8 +19,8 @@ export interface IBlobMetadata {
|
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
/**
|
|
22
|
-
*
|
|
22
|
+
* ContainerRuntime needs to know if this is a replayed savedOp as those need to be skipped in stashed ops scenarios.
|
|
23
23
|
*/
|
|
24
|
-
export interface
|
|
24
|
+
export interface ISavedOpMetadata {
|
|
25
25
|
savedOp?: boolean;
|
|
26
26
|
}
|
|
@@ -339,19 +339,19 @@ stateDiagram-v2
|
|
|
339
339
|
state "Store original (uncompressed, unchunked, ungrouped) batch locally" as store
|
|
340
340
|
state if_compression <<choice>>
|
|
341
341
|
[*] --> ContainerRuntime.submit
|
|
342
|
-
ContainerRuntime.submit --> outbox.
|
|
342
|
+
ContainerRuntime.submit --> outbox.submitIdAllocation
|
|
343
343
|
ContainerRuntime.submit --> outbox.submitBlobAttach
|
|
344
344
|
ContainerRuntime.submit --> outbox.submit
|
|
345
345
|
outbox.submit --> scheduleFlush
|
|
346
|
-
outbox.
|
|
346
|
+
outbox.submitIdAllocation --> scheduleFlush
|
|
347
347
|
outbox.submitBlobAttach --> scheduleFlush
|
|
348
348
|
scheduleFlush --> jsTurn
|
|
349
349
|
jsTurn --> flush
|
|
350
350
|
flush --> outbox.flushInternalMain
|
|
351
|
-
flush --> outbox.
|
|
351
|
+
flush --> outbox.flushInternalIdAllocation
|
|
352
352
|
flush --> outbox.flushInternalBlobAttach
|
|
353
353
|
outbox.flushInternalMain --> flushInternal
|
|
354
|
-
outbox.
|
|
354
|
+
outbox.flushInternalIdAllocation --> flushInternal
|
|
355
355
|
outbox.flushInternalBlobAttach --> flushInternal
|
|
356
356
|
flushInternal --> ContainerRuntime.reSubmit: if batch has reentrant ops and should group
|
|
357
357
|
ContainerRuntime.reSubmit --> flushInternal
|
|
@@ -9,8 +9,12 @@ import { BatchMessage, IBatch, IBatchCheckpoint } from "./definitions.js";
|
|
|
9
9
|
|
|
10
10
|
export interface IBatchManagerOptions {
|
|
11
11
|
readonly hardLimit: number;
|
|
12
|
-
readonly softLimit?: number;
|
|
13
12
|
readonly compressionOptions?: ICompressionRuntimeOptions;
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* If true, the outbox is allowed to rebase the batch during flushing.
|
|
16
|
+
*/
|
|
17
|
+
readonly canRebase: boolean;
|
|
14
18
|
}
|
|
15
19
|
|
|
16
20
|
export interface BatchSequenceNumbers {
|
|
@@ -72,19 +76,6 @@ export class BatchManager {
|
|
|
72
76
|
// initially stored as base64, and that requires only 2 extra escape characters.
|
|
73
77
|
const socketMessageSize = contentSize + opOverhead * opCount;
|
|
74
78
|
|
|
75
|
-
// If we were provided soft limit, check for exceeding it.
|
|
76
|
-
// But only if we have any ops, as the intention here is to flush existing ops (on exceeding this limit)
|
|
77
|
-
// and start over. That's not an option if we have no ops.
|
|
78
|
-
// If compression is enabled, the soft and hard limit are ignored and the message will be pushed anyways.
|
|
79
|
-
// Cases where the message is still too large will be handled by the maxConsecutiveReconnects path.
|
|
80
|
-
if (
|
|
81
|
-
this.options.softLimit !== undefined &&
|
|
82
|
-
this.length > 0 &&
|
|
83
|
-
socketMessageSize >= this.options.softLimit
|
|
84
|
-
) {
|
|
85
|
-
return false;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
79
|
if (socketMessageSize >= this.options.hardLimit) {
|
|
89
80
|
return false;
|
|
90
81
|
}
|
|
@@ -89,11 +89,9 @@ export function getLongStack<T>(action: () => T, length: number = 50): T {
|
|
|
89
89
|
|
|
90
90
|
export class Outbox {
|
|
91
91
|
private readonly mc: MonitoringContext;
|
|
92
|
-
private readonly attachFlowBatch: BatchManager;
|
|
93
92
|
private readonly mainBatch: BatchManager;
|
|
94
93
|
private readonly blobAttachBatch: BatchManager;
|
|
95
94
|
private readonly idAllocationBatch: BatchManager;
|
|
96
|
-
private readonly defaultAttachFlowSoftLimitInBytes = 320 * 1024;
|
|
97
95
|
private batchRebasesToReport = 5;
|
|
98
96
|
private rebasing = false;
|
|
99
97
|
|
|
@@ -113,21 +111,14 @@ export class Outbox {
|
|
|
113
111
|
Number.POSITIVE_INFINITY;
|
|
114
112
|
// We need to allow infinite size batches if we enable compression
|
|
115
113
|
const hardLimit = isCompressionEnabled ? Infinity : this.params.config.maxBatchSizeInBytes;
|
|
116
|
-
const softLimit = isCompressionEnabled ? Infinity : this.defaultAttachFlowSoftLimitInBytes;
|
|
117
114
|
|
|
118
|
-
this.
|
|
119
|
-
this.
|
|
120
|
-
this.
|
|
121
|
-
this.idAllocationBatch = new BatchManager({ hardLimit });
|
|
115
|
+
this.mainBatch = new BatchManager({ hardLimit, canRebase: true });
|
|
116
|
+
this.blobAttachBatch = new BatchManager({ hardLimit, canRebase: true });
|
|
117
|
+
this.idAllocationBatch = new BatchManager({ hardLimit, canRebase: false });
|
|
122
118
|
}
|
|
123
119
|
|
|
124
120
|
public get messageCount(): number {
|
|
125
|
-
return
|
|
126
|
-
this.attachFlowBatch.length +
|
|
127
|
-
this.mainBatch.length +
|
|
128
|
-
this.blobAttachBatch.length +
|
|
129
|
-
this.idAllocationBatch.length
|
|
130
|
-
);
|
|
121
|
+
return this.mainBatch.length + this.blobAttachBatch.length + this.idAllocationBatch.length;
|
|
131
122
|
}
|
|
132
123
|
|
|
133
124
|
public get isEmpty(): boolean {
|
|
@@ -142,13 +133,11 @@ export class Outbox {
|
|
|
142
133
|
*/
|
|
143
134
|
private maybeFlushPartialBatch() {
|
|
144
135
|
const mainBatchSeqNums = this.mainBatch.sequenceNumbers;
|
|
145
|
-
const attachFlowBatchSeqNums = this.attachFlowBatch.sequenceNumbers;
|
|
146
136
|
const blobAttachSeqNums = this.blobAttachBatch.sequenceNumbers;
|
|
147
137
|
const idAllocSeqNums = this.idAllocationBatch.sequenceNumbers;
|
|
148
138
|
assert(
|
|
149
139
|
this.params.config.disablePartialFlush ||
|
|
150
|
-
(sequenceNumbersMatch(mainBatchSeqNums,
|
|
151
|
-
sequenceNumbersMatch(mainBatchSeqNums, blobAttachSeqNums) &&
|
|
140
|
+
(sequenceNumbersMatch(mainBatchSeqNums, blobAttachSeqNums) &&
|
|
152
141
|
sequenceNumbersMatch(mainBatchSeqNums, idAllocSeqNums)),
|
|
153
142
|
0x58d /* Reference sequence numbers from both batches must be in sync */,
|
|
154
143
|
);
|
|
@@ -157,7 +146,6 @@ export class Outbox {
|
|
|
157
146
|
|
|
158
147
|
if (
|
|
159
148
|
sequenceNumbersMatch(mainBatchSeqNums, currentSequenceNumbers) &&
|
|
160
|
-
sequenceNumbersMatch(attachFlowBatchSeqNums, currentSequenceNumbers) &&
|
|
161
149
|
sequenceNumbersMatch(blobAttachSeqNums, currentSequenceNumbers) &&
|
|
162
150
|
sequenceNumbersMatch(idAllocSeqNums, currentSequenceNumbers)
|
|
163
151
|
) {
|
|
@@ -172,8 +160,6 @@ export class Outbox {
|
|
|
172
160
|
eventName: "ReferenceSequenceNumberMismatch",
|
|
173
161
|
mainReferenceSequenceNumber: mainBatchSeqNums.referenceSequenceNumber,
|
|
174
162
|
mainClientSequenceNumber: mainBatchSeqNums.clientSequenceNumber,
|
|
175
|
-
attachReferenceSequenceNumber: attachFlowBatchSeqNums.referenceSequenceNumber,
|
|
176
|
-
attachClientSequenceNumber: attachFlowBatchSeqNums.clientSequenceNumber,
|
|
177
163
|
blobAttachReferenceSequenceNumber: blobAttachSeqNums.referenceSequenceNumber,
|
|
178
164
|
blobAttachClientSequenceNumber: blobAttachSeqNums.clientSequenceNumber,
|
|
179
165
|
currentReferenceSequenceNumber: currentSequenceNumbers.referenceSequenceNumber,
|
|
@@ -194,37 +180,6 @@ export class Outbox {
|
|
|
194
180
|
this.addMessageToBatchManager(this.mainBatch, message);
|
|
195
181
|
}
|
|
196
182
|
|
|
197
|
-
public submitAttach(message: BatchMessage) {
|
|
198
|
-
this.maybeFlushPartialBatch();
|
|
199
|
-
|
|
200
|
-
if (
|
|
201
|
-
!this.attachFlowBatch.push(
|
|
202
|
-
message,
|
|
203
|
-
this.isContextReentrant(),
|
|
204
|
-
this.params.getCurrentSequenceNumbers().clientSequenceNumber,
|
|
205
|
-
)
|
|
206
|
-
) {
|
|
207
|
-
// BatchManager has two limits - soft limit & hard limit. Soft limit is only engaged
|
|
208
|
-
// when queue is not empty.
|
|
209
|
-
// Flush queue & retry. Failure on retry would mean - single message is bigger than hard limit
|
|
210
|
-
this.flushInternal(this.attachFlowBatch);
|
|
211
|
-
|
|
212
|
-
this.addMessageToBatchManager(this.attachFlowBatch, message);
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
// If compression is enabled, we will always successfully receive
|
|
216
|
-
// attach ops and compress then send them at the next JS turn, regardless
|
|
217
|
-
// of the overall size of the accumulated ops in the batch.
|
|
218
|
-
// However, it is more efficient to flush these ops faster, preferably
|
|
219
|
-
// after they reach a size which would benefit from compression.
|
|
220
|
-
if (
|
|
221
|
-
this.attachFlowBatch.contentSizeInBytes >=
|
|
222
|
-
this.params.config.compressionOptions.minimumBatchSizeInBytes
|
|
223
|
-
) {
|
|
224
|
-
this.flushInternal(this.attachFlowBatch);
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
|
|
228
183
|
public submitBlobAttach(message: BatchMessage) {
|
|
229
184
|
this.maybeFlushPartialBatch();
|
|
230
185
|
|
|
@@ -303,7 +258,6 @@ export class Outbox {
|
|
|
303
258
|
|
|
304
259
|
private flushAll() {
|
|
305
260
|
this.flushInternal(this.idAllocationBatch);
|
|
306
|
-
this.flushInternal(this.attachFlowBatch);
|
|
307
261
|
this.flushInternal(this.blobAttachBatch, true /* disableGroupedBatching */);
|
|
308
262
|
this.flushInternal(this.mainBatch);
|
|
309
263
|
}
|
|
@@ -316,7 +270,7 @@ export class Outbox {
|
|
|
316
270
|
const rawBatch = batchManager.popBatch();
|
|
317
271
|
const shouldGroup =
|
|
318
272
|
!disableGroupedBatching && this.params.groupingManager.shouldGroup(rawBatch);
|
|
319
|
-
if (rawBatch.hasReentrantOps === true && shouldGroup) {
|
|
273
|
+
if (batchManager.options.canRebase && rawBatch.hasReentrantOps === true && shouldGroup) {
|
|
320
274
|
assert(!this.rebasing, 0x6fa /* A rebased batch should never have reentrant ops */);
|
|
321
275
|
// If a batch contains reentrant ops (ops created as a result from processing another op)
|
|
322
276
|
// it needs to be rebased so that we can ensure consistent reference sequence numbers
|
|
@@ -346,6 +300,7 @@ export class Outbox {
|
|
|
346
300
|
*/
|
|
347
301
|
private rebase(rawBatch: IBatch, batchManager: BatchManager) {
|
|
348
302
|
assert(!this.rebasing, 0x6fb /* Reentrancy */);
|
|
303
|
+
assert(batchManager.options.canRebase, "BatchManager does not support rebase");
|
|
349
304
|
|
|
350
305
|
this.rebasing = true;
|
|
351
306
|
for (const message of rawBatch.content) {
|
|
@@ -479,7 +434,6 @@ export class Outbox {
|
|
|
479
434
|
const mainBatch: IBatchCheckpoint = this.mainBatch.checkpoint();
|
|
480
435
|
return {
|
|
481
436
|
mainBatch,
|
|
482
|
-
attachFlowBatch: this.attachFlowBatch.checkpoint(),
|
|
483
437
|
blobAttachBatch: this.blobAttachBatch.checkpoint(),
|
|
484
438
|
};
|
|
485
439
|
}
|