@fluidframework/container-runtime 2.0.0-dev.2.2.0.111723 → 2.0.0-dev.2.3.0.115467
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/dist/blobManager.d.ts +20 -5
- package/dist/blobManager.d.ts.map +1 -1
- package/dist/blobManager.js +57 -15
- package/dist/blobManager.js.map +1 -1
- package/dist/containerRuntime.d.ts +16 -33
- package/dist/containerRuntime.d.ts.map +1 -1
- package/dist/containerRuntime.js +71 -219
- package/dist/containerRuntime.js.map +1 -1
- package/dist/dataStoreContext.js +2 -2
- package/dist/dataStoreContext.js.map +1 -1
- package/dist/dataStores.d.ts.map +1 -1
- package/dist/dataStores.js +2 -1
- package/dist/dataStores.js.map +1 -1
- package/dist/garbageCollection.d.ts +7 -16
- package/dist/garbageCollection.d.ts.map +1 -1
- package/dist/garbageCollection.js +41 -61
- package/dist/garbageCollection.js.map +1 -1
- package/dist/garbageCollectionConstants.d.ts +19 -0
- package/dist/garbageCollectionConstants.d.ts.map +1 -0
- package/dist/garbageCollectionConstants.js +34 -0
- package/dist/garbageCollectionConstants.js.map +1 -0
- package/dist/gcSweepReadyUsageDetection.js +2 -2
- package/dist/gcSweepReadyUsageDetection.js.map +1 -1
- package/dist/index.d.ts +4 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -6
- package/dist/index.js.map +1 -1
- package/dist/opLifecycle/batchManager.d.ts +30 -0
- package/dist/opLifecycle/batchManager.d.ts.map +1 -0
- package/dist/{batchManager.js → opLifecycle/batchManager.js} +17 -17
- package/dist/opLifecycle/batchManager.js.map +1 -0
- package/dist/opLifecycle/definitions.d.ts +40 -0
- package/dist/opLifecycle/definitions.d.ts.map +1 -0
- package/dist/opLifecycle/definitions.js +7 -0
- package/dist/opLifecycle/definitions.js.map +1 -0
- package/dist/opLifecycle/index.d.ts +12 -0
- package/dist/opLifecycle/index.d.ts.map +1 -0
- package/dist/opLifecycle/index.js +21 -0
- package/dist/opLifecycle/index.js.map +1 -0
- package/dist/{opCompressor.d.ts → opLifecycle/opCompressor.d.ts} +2 -2
- package/dist/opLifecycle/opCompressor.d.ts.map +1 -0
- package/dist/{opCompressor.js → opLifecycle/opCompressor.js} +16 -13
- package/dist/opLifecycle/opCompressor.js.map +1 -0
- package/dist/{opDecompressor.d.ts → opLifecycle/opDecompressor.d.ts} +0 -0
- package/dist/opLifecycle/opDecompressor.d.ts.map +1 -0
- package/dist/{opDecompressor.js → opLifecycle/opDecompressor.js} +5 -5
- package/dist/opLifecycle/opDecompressor.js.map +1 -0
- package/dist/opLifecycle/opSplitter.d.ts +17 -0
- package/dist/opLifecycle/opSplitter.d.ts.map +1 -0
- package/dist/opLifecycle/opSplitter.js +61 -0
- package/dist/opLifecycle/opSplitter.js.map +1 -0
- package/dist/opLifecycle/outbox.d.ts +47 -0
- package/dist/opLifecycle/outbox.d.ts.map +1 -0
- package/dist/opLifecycle/outbox.js +153 -0
- package/dist/opLifecycle/outbox.js.map +1 -0
- package/dist/opLifecycle/remoteMessageProcessor.d.ts +26 -0
- package/dist/opLifecycle/remoteMessageProcessor.d.ts.map +1 -0
- package/dist/opLifecycle/remoteMessageProcessor.js +81 -0
- package/dist/opLifecycle/remoteMessageProcessor.js.map +1 -0
- package/dist/packageVersion.d.ts +1 -1
- package/dist/packageVersion.js +1 -1
- package/dist/packageVersion.js.map +1 -1
- package/dist/summaryFormat.js +2 -2
- package/dist/summaryFormat.js.map +1 -1
- package/lib/blobManager.d.ts +20 -5
- package/lib/blobManager.d.ts.map +1 -1
- package/lib/blobManager.js +59 -17
- package/lib/blobManager.js.map +1 -1
- package/lib/containerRuntime.d.ts +16 -33
- package/lib/containerRuntime.d.ts.map +1 -1
- package/lib/containerRuntime.js +68 -215
- package/lib/containerRuntime.js.map +1 -1
- package/lib/dataStoreContext.js +1 -1
- package/lib/dataStoreContext.js.map +1 -1
- package/lib/dataStores.d.ts.map +1 -1
- package/lib/dataStores.js +2 -1
- package/lib/dataStores.js.map +1 -1
- package/lib/garbageCollection.d.ts +7 -16
- package/lib/garbageCollection.d.ts.map +1 -1
- package/lib/garbageCollection.js +19 -39
- package/lib/garbageCollection.js.map +1 -1
- package/lib/garbageCollectionConstants.d.ts +19 -0
- package/lib/garbageCollectionConstants.d.ts.map +1 -0
- package/lib/garbageCollectionConstants.js +31 -0
- package/lib/garbageCollectionConstants.js.map +1 -0
- package/lib/gcSweepReadyUsageDetection.js +1 -1
- package/lib/gcSweepReadyUsageDetection.js.map +1 -1
- package/lib/index.d.ts +4 -2
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +3 -2
- package/lib/index.js.map +1 -1
- package/lib/opLifecycle/batchManager.d.ts +30 -0
- package/lib/opLifecycle/batchManager.d.ts.map +1 -0
- package/lib/{batchManager.js → opLifecycle/batchManager.js} +17 -17
- package/lib/opLifecycle/batchManager.js.map +1 -0
- package/lib/opLifecycle/definitions.d.ts +40 -0
- package/lib/opLifecycle/definitions.d.ts.map +1 -0
- package/lib/opLifecycle/definitions.js +6 -0
- package/lib/opLifecycle/definitions.js.map +1 -0
- package/lib/opLifecycle/index.d.ts +12 -0
- package/lib/opLifecycle/index.d.ts.map +1 -0
- package/lib/opLifecycle/index.js +11 -0
- package/lib/opLifecycle/index.js.map +1 -0
- package/lib/{opCompressor.d.ts → opLifecycle/opCompressor.d.ts} +2 -2
- package/lib/opLifecycle/opCompressor.d.ts.map +1 -0
- package/lib/{opCompressor.js → opLifecycle/opCompressor.js} +16 -13
- package/lib/opLifecycle/opCompressor.js.map +1 -0
- package/lib/{opDecompressor.d.ts → opLifecycle/opDecompressor.d.ts} +0 -0
- package/lib/opLifecycle/opDecompressor.d.ts.map +1 -0
- package/lib/{opDecompressor.js → opLifecycle/opDecompressor.js} +4 -4
- package/lib/opLifecycle/opDecompressor.js.map +1 -0
- package/lib/opLifecycle/opSplitter.d.ts +17 -0
- package/lib/opLifecycle/opSplitter.d.ts.map +1 -0
- package/lib/opLifecycle/opSplitter.js +57 -0
- package/lib/opLifecycle/opSplitter.js.map +1 -0
- package/lib/opLifecycle/outbox.d.ts +47 -0
- package/lib/opLifecycle/outbox.d.ts.map +1 -0
- package/lib/opLifecycle/outbox.js +149 -0
- package/lib/opLifecycle/outbox.js.map +1 -0
- package/lib/opLifecycle/remoteMessageProcessor.d.ts +26 -0
- package/lib/opLifecycle/remoteMessageProcessor.d.ts.map +1 -0
- package/lib/opLifecycle/remoteMessageProcessor.js +76 -0
- package/lib/opLifecycle/remoteMessageProcessor.js.map +1 -0
- package/lib/packageVersion.d.ts +1 -1
- package/lib/packageVersion.js +1 -1
- package/lib/packageVersion.js.map +1 -1
- package/lib/summaryFormat.js +1 -1
- package/lib/summaryFormat.js.map +1 -1
- package/package.json +21 -34
- package/src/blobManager.ts +74 -19
- package/src/containerRuntime.ts +91 -278
- package/src/dataStoreContext.ts +1 -1
- package/src/dataStores.ts +2 -1
- package/src/garbageCollection.ts +33 -43
- package/src/garbageCollectionConstants.ts +35 -0
- package/src/gcSweepReadyUsageDetection.ts +1 -1
- package/src/index.ts +5 -4
- package/src/{batchManager.ts → opLifecycle/batchManager.ts} +30 -33
- package/src/opLifecycle/definitions.ts +44 -0
- package/src/opLifecycle/index.ts +17 -0
- package/src/{opCompressor.ts → opLifecycle/opCompressor.ts} +21 -16
- package/src/{opDecompressor.ts → opLifecycle/opDecompressor.ts} +8 -6
- package/src/opLifecycle/opSplitter.ts +78 -0
- package/src/opLifecycle/outbox.ts +204 -0
- package/src/opLifecycle/remoteMessageProcessor.ts +90 -0
- package/src/packageVersion.ts +1 -1
- package/src/summaryFormat.ts +1 -1
- package/dist/batchManager.d.ts +0 -42
- package/dist/batchManager.d.ts.map +0 -1
- package/dist/batchManager.js.map +0 -1
- package/dist/opCompressor.d.ts.map +0 -1
- package/dist/opCompressor.js.map +0 -1
- package/dist/opDecompressor.d.ts.map +0 -1
- package/dist/opDecompressor.js.map +0 -1
- package/lib/batchManager.d.ts +0 -42
- package/lib/batchManager.d.ts.map +0 -1
- package/lib/batchManager.js.map +0 -1
- package/lib/opCompressor.d.ts.map +0 -1
- package/lib/opCompressor.js.map +0 -1
- package/lib/opDecompressor.d.ts.map +0 -1
- package/lib/opDecompressor.js.map +0 -1
package/src/containerRuntime.ts
CHANGED
|
@@ -16,14 +16,12 @@ import {
|
|
|
16
16
|
IFluidTokenProvider,
|
|
17
17
|
IContainerContext,
|
|
18
18
|
IDeltaManager,
|
|
19
|
-
IDeltaSender,
|
|
20
19
|
IRuntime,
|
|
21
20
|
ICriticalContainerError,
|
|
22
21
|
AttachState,
|
|
23
22
|
ILoaderOptions,
|
|
24
23
|
LoaderHeader,
|
|
25
24
|
ISnapshotTreeWithBlobContents,
|
|
26
|
-
IBatchMessage,
|
|
27
25
|
} from "@fluidframework/container-definitions";
|
|
28
26
|
import {
|
|
29
27
|
IContainerRuntime,
|
|
@@ -119,7 +117,6 @@ import {
|
|
|
119
117
|
IPendingLocalState,
|
|
120
118
|
PendingStateManager,
|
|
121
119
|
} from "./pendingStateManager";
|
|
122
|
-
import { BatchManager, BatchMessage } from "./batchManager";
|
|
123
120
|
import { pkgVersion } from "./packageVersion";
|
|
124
121
|
import { BlobManager, IBlobManagerLoadInfo, IPendingBlobs } from "./blobManager";
|
|
125
122
|
import { DataStores, getSummaryForDatastores } from "./dataStores";
|
|
@@ -154,11 +151,13 @@ import { RunWhileConnectedCoordinator } from "./runWhileConnectedCoordinator";
|
|
|
154
151
|
import {
|
|
155
152
|
GarbageCollector,
|
|
156
153
|
GCNodeType,
|
|
157
|
-
gcTreeKey,
|
|
158
154
|
IGarbageCollectionRuntime,
|
|
159
155
|
IGarbageCollector,
|
|
160
156
|
IGCStats,
|
|
161
157
|
} from "./garbageCollection";
|
|
158
|
+
import {
|
|
159
|
+
gcTreeKey,
|
|
160
|
+
} from "./garbageCollectionConstants";
|
|
162
161
|
import {
|
|
163
162
|
channelToDataStore,
|
|
164
163
|
IDataStoreAliasMessage,
|
|
@@ -167,7 +166,15 @@ import {
|
|
|
167
166
|
import { BindBatchTracker } from "./batchTracker";
|
|
168
167
|
import { ISerializedBaseSnapshotBlobs, SerializedSnapshotStorage } from "./serializedSnapshotStorage";
|
|
169
168
|
import { ScheduleManager } from "./scheduleManager";
|
|
170
|
-
import {
|
|
169
|
+
import {
|
|
170
|
+
BatchMessage,
|
|
171
|
+
IBatchCheckpoint,
|
|
172
|
+
OpCompressor,
|
|
173
|
+
OpDecompressor,
|
|
174
|
+
Outbox,
|
|
175
|
+
OpSplitter,
|
|
176
|
+
RemoteMessageProcessor,
|
|
177
|
+
} from "./opLifecycle";
|
|
171
178
|
|
|
172
179
|
export enum ContainerMessageType {
|
|
173
180
|
// An op to be delivered to store
|
|
@@ -189,16 +196,6 @@ export enum ContainerMessageType {
|
|
|
189
196
|
Alias = "alias",
|
|
190
197
|
}
|
|
191
198
|
|
|
192
|
-
export interface IChunkedOp {
|
|
193
|
-
chunkId: number;
|
|
194
|
-
|
|
195
|
-
totalChunks: number;
|
|
196
|
-
|
|
197
|
-
contents: string;
|
|
198
|
-
|
|
199
|
-
originalType: MessageType | ContainerMessageType;
|
|
200
|
-
}
|
|
201
|
-
|
|
202
199
|
export interface ContainerRuntimeMessage {
|
|
203
200
|
contents: any;
|
|
204
201
|
type: ContainerMessageType;
|
|
@@ -589,36 +586,6 @@ export function isRuntimeMessage(message: ISequencedDocumentMessage): boolean {
|
|
|
589
586
|
return (Object.values(RuntimeMessage) as string[]).includes(message.type);
|
|
590
587
|
}
|
|
591
588
|
|
|
592
|
-
/**
|
|
593
|
-
* Unpacks runtime messages
|
|
594
|
-
*
|
|
595
|
-
* @remarks This API makes no promises regarding backward-compatibility. This is internal API.
|
|
596
|
-
* @param message - message (as it observed in storage / service)
|
|
597
|
-
* @returns unpacked runtime message
|
|
598
|
-
*
|
|
599
|
-
* @internal
|
|
600
|
-
*/
|
|
601
|
-
export function unpackRuntimeMessage(message: ISequencedDocumentMessage) {
|
|
602
|
-
if (message.type === MessageType.Operation) {
|
|
603
|
-
// legacy op format?
|
|
604
|
-
if (message.contents.address !== undefined && message.contents.type === undefined) {
|
|
605
|
-
message.type = ContainerMessageType.FluidDataStoreOp;
|
|
606
|
-
} else {
|
|
607
|
-
// new format
|
|
608
|
-
const innerContents = message.contents as ContainerRuntimeMessage;
|
|
609
|
-
message.type = innerContents.type;
|
|
610
|
-
message.contents = innerContents.contents;
|
|
611
|
-
}
|
|
612
|
-
return true;
|
|
613
|
-
} else {
|
|
614
|
-
// Legacy format, but it's already "unpacked",
|
|
615
|
-
// i.e. message.type is actually ContainerMessageType.
|
|
616
|
-
// Or it's non-runtime message.
|
|
617
|
-
// Nothing to do in such case.
|
|
618
|
-
return false;
|
|
619
|
-
}
|
|
620
|
-
}
|
|
621
|
-
|
|
622
589
|
/**
|
|
623
590
|
* Legacy ID for the built-in AgentScheduler. To minimize disruption while removing it, retaining this as a
|
|
624
591
|
* special-case for document dirty state. Ultimately we should have no special-cases from the
|
|
@@ -661,6 +628,8 @@ export class ContainerRuntime extends TypedEventEmitter<IContainerRuntimeEvents>
|
|
|
661
628
|
* @param requestHandler - Request handlers for the container runtime
|
|
662
629
|
* @param runtimeOptions - Additional options to be passed to the runtime
|
|
663
630
|
* @param existing - (optional) When loading from an existing snapshot. Precedes context.existing if provided
|
|
631
|
+
* @param containerRuntimeCtor - (optional) Constructor to use to create the ContainerRuntime instance. This
|
|
632
|
+
* allows mixin classes to leverage this method to define their own async initializer.
|
|
664
633
|
*/
|
|
665
634
|
public static async load(
|
|
666
635
|
context: IContainerContext,
|
|
@@ -669,6 +638,7 @@ export class ContainerRuntime extends TypedEventEmitter<IContainerRuntimeEvents>
|
|
|
669
638
|
runtimeOptions: IContainerRuntimeOptions = {},
|
|
670
639
|
containerScope: FluidObject = context.scope,
|
|
671
640
|
existing?: boolean,
|
|
641
|
+
containerRuntimeCtor: typeof ContainerRuntime = ContainerRuntime
|
|
672
642
|
): Promise<ContainerRuntime> {
|
|
673
643
|
// If taggedLogger exists, use it. Otherwise, wrap the vanilla logger:
|
|
674
644
|
// back-compat: Remove the TaggedLoggerAdapter fallback once all the host are using loader > 0.45
|
|
@@ -687,8 +657,10 @@ export class ContainerRuntime extends TypedEventEmitter<IContainerRuntimeEvents>
|
|
|
687
657
|
loadSequenceNumberVerification = "close",
|
|
688
658
|
flushMode = defaultFlushMode,
|
|
689
659
|
enableOfflineLoad = false,
|
|
690
|
-
compressionOptions = {
|
|
691
|
-
|
|
660
|
+
compressionOptions = {
|
|
661
|
+
minimumBatchSizeInBytes: Number.POSITIVE_INFINITY,
|
|
662
|
+
compressionAlgorithm: CompressionAlgorithms.lz4
|
|
663
|
+
},
|
|
692
664
|
maxBatchSizeInBytes = defaultMaxBatchSizeInBytes,
|
|
693
665
|
} = runtimeOptions;
|
|
694
666
|
|
|
@@ -752,7 +724,7 @@ export class ContainerRuntime extends TypedEventEmitter<IContainerRuntimeEvents>
|
|
|
752
724
|
}
|
|
753
725
|
}
|
|
754
726
|
|
|
755
|
-
const runtime = new
|
|
727
|
+
const runtime = new containerRuntimeCtor(
|
|
756
728
|
context,
|
|
757
729
|
registry,
|
|
758
730
|
metadata,
|
|
@@ -846,8 +818,6 @@ export class ContainerRuntime extends TypedEventEmitter<IContainerRuntimeEvents>
|
|
|
846
818
|
// internal logger for ContainerRuntime. Use this.logger for stores, summaries, etc.
|
|
847
819
|
private readonly mc: MonitoringContext;
|
|
848
820
|
|
|
849
|
-
private readonly opDecompressor: OpDecompressor = new OpDecompressor();
|
|
850
|
-
|
|
851
821
|
private readonly summarizerClientElection?: SummarizerClientElection;
|
|
852
822
|
/**
|
|
853
823
|
* summaryManager will only be created if this client is permitted to spawn a summarizing client
|
|
@@ -908,27 +878,19 @@ export class ContainerRuntime extends TypedEventEmitter<IContainerRuntimeEvents>
|
|
|
908
878
|
* It is created only by summarizing container (i.e. one with clientType === "summarizer")
|
|
909
879
|
*/
|
|
910
880
|
private readonly _summarizer?: Summarizer;
|
|
911
|
-
private readonly deltaSender: IDeltaSender;
|
|
912
881
|
private readonly scheduleManager: ScheduleManager;
|
|
913
882
|
private readonly blobManager: BlobManager;
|
|
914
883
|
private readonly pendingStateManager: PendingStateManager;
|
|
915
|
-
private readonly
|
|
916
|
-
private readonly pendingBatch: BatchManager;
|
|
884
|
+
private readonly outbox: Outbox;
|
|
917
885
|
|
|
918
886
|
private readonly garbageCollector: IGarbageCollector;
|
|
919
887
|
|
|
920
|
-
// Local copy of incomplete received chunks.
|
|
921
|
-
private readonly chunkMap: Map<string, string[]>;
|
|
922
|
-
|
|
923
888
|
private readonly dataStores: DataStores;
|
|
889
|
+
private readonly remoteMessageProcessor: RemoteMessageProcessor;
|
|
924
890
|
|
|
925
891
|
/** The last message processed at the time of the last summary. */
|
|
926
892
|
private messageAtLastSummary: ISummaryMetadataMessage | undefined;
|
|
927
893
|
|
|
928
|
-
private get emptyBatch() {
|
|
929
|
-
return this.pendingBatch.empty && this.pendingAttachBatch.empty;
|
|
930
|
-
}
|
|
931
|
-
|
|
932
894
|
private get summarizer(): Summarizer {
|
|
933
895
|
assert(this._summarizer !== undefined, 0x257 /* "This is not summarizing container" */);
|
|
934
896
|
return this._summarizer;
|
|
@@ -999,7 +961,10 @@ export class ContainerRuntime extends TypedEventEmitter<IContainerRuntimeEvents>
|
|
|
999
961
|
*/
|
|
1000
962
|
private nextSummaryNumber: number;
|
|
1001
963
|
|
|
1002
|
-
|
|
964
|
+
/**
|
|
965
|
+
* @internal
|
|
966
|
+
*/
|
|
967
|
+
protected constructor(
|
|
1003
968
|
private readonly context: IContainerContext,
|
|
1004
969
|
private readonly registry: IFluidDataStoreRegistry,
|
|
1005
970
|
metadata: IContainerRuntimeMetadata | undefined,
|
|
@@ -1045,7 +1010,7 @@ export class ContainerRuntime extends TypedEventEmitter<IContainerRuntimeEvents>
|
|
|
1045
1010
|
this.messageAtLastSummary = metadata?.message;
|
|
1046
1011
|
|
|
1047
1012
|
this._connected = this.context.connected;
|
|
1048
|
-
this.
|
|
1013
|
+
this.remoteMessageProcessor = new RemoteMessageProcessor(new OpSplitter(chunks), new OpDecompressor());
|
|
1049
1014
|
|
|
1050
1015
|
this.handleContext = new ContainerFluidHandleContext("", this);
|
|
1051
1016
|
|
|
@@ -1067,21 +1032,6 @@ export class ContainerRuntime extends TypedEventEmitter<IContainerRuntimeEvents>
|
|
|
1067
1032
|
|
|
1068
1033
|
this._flushMode = runtimeOptions.flushMode;
|
|
1069
1034
|
|
|
1070
|
-
// Provide lower soft limit - we want to have some number of ops to get efficiency in compression
|
|
1071
|
-
// & bandwidth usage, but at the same time we want to send these ops sooner, to reduce overall
|
|
1072
|
-
// latency of processing a batch.
|
|
1073
|
-
// So there is some ballance here, that depends on compression algorithm and its efficiency working with smaller
|
|
1074
|
-
// payloads. That number represents final (compressed) bits (once compression is implemented).
|
|
1075
|
-
this.pendingAttachBatch = new BatchManager(this.mc.logger, {
|
|
1076
|
-
hardLimit: runtimeOptions.maxBatchSizeInBytes,
|
|
1077
|
-
softLimit: 64 * 1024,
|
|
1078
|
-
compressionOptions: runtimeOptions.compressionOptions
|
|
1079
|
-
});
|
|
1080
|
-
this.pendingBatch = new BatchManager(this.mc.logger, {
|
|
1081
|
-
hardLimit: runtimeOptions.maxBatchSizeInBytes,
|
|
1082
|
-
compressionOptions: runtimeOptions.compressionOptions
|
|
1083
|
-
});
|
|
1084
|
-
|
|
1085
1035
|
const pendingRuntimeState = context.pendingLocalState as IPendingRuntimeState | undefined;
|
|
1086
1036
|
const baseSnapshot: ISnapshotTree | undefined = pendingRuntimeState?.baseSnapshot ?? context.baseSnapshot;
|
|
1087
1037
|
|
|
@@ -1184,8 +1134,6 @@ export class ContainerRuntime extends TypedEventEmitter<IContainerRuntimeEvents>
|
|
|
1184
1134
|
ChildLogger.create(this.logger, "ScheduleManager"),
|
|
1185
1135
|
);
|
|
1186
1136
|
|
|
1187
|
-
this.deltaSender = this.deltaManager;
|
|
1188
|
-
|
|
1189
1137
|
this.pendingStateManager = new PendingStateManager(
|
|
1190
1138
|
{
|
|
1191
1139
|
applyStashedOp: this.applyStashedOp.bind(this),
|
|
@@ -1199,8 +1147,19 @@ export class ContainerRuntime extends TypedEventEmitter<IContainerRuntimeEvents>
|
|
|
1199
1147
|
},
|
|
1200
1148
|
pendingRuntimeState?.pending);
|
|
1201
1149
|
|
|
1150
|
+
this.outbox = new Outbox({
|
|
1151
|
+
shouldSend: () => this.canSendOps(),
|
|
1152
|
+
pendingStateManager: this.pendingStateManager,
|
|
1153
|
+
containerContext: this.context,
|
|
1154
|
+
compressor: new OpCompressor(this.mc.logger),
|
|
1155
|
+
config: {
|
|
1156
|
+
compressionOptions: runtimeOptions.compressionOptions,
|
|
1157
|
+
maxBatchSizeInBytes: runtimeOptions.maxBatchSizeInBytes,
|
|
1158
|
+
},
|
|
1159
|
+
});
|
|
1160
|
+
|
|
1202
1161
|
this.context.quorum.on("removeMember", (clientId: string) => {
|
|
1203
|
-
this.
|
|
1162
|
+
this.remoteMessageProcessor.clearPartialMessagesFor(clientId);
|
|
1204
1163
|
});
|
|
1205
1164
|
|
|
1206
1165
|
this.summaryCollection = new SummaryCollection(this.deltaManager, this.logger);
|
|
@@ -1501,7 +1460,7 @@ export class ContainerRuntime extends TypedEventEmitter<IContainerRuntimeEvents>
|
|
|
1501
1460
|
addBlobToSummary(summaryTree, metadataBlobName, JSON.stringify(metadata));
|
|
1502
1461
|
}
|
|
1503
1462
|
|
|
1504
|
-
|
|
1463
|
+
protected addContainerStateToSummary(
|
|
1505
1464
|
summaryTree: ISummaryTreeWithStats,
|
|
1506
1465
|
fullTree: boolean,
|
|
1507
1466
|
trackState: boolean,
|
|
@@ -1509,8 +1468,8 @@ export class ContainerRuntime extends TypedEventEmitter<IContainerRuntimeEvents>
|
|
|
1509
1468
|
) {
|
|
1510
1469
|
this.addMetadataToSummary(summaryTree);
|
|
1511
1470
|
|
|
1512
|
-
if (this.
|
|
1513
|
-
const content = JSON.stringify([...this.
|
|
1471
|
+
if (this.remoteMessageProcessor.partialMessages.size > 0) {
|
|
1472
|
+
const content = JSON.stringify([...this.remoteMessageProcessor.partialMessages]);
|
|
1514
1473
|
addBlobToSummary(summaryTree, chunksBlobName, content);
|
|
1515
1474
|
}
|
|
1516
1475
|
|
|
@@ -1705,28 +1664,19 @@ export class ContainerRuntime extends TypedEventEmitter<IContainerRuntimeEvents>
|
|
|
1705
1664
|
public process(messageArg: ISequencedDocumentMessage, local: boolean) {
|
|
1706
1665
|
this.verifyNotClosed();
|
|
1707
1666
|
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
// We do not need to make deep copy, as each layer will just replace message.content itself,
|
|
1711
|
-
// but would not modify contents details
|
|
1712
|
-
let message = { ...messageArg };
|
|
1713
|
-
|
|
1714
|
-
// back-compat: ADO #1385: eventually should become unconditional, but only for runtime messages!
|
|
1715
|
-
// System message may have no contents, or in some cases (mostly for back-compat) they may have actual objects.
|
|
1716
|
-
// Old ops may contain empty string (I assume noops).
|
|
1717
|
-
if (typeof message.contents === "string" && message.contents !== "") {
|
|
1718
|
-
message.contents = JSON.parse(message.contents);
|
|
1667
|
+
if (this.mc.config.getBoolean("enableOfflineLoad") ?? this.runtimeOptions.enableOfflineLoad) {
|
|
1668
|
+
this.savedOps.push(messageArg);
|
|
1719
1669
|
}
|
|
1720
1670
|
|
|
1721
|
-
message = this.opDecompressor.processMessage(message);
|
|
1722
1671
|
|
|
1723
|
-
//
|
|
1724
|
-
//
|
|
1725
|
-
|
|
1672
|
+
// Whether or not the message is actually a runtime message.
|
|
1673
|
+
// It may be a legacy runtime message (ie already unpacked and ContainerMessageType)
|
|
1674
|
+
// or something different, like a system message.
|
|
1675
|
+
const runtimeMessage = messageArg.type === MessageType.Operation;
|
|
1726
1676
|
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1677
|
+
// Do shallow copy of message, as the processing flow will modify it.
|
|
1678
|
+
const messageCopy = { ...messageArg };
|
|
1679
|
+
const message = this.remoteMessageProcessor.process(messageCopy);
|
|
1730
1680
|
|
|
1731
1681
|
// Surround the actual processing of the operation with messages to the schedule manager indicating
|
|
1732
1682
|
// the beginning and end. This allows it to emit appropriate events and/or pause the processing of new
|
|
@@ -1734,10 +1684,6 @@ export class ContainerRuntime extends TypedEventEmitter<IContainerRuntimeEvents>
|
|
|
1734
1684
|
this.scheduleManager.beforeOpProcessing(message);
|
|
1735
1685
|
|
|
1736
1686
|
try {
|
|
1737
|
-
// Chunk processing must come first given that we will transform the message to the unchunked version
|
|
1738
|
-
// once all pieces are available
|
|
1739
|
-
message = this.processRemoteChunkedMessage(message);
|
|
1740
|
-
|
|
1741
1687
|
let localOpMetadata: unknown;
|
|
1742
1688
|
if (local && runtimeMessage) {
|
|
1743
1689
|
localOpMetadata = this.pendingStateManager.processPendingLocalMessage(message);
|
|
@@ -1870,97 +1816,22 @@ export class ContainerRuntime extends TypedEventEmitter<IContainerRuntimeEvents>
|
|
|
1870
1816
|
assert(this._orderSequentiallyCalls === 0,
|
|
1871
1817
|
0x24c /* "Cannot call `flush()` from `orderSequentially`'s callback" */);
|
|
1872
1818
|
|
|
1873
|
-
this.
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
assert(this.emptyBatch, 0x3cf /* reentrancy */);
|
|
1877
|
-
}
|
|
1878
|
-
|
|
1879
|
-
protected flushBatch(batch: BatchMessage[]): void {
|
|
1880
|
-
const length = batch.length;
|
|
1881
|
-
|
|
1882
|
-
if (length > 1) {
|
|
1883
|
-
batch[0].metadata = { ...batch[0].metadata, batch: true };
|
|
1884
|
-
batch[length - 1].metadata = { ...batch[length - 1].metadata, batch: false };
|
|
1885
|
-
|
|
1886
|
-
// This assert fires for the following reason (there might be more cases like that):
|
|
1887
|
-
// AgentScheduler will send ops in response to ConsensusRegisterCollection's "atomicChanged" event handler,
|
|
1888
|
-
// i.e. in the middle of op processing!
|
|
1889
|
-
// Sending ops while processing ops is not good idea - it's not defined when
|
|
1890
|
-
// referenceSequenceNumber changes in op processing sequence (at the beginning or end of op processing),
|
|
1891
|
-
// If we send ops in response to processing multiple ops, then we for sure hit this assert!
|
|
1892
|
-
// Tracked via ADO #1834
|
|
1893
|
-
// assert(batch[0].referenceSequenceNumber === batch[length - 1].referenceSequenceNumber,
|
|
1894
|
-
// "Batch should be generated synchronously, without processing ops in the middle!");
|
|
1895
|
-
}
|
|
1896
|
-
|
|
1897
|
-
let clientSequenceNumber: number = -1;
|
|
1898
|
-
|
|
1899
|
-
// Did we disconnect in the middle of turn-based batch?
|
|
1900
|
-
// If so, do nothing, as pending state manager will resubmit it correctly on reconnect.
|
|
1901
|
-
if (this.canSendOps()) {
|
|
1902
|
-
if (this.context.submitBatchFn !== undefined) {
|
|
1903
|
-
const batchToSend: IBatchMessage[] = [];
|
|
1904
|
-
|
|
1905
|
-
for (const message of batch) {
|
|
1906
|
-
batchToSend.push({ contents: message.contents, metadata: message.metadata });
|
|
1907
|
-
}
|
|
1908
|
-
|
|
1909
|
-
// returns clientSequenceNumber of last message in a batch
|
|
1910
|
-
clientSequenceNumber = this.context.submitBatchFn(batchToSend);
|
|
1911
|
-
} else {
|
|
1912
|
-
// Legacy path - supporting old loader versions. Can be removed only when LTS moves above
|
|
1913
|
-
// version that has support for batches (submitBatchFn)
|
|
1914
|
-
for (const message of batch) {
|
|
1915
|
-
// Legacy path doesn't support compressed payloads and will submit uncompressed payload anyways
|
|
1916
|
-
if (message.metadata?.compressed) {
|
|
1917
|
-
delete message.metadata.compressed;
|
|
1918
|
-
}
|
|
1919
|
-
|
|
1920
|
-
clientSequenceNumber = this.context.submitFn(
|
|
1921
|
-
MessageType.Operation,
|
|
1922
|
-
message.deserializedContent,
|
|
1923
|
-
true, // batch
|
|
1924
|
-
message.metadata);
|
|
1925
|
-
}
|
|
1926
|
-
|
|
1927
|
-
this.deltaSender.flush();
|
|
1928
|
-
}
|
|
1929
|
-
|
|
1930
|
-
// Convert from clientSequenceNumber of last message in the batch to clientSequenceNumber of first message.
|
|
1931
|
-
clientSequenceNumber -= batch.length - 1;
|
|
1932
|
-
assert(clientSequenceNumber >= 0, 0x3d0 /* clientSequenceNumber can't be negative */);
|
|
1933
|
-
}
|
|
1934
|
-
|
|
1935
|
-
// Let the PendingStateManager know that a message was submitted.
|
|
1936
|
-
// In future, need to shift toward keeping batch as a whole!
|
|
1937
|
-
for (const message of batch) {
|
|
1938
|
-
this.pendingStateManager.onSubmitMessage(
|
|
1939
|
-
message.deserializedContent.type,
|
|
1940
|
-
clientSequenceNumber,
|
|
1941
|
-
message.referenceSequenceNumber,
|
|
1942
|
-
message.deserializedContent.contents,
|
|
1943
|
-
message.localOpMetadata,
|
|
1944
|
-
message.metadata,
|
|
1945
|
-
);
|
|
1946
|
-
clientSequenceNumber++;
|
|
1947
|
-
}
|
|
1948
|
-
|
|
1949
|
-
this.pendingStateManager.onFlush();
|
|
1819
|
+
this.outbox.flush();
|
|
1820
|
+
assert(this.outbox.isEmpty, 0x3cf /* reentrancy */);
|
|
1950
1821
|
}
|
|
1951
1822
|
|
|
1952
|
-
public orderSequentially(callback: () =>
|
|
1953
|
-
let checkpoint:
|
|
1954
|
-
|
|
1823
|
+
public orderSequentially<T>(callback: () => T): T {
|
|
1824
|
+
let checkpoint: IBatchCheckpoint | undefined;
|
|
1825
|
+
let result: T;
|
|
1955
1826
|
if (this.mc.config.getBoolean("Fluid.ContainerRuntime.EnableRollback")) {
|
|
1956
1827
|
// Note: we are not touching this.pendingAttachBatch here, for two reasons:
|
|
1957
1828
|
// 1. It would not help, as we flush attach ops as they become available.
|
|
1958
1829
|
// 2. There is no way to undo process of data store creation.
|
|
1959
|
-
checkpoint = this.
|
|
1830
|
+
checkpoint = this.outbox.checkpoint().mainBatch;
|
|
1960
1831
|
}
|
|
1961
1832
|
try {
|
|
1962
1833
|
this._orderSequentiallyCalls++;
|
|
1963
|
-
callback();
|
|
1834
|
+
result = callback();
|
|
1964
1835
|
} catch (error) {
|
|
1965
1836
|
if (checkpoint) {
|
|
1966
1837
|
// This will throw and close the container if rollback fails
|
|
@@ -1992,6 +1863,7 @@ export class ContainerRuntime extends TypedEventEmitter<IContainerRuntimeEvents>
|
|
|
1992
1863
|
if (this.flushMode === FlushMode.Immediate && this._orderSequentiallyCalls === 0) {
|
|
1993
1864
|
this.flush();
|
|
1994
1865
|
}
|
|
1866
|
+
return result;
|
|
1995
1867
|
}
|
|
1996
1868
|
|
|
1997
1869
|
public async createDataStore(pkg: string | string[]): Promise<IDataStore> {
|
|
@@ -2267,20 +2139,24 @@ export class ContainerRuntime extends TypedEventEmitter<IContainerRuntimeEvents>
|
|
|
2267
2139
|
// always referenced, so the used routes is only self-route (empty string).
|
|
2268
2140
|
this.summarizerNode.updateUsedRoutes([""]);
|
|
2269
2141
|
|
|
2142
|
+
const blobManagerUsedRoutes: string[] = [];
|
|
2270
2143
|
const dataStoreUsedRoutes: string[] = [];
|
|
2271
2144
|
for (const route of usedRoutes) {
|
|
2272
|
-
if (
|
|
2145
|
+
if (this.isBlobPath(route)) {
|
|
2146
|
+
blobManagerUsedRoutes.push(route);
|
|
2147
|
+
} else {
|
|
2273
2148
|
dataStoreUsedRoutes.push(route);
|
|
2274
2149
|
}
|
|
2275
2150
|
}
|
|
2276
2151
|
|
|
2277
|
-
|
|
2152
|
+
this.blobManager.updateUsedRoutes(blobManagerUsedRoutes);
|
|
2153
|
+
this.dataStores.updateUsedRoutes(dataStoreUsedRoutes);
|
|
2278
2154
|
}
|
|
2279
2155
|
|
|
2280
2156
|
/**
|
|
2281
2157
|
* This is called to update objects whose routes are unused. The unused objects are either deleted or marked as
|
|
2282
2158
|
* tombstones.
|
|
2283
|
-
* @param unusedRoutes - The routes that are unused in all data stores in this Container.
|
|
2159
|
+
* @param unusedRoutes - The routes that are unused in all data stores and attachment blobs in this Container.
|
|
2284
2160
|
* @param tombstone - if true, the objects corresponding to unused routes are marked tombstones. Otherwise, they
|
|
2285
2161
|
* are deleted.
|
|
2286
2162
|
*/
|
|
@@ -2295,10 +2171,7 @@ export class ContainerRuntime extends TypedEventEmitter<IContainerRuntimeEvents>
|
|
|
2295
2171
|
}
|
|
2296
2172
|
}
|
|
2297
2173
|
|
|
2298
|
-
|
|
2299
|
-
if (!tombstone) {
|
|
2300
|
-
this.blobManager.deleteUnusedRoutes(blobManagerUnusedRoutes);
|
|
2301
|
-
}
|
|
2174
|
+
this.blobManager.updateUnusedRoutes(blobManagerUnusedRoutes, tombstone);
|
|
2302
2175
|
this.dataStores.updateUnusedRoutes(dataStoreUnusedRoutes, tombstone);
|
|
2303
2176
|
}
|
|
2304
2177
|
|
|
@@ -2397,7 +2270,7 @@ export class ContainerRuntime extends TypedEventEmitter<IContainerRuntimeEvents>
|
|
|
2397
2270
|
},
|
|
2398
2271
|
);
|
|
2399
2272
|
|
|
2400
|
-
assert(this.
|
|
2273
|
+
assert(this.outbox.isEmpty, 0x3d1 /* Can't trigger summary in the middle of a batch */);
|
|
2401
2274
|
|
|
2402
2275
|
let latestSnapshotVersionId: string | undefined;
|
|
2403
2276
|
if (refreshLatestAck) {
|
|
@@ -2607,45 +2480,8 @@ export class ContainerRuntime extends TypedEventEmitter<IContainerRuntimeEvents>
|
|
|
2607
2480
|
}
|
|
2608
2481
|
}
|
|
2609
2482
|
|
|
2610
|
-
private processRemoteChunkedMessage(message: ISequencedDocumentMessage) {
|
|
2611
|
-
if (message.type !== ContainerMessageType.ChunkedOp) {
|
|
2612
|
-
return message;
|
|
2613
|
-
}
|
|
2614
|
-
|
|
2615
|
-
const clientId = message.clientId;
|
|
2616
|
-
const chunkedContent = message.contents as IChunkedOp;
|
|
2617
|
-
this.addChunk(clientId, chunkedContent);
|
|
2618
|
-
if (chunkedContent.chunkId === chunkedContent.totalChunks) {
|
|
2619
|
-
const newMessage = { ...message };
|
|
2620
|
-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
2621
|
-
const serializedContent = this.chunkMap.get(clientId)!.join("");
|
|
2622
|
-
newMessage.contents = JSON.parse(serializedContent);
|
|
2623
|
-
newMessage.type = chunkedContent.originalType;
|
|
2624
|
-
this.clearPartialChunks(clientId);
|
|
2625
|
-
return newMessage;
|
|
2626
|
-
}
|
|
2627
|
-
return message;
|
|
2628
|
-
}
|
|
2629
|
-
|
|
2630
|
-
private addChunk(clientId: string, chunkedContent: IChunkedOp) {
|
|
2631
|
-
let map = this.chunkMap.get(clientId);
|
|
2632
|
-
if (map === undefined) {
|
|
2633
|
-
map = [];
|
|
2634
|
-
this.chunkMap.set(clientId, map);
|
|
2635
|
-
}
|
|
2636
|
-
assert(chunkedContent.chunkId === map.length + 1,
|
|
2637
|
-
0x131 /* "Mismatch between new chunkId and expected chunkMap" */); // 1-based indexing
|
|
2638
|
-
map.push(chunkedContent.contents);
|
|
2639
|
-
}
|
|
2640
|
-
|
|
2641
|
-
private clearPartialChunks(clientId: string) {
|
|
2642
|
-
if (this.chunkMap.has(clientId)) {
|
|
2643
|
-
this.chunkMap.delete(clientId);
|
|
2644
|
-
}
|
|
2645
|
-
}
|
|
2646
|
-
|
|
2647
2483
|
private hasPendingMessages() {
|
|
2648
|
-
return this.pendingStateManager.hasPendingMessages() || !this.
|
|
2484
|
+
return this.pendingStateManager.hasPendingMessages() || !this.outbox.isEmpty;
|
|
2649
2485
|
}
|
|
2650
2486
|
|
|
2651
2487
|
private updateDocumentDirtyState(dirty: boolean) {
|
|
@@ -2708,7 +2544,7 @@ export class ContainerRuntime extends TypedEventEmitter<IContainerRuntimeEvents>
|
|
|
2708
2544
|
const serializedContent = JSON.stringify(deserializedContent);
|
|
2709
2545
|
|
|
2710
2546
|
if (this.deltaManager.readOnlyInfo.readonly) {
|
|
2711
|
-
this.logger.
|
|
2547
|
+
this.logger.sendTelemetryEvent({ eventName: "SubmitOpInReadonly", connected: this.connected });
|
|
2712
2548
|
}
|
|
2713
2549
|
|
|
2714
2550
|
const message: BatchMessage = {
|
|
@@ -2741,45 +2577,22 @@ export class ContainerRuntime extends TypedEventEmitter<IContainerRuntimeEvents>
|
|
|
2741
2577
|
// Please note that this does not change file format, so it can be disabled in the future if this
|
|
2742
2578
|
// optimization no longer makes sense (for example, batch compression may make it less appealing).
|
|
2743
2579
|
if (this.currentlyBatching() && type === ContainerMessageType.Attach &&
|
|
2744
|
-
this.mc.config.getBoolean("Fluid.ContainerRuntime.
|
|
2745
|
-
|
|
2746
|
-
// BatchManager has two limits - soft limit & hard limit. Soft limit is only engaged
|
|
2747
|
-
// when queue is not empty.
|
|
2748
|
-
// Flush queue & retry. Failure on retry would mean - single message is bigger than hard limit
|
|
2749
|
-
this.flushBatch(this.pendingAttachBatch.popBatch());
|
|
2750
|
-
if (!this.pendingAttachBatch.push(message)) {
|
|
2751
|
-
throw new GenericError(
|
|
2752
|
-
"BatchTooLarge",
|
|
2753
|
-
/* error */ undefined,
|
|
2754
|
-
{
|
|
2755
|
-
opSize: (message.contents?.length) ?? 0,
|
|
2756
|
-
count: this.pendingAttachBatch.length,
|
|
2757
|
-
limit: this.pendingAttachBatch.options.hardLimit,
|
|
2758
|
-
});
|
|
2759
|
-
}
|
|
2760
|
-
}
|
|
2580
|
+
this.mc.config.getBoolean("Fluid.ContainerRuntime.disableAttachOpReorder") !== true) {
|
|
2581
|
+
this.outbox.submitAttach(message);
|
|
2761
2582
|
} else {
|
|
2762
|
-
|
|
2763
|
-
|
|
2764
|
-
|
|
2765
|
-
|
|
2766
|
-
|
|
2767
|
-
|
|
2768
|
-
|
|
2769
|
-
|
|
2770
|
-
|
|
2771
|
-
|
|
2772
|
-
|
|
2583
|
+
this.outbox.submit(message);
|
|
2584
|
+
}
|
|
2585
|
+
|
|
2586
|
+
if (!this.currentlyBatching()) {
|
|
2587
|
+
this.flush();
|
|
2588
|
+
} else if (!this.flushMicroTaskExists) {
|
|
2589
|
+
this.flushMicroTaskExists = true;
|
|
2590
|
+
// Queue a microtask to detect the end of the turn and force a flush.
|
|
2591
|
+
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
2592
|
+
Promise.resolve().then(() => {
|
|
2593
|
+
this.flushMicroTaskExists = false;
|
|
2773
2594
|
this.flush();
|
|
2774
|
-
}
|
|
2775
|
-
this.flushMicroTaskExists = true;
|
|
2776
|
-
// Queue a microtask to detect the end of the turn and force a flush.
|
|
2777
|
-
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
2778
|
-
Promise.resolve().then(() => {
|
|
2779
|
-
this.flushMicroTaskExists = false;
|
|
2780
|
-
this.flush();
|
|
2781
|
-
});
|
|
2782
|
-
}
|
|
2595
|
+
}).catch((error) => { this.closeFn(error as GenericError) });
|
|
2783
2596
|
}
|
|
2784
2597
|
} catch (error) {
|
|
2785
2598
|
this.closeFn(error as GenericError);
|
|
@@ -2796,7 +2609,7 @@ export class ContainerRuntime extends TypedEventEmitter<IContainerRuntimeEvents>
|
|
|
2796
2609
|
assert(this.connected, 0x133 /* "Container disconnected when trying to submit system message" */);
|
|
2797
2610
|
|
|
2798
2611
|
// System message should not be sent in the middle of the batch.
|
|
2799
|
-
assert(this.
|
|
2612
|
+
assert(this.outbox.isEmpty, 0x3d4 /* System op in the middle of a batch */);
|
|
2800
2613
|
|
|
2801
2614
|
// back-compat: ADO #1385: Make this call unconditional in the future
|
|
2802
2615
|
return this.context.submitSummaryFn !== undefined
|
|
@@ -2908,12 +2721,12 @@ export class ContainerRuntime extends TypedEventEmitter<IContainerRuntimeEvents>
|
|
|
2908
2721
|
|
|
2909
2722
|
const latestSnapshotRefSeq = await seqFromTree(fetchResult.snapshotTree, readAndParseBlob);
|
|
2910
2723
|
summaryLogger.sendTelemetryEvent(
|
|
2911
|
-
|
|
2912
|
-
|
|
2913
|
-
|
|
2914
|
-
|
|
2915
|
-
|
|
2916
|
-
|
|
2724
|
+
{
|
|
2725
|
+
eventName: "LatestSummaryRetrieved",
|
|
2726
|
+
ackHandle,
|
|
2727
|
+
lastSequenceNumber: latestSnapshotRefSeq,
|
|
2728
|
+
targetSequenceNumber: summaryRefSeq,
|
|
2729
|
+
});
|
|
2917
2730
|
|
|
2918
2731
|
// In case we had to retrieve the latest snapshot and it is different than summaryRefSeq,
|
|
2919
2732
|
// wait for the delta manager to catch up before refreshing the latest Summary.
|
package/src/dataStoreContext.ts
CHANGED
|
@@ -87,7 +87,7 @@ import {
|
|
|
87
87
|
getAttributesFormatVersion,
|
|
88
88
|
getFluidDataStoreAttributes,
|
|
89
89
|
} from "./summaryFormat";
|
|
90
|
-
import { throwOnTombstoneUsageKey } from "./
|
|
90
|
+
import { throwOnTombstoneUsageKey } from "./garbageCollectionConstants";
|
|
91
91
|
import { summarizerClientType } from "./summarizerClientElection";
|
|
92
92
|
|
|
93
93
|
function createAttributes(
|
package/src/dataStores.ts
CHANGED
|
@@ -54,7 +54,8 @@ import {
|
|
|
54
54
|
} from "./dataStoreContext";
|
|
55
55
|
import { IContainerRuntimeMetadata, nonDataStorePaths, rootHasIsolatedChannels } from "./summaryFormat";
|
|
56
56
|
import { IDataStoreAliasMessage, isDataStoreAliasMessage } from "./dataStore";
|
|
57
|
-
import {
|
|
57
|
+
import { GCNodeType } from "./garbageCollection";
|
|
58
|
+
import { throwOnTombstoneUsageKey } from "./garbageCollectionConstants";
|
|
58
59
|
import { summarizerClientType } from "./summarizerClientElection";
|
|
59
60
|
|
|
60
61
|
type PendingAliasResolve = (success: boolean) => void;
|