@fluidframework/container-runtime 0.52.0 → 0.54.0-47413
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/containerHandleContext.d.ts +0 -1
- package/dist/containerHandleContext.d.ts.map +1 -1
- package/dist/containerHandleContext.js +0 -1
- package/dist/containerHandleContext.js.map +1 -1
- package/dist/containerRuntime.d.ts +43 -19
- package/dist/containerRuntime.d.ts.map +1 -1
- package/dist/containerRuntime.js +201 -111
- package/dist/containerRuntime.js.map +1 -1
- package/dist/dataStoreContext.d.ts +33 -4
- package/dist/dataStoreContext.d.ts.map +1 -1
- package/dist/dataStoreContext.js +45 -17
- package/dist/dataStoreContext.js.map +1 -1
- package/dist/dataStores.d.ts +14 -10
- package/dist/dataStores.d.ts.map +1 -1
- package/dist/dataStores.js +73 -41
- package/dist/dataStores.js.map +1 -1
- package/dist/garbageCollection.d.ts +82 -15
- package/dist/garbageCollection.d.ts.map +1 -1
- package/dist/garbageCollection.js +359 -26
- package/dist/garbageCollection.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +11 -2
- package/dist/index.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 +0 -1
- package/dist/pendingStateManager.d.ts.map +1 -1
- package/dist/pendingStateManager.js +0 -36
- package/dist/pendingStateManager.js.map +1 -1
- package/dist/runningSummarizer.d.ts +3 -2
- package/dist/runningSummarizer.d.ts.map +1 -1
- package/dist/runningSummarizer.js +6 -6
- package/dist/runningSummarizer.js.map +1 -1
- package/dist/summarizer.d.ts +23 -3
- package/dist/summarizer.d.ts.map +1 -1
- package/dist/summarizer.js +135 -45
- package/dist/summarizer.js.map +1 -1
- package/dist/summarizerTypes.d.ts +3 -10
- package/dist/summarizerTypes.d.ts.map +1 -1
- package/dist/summarizerTypes.js.map +1 -1
- package/dist/summaryFormat.d.ts +10 -1
- package/dist/summaryFormat.d.ts.map +1 -1
- package/dist/summaryFormat.js +2 -1
- package/dist/summaryFormat.js.map +1 -1
- package/dist/summaryGenerator.d.ts.map +1 -1
- package/dist/summaryGenerator.js +1 -3
- package/dist/summaryGenerator.js.map +1 -1
- package/dist/summaryManager.d.ts +0 -15
- package/dist/summaryManager.d.ts.map +1 -1
- package/dist/summaryManager.js +1 -35
- package/dist/summaryManager.js.map +1 -1
- package/lib/containerHandleContext.d.ts +0 -1
- package/lib/containerHandleContext.d.ts.map +1 -1
- package/lib/containerHandleContext.js +0 -1
- package/lib/containerHandleContext.js.map +1 -1
- package/lib/containerRuntime.d.ts +43 -19
- package/lib/containerRuntime.d.ts.map +1 -1
- package/lib/containerRuntime.js +206 -117
- package/lib/containerRuntime.js.map +1 -1
- package/lib/dataStoreContext.d.ts +33 -4
- package/lib/dataStoreContext.d.ts.map +1 -1
- package/lib/dataStoreContext.js +45 -17
- package/lib/dataStoreContext.js.map +1 -1
- package/lib/dataStores.d.ts +14 -10
- package/lib/dataStores.d.ts.map +1 -1
- package/lib/dataStores.js +76 -44
- package/lib/dataStores.js.map +1 -1
- package/lib/garbageCollection.d.ts +82 -15
- package/lib/garbageCollection.d.ts.map +1 -1
- package/lib/garbageCollection.js +361 -28
- package/lib/garbageCollection.js.map +1 -1
- package/lib/index.d.ts +2 -2
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +2 -1
- package/lib/index.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 +0 -1
- package/lib/pendingStateManager.d.ts.map +1 -1
- package/lib/pendingStateManager.js +0 -36
- package/lib/pendingStateManager.js.map +1 -1
- package/lib/runningSummarizer.d.ts +3 -2
- package/lib/runningSummarizer.d.ts.map +1 -1
- package/lib/runningSummarizer.js +6 -6
- package/lib/runningSummarizer.js.map +1 -1
- package/lib/summarizer.d.ts +23 -3
- package/lib/summarizer.d.ts.map +1 -1
- package/lib/summarizer.js +135 -45
- package/lib/summarizer.js.map +1 -1
- package/lib/summarizerTypes.d.ts +3 -10
- package/lib/summarizerTypes.d.ts.map +1 -1
- package/lib/summarizerTypes.js.map +1 -1
- package/lib/summaryFormat.d.ts +10 -1
- package/lib/summaryFormat.d.ts.map +1 -1
- package/lib/summaryFormat.js +1 -0
- package/lib/summaryFormat.js.map +1 -1
- package/lib/summaryGenerator.d.ts.map +1 -1
- package/lib/summaryGenerator.js +1 -3
- package/lib/summaryGenerator.js.map +1 -1
- package/lib/summaryManager.d.ts +0 -15
- package/lib/summaryManager.d.ts.map +1 -1
- package/lib/summaryManager.js +1 -34
- package/lib/summaryManager.js.map +1 -1
- package/package.json +14 -14
- package/src/containerHandleContext.ts +0 -1
- package/src/containerRuntime.ts +280 -140
- package/src/dataStoreContext.ts +59 -20
- package/src/dataStores.ts +116 -54
- package/src/garbageCollection.ts +492 -29
- package/src/index.ts +20 -2
- package/src/packageVersion.ts +1 -1
- package/src/pendingStateManager.ts +0 -43
- package/src/runningSummarizer.ts +12 -10
- package/src/summarizer.ts +154 -53
- package/src/summarizerTypes.ts +3 -11
- package/src/summaryFormat.ts +11 -1
- package/src/summaryGenerator.ts +2 -3
- package/src/summaryManager.ts +2 -49
- package/dist/localStorageFeatureGates.d.ts +0 -13
- package/dist/localStorageFeatureGates.d.ts.map +0 -1
- package/dist/localStorageFeatureGates.js +0 -31
- package/dist/localStorageFeatureGates.js.map +0 -1
- package/lib/localStorageFeatureGates.d.ts +0 -13
- package/lib/localStorageFeatureGates.d.ts.map +0 -1
- package/lib/localStorageFeatureGates.js +0 -27
- package/lib/localStorageFeatureGates.js.map +0 -1
- package/src/localStorageFeatureGates.ts +0 -27
package/lib/dataStores.d.ts
CHANGED
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
5
|
import { ITelemetryBaseLogger, IDisposable } from "@fluidframework/common-definitions";
|
|
6
|
-
import { ISequencedDocumentMessage, ISnapshotTree
|
|
7
|
-
import { CreateChildSummarizerNodeFn, CreateChildSummarizerNodeParam, IAttachMessage, IFluidDataStoreChannel, IFluidDataStoreContextDetached, IGarbageCollectionData, IInboundSignalMessage, ISummaryTreeWithStats } from "@fluidframework/runtime-definitions";
|
|
6
|
+
import { ISequencedDocumentMessage, ISnapshotTree } from "@fluidframework/protocol-definitions";
|
|
7
|
+
import { CreateChildSummarizerNodeFn, CreateChildSummarizerNodeParam, IAttachMessage, IFluidDataStoreChannel, IFluidDataStoreContextDetached, IGarbageCollectionData, IGarbageCollectionSummaryDetails, IInboundSignalMessage, ISummaryTreeWithStats } from "@fluidframework/runtime-definitions";
|
|
8
8
|
import { AttachState } from "@fluidframework/container-definitions";
|
|
9
9
|
import { DataStoreContexts } from "./dataStoreContexts";
|
|
10
10
|
import { ContainerRuntime } from "./containerRuntime";
|
|
@@ -21,13 +21,22 @@ export declare class DataStores implements IDisposable {
|
|
|
21
21
|
private readonly submitAttachFn;
|
|
22
22
|
private readonly getCreateChildSummarizerNodeFn;
|
|
23
23
|
private readonly deleteChildSummarizerNodeFn;
|
|
24
|
+
private readonly dataStoreChanged;
|
|
25
|
+
private readonly aliasMap;
|
|
24
26
|
private readonly contexts;
|
|
25
27
|
private readonly pendingAttach;
|
|
26
28
|
readonly attachOpFiredForDataStore: Set<string>;
|
|
27
29
|
private readonly logger;
|
|
28
30
|
private readonly disposeOnce;
|
|
29
|
-
|
|
31
|
+
readonly containerLoadStats: {
|
|
32
|
+
readonly containerLoadDataStoreCount: number;
|
|
33
|
+
readonly referencedDataStoreCount: number;
|
|
34
|
+
};
|
|
35
|
+
constructor(baseSnapshot: ISnapshotTree | undefined, runtime: ContainerRuntime, submitAttachFn: (attachContent: any) => void, getCreateChildSummarizerNodeFn: (id: string, createParam: CreateChildSummarizerNodeParam) => CreateChildSummarizerNodeFn, deleteChildSummarizerNodeFn: (id: string) => void, baseLogger: ITelemetryBaseLogger, getDataStoreBaseGCDetails: () => Promise<Map<string, IGarbageCollectionSummaryDetails>>, dataStoreChanged: (id: string) => void, aliasMap: Map<string, string>, contexts?: DataStoreContexts);
|
|
36
|
+
aliases(): ReadonlyMap<string, string>;
|
|
30
37
|
processAttachMessage(message: ISequencedDocumentMessage, local: boolean): void;
|
|
38
|
+
processAliasMessage(message: ISequencedDocumentMessage, localOpMetadata: unknown, local: boolean): void;
|
|
39
|
+
private processAliasMessageCore;
|
|
31
40
|
bindFluidDataStore(fluidDataStoreRuntime: IFluidDataStoreChannel): void;
|
|
32
41
|
createDetachedDataStoreCore(pkg: Readonly<string[]>, isRoot: boolean, id?: string): IFluidDataStoreContextDetached;
|
|
33
42
|
_createFluidDataStoreContext(pkg: string[], id: string, isRoot: boolean, props?: any): LocalFluidDataStoreContext;
|
|
@@ -41,19 +50,14 @@ export declare class DataStores implements IDisposable {
|
|
|
41
50
|
processSignal(address: string, message: IInboundSignalMessage, local: boolean): void;
|
|
42
51
|
setConnectionState(connected: boolean, clientId?: string): void;
|
|
43
52
|
setAttachState(attachState: AttachState.Attaching | AttachState.Attached): void;
|
|
44
|
-
/**
|
|
45
|
-
* Notifies this object to take the snapshot of the container.
|
|
46
|
-
* @deprecated - Use summarize to get summary of the container runtime.
|
|
47
|
-
*/
|
|
48
|
-
snapshot(): Promise<ITreeEntry[]>;
|
|
49
53
|
get size(): number;
|
|
50
54
|
summarize(fullTree: boolean, trackState: boolean): Promise<ISummaryTreeWithStats>;
|
|
51
55
|
createSummary(): ISummaryTreeWithStats;
|
|
52
56
|
/**
|
|
53
57
|
* Generates data used for garbage collection. It does the following:
|
|
54
58
|
* 1. Calls into each child data store context to get its GC data.
|
|
55
|
-
* 2.
|
|
56
|
-
*
|
|
59
|
+
* 2. Prefixes the child context's id to the GC nodes in the child's GC data. This makes sure that the node can be
|
|
60
|
+
* identified as belonging to the child.
|
|
57
61
|
* 3. Adds a GC node for this channel to the nodes received from the children. All these nodes together represent
|
|
58
62
|
* the GC data of this channel.
|
|
59
63
|
* @param fullGC - true to bypass optimizations and force full generation of GC data.
|
package/lib/dataStores.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dataStores.d.ts","sourceRoot":"","sources":["../src/dataStores.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAoB,oBAAoB,EAAE,WAAW,EAAE,MAAM,oCAAoC,CAAC;AAEzG,OAAO,EACH,yBAAyB,EACzB,aAAa,
|
|
1
|
+
{"version":3,"file":"dataStores.d.ts","sourceRoot":"","sources":["../src/dataStores.ts"],"names":[],"mappings":"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"}
|
package/lib/dataStores.js
CHANGED
|
@@ -3,30 +3,40 @@
|
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
5
|
import { DataCorruptionError, extractSafePropertiesFromMessage } from "@fluidframework/container-utils";
|
|
6
|
-
import { SummaryType, } from "@fluidframework/protocol-definitions";
|
|
7
6
|
import { channelsTreeName, CreateSummarizerNodeSource, } from "@fluidframework/runtime-definitions";
|
|
8
|
-
import { convertSnapshotTreeToSummaryTree,
|
|
7
|
+
import { convertSnapshotTreeToSummaryTree, convertToSummaryTree, create404Response, responseToException, SummaryTreeBuilder, } from "@fluidframework/runtime-utils";
|
|
9
8
|
import { ChildLogger, TelemetryDataTag } from "@fluidframework/telemetry-utils";
|
|
10
9
|
import { AttachState } from "@fluidframework/container-definitions";
|
|
11
10
|
import { BlobCacheStorageService, buildSnapshotTree } from "@fluidframework/driver-utils";
|
|
12
|
-
import { assert, Lazy } from "@fluidframework/common-utils";
|
|
11
|
+
import { assert, Lazy, LazyPromise } from "@fluidframework/common-utils";
|
|
13
12
|
import { v4 as uuid } from "uuid";
|
|
14
|
-
import {
|
|
15
|
-
import { GCDataBuilder, getChildNodesUsedRoutes } from "@fluidframework/garbage-collector";
|
|
13
|
+
import { GCDataBuilder, unpackChildNodesUsedRoutes } from "@fluidframework/garbage-collector";
|
|
16
14
|
import { DataStoreContexts } from "./dataStoreContexts";
|
|
17
15
|
import { RemotedFluidDataStoreContext, LocalFluidDataStoreContext, createAttributesBlob, LocalDetachedFluidDataStoreContext, } from "./dataStoreContext";
|
|
18
16
|
import { nonDataStorePaths, rootHasIsolatedChannels } from "./summaryFormat";
|
|
17
|
+
/**
|
|
18
|
+
* Type guard that returns true if the given alias message is actually an instance of
|
|
19
|
+
* a class which implements @see IDataStoreAliasMessage
|
|
20
|
+
* @param maybeDataStoreAliasMessage - message object to be validated
|
|
21
|
+
* @returns True if the @see IDataStoreAliasMessage is fully implemented, false otherwise
|
|
22
|
+
*/
|
|
23
|
+
const isDataStoreAliasMessage = (maybeDataStoreAliasMessage) => {
|
|
24
|
+
return typeof (maybeDataStoreAliasMessage === null || maybeDataStoreAliasMessage === void 0 ? void 0 : maybeDataStoreAliasMessage.internalId) === "string"
|
|
25
|
+
&& typeof (maybeDataStoreAliasMessage === null || maybeDataStoreAliasMessage === void 0 ? void 0 : maybeDataStoreAliasMessage.alias) === "string";
|
|
26
|
+
};
|
|
19
27
|
/**
|
|
20
28
|
* This class encapsulates data store handling. Currently it is only used by the container runtime,
|
|
21
29
|
* but eventually could be hosted on any channel once we formalize the channel api boundary.
|
|
22
30
|
*/
|
|
23
31
|
export class DataStores {
|
|
24
|
-
constructor(baseSnapshot, runtime, submitAttachFn, getCreateChildSummarizerNodeFn, deleteChildSummarizerNodeFn, baseLogger, contexts = new DataStoreContexts(baseLogger)) {
|
|
32
|
+
constructor(baseSnapshot, runtime, submitAttachFn, getCreateChildSummarizerNodeFn, deleteChildSummarizerNodeFn, baseLogger, getDataStoreBaseGCDetails, dataStoreChanged, aliasMap, contexts = new DataStoreContexts(baseLogger)) {
|
|
25
33
|
this.baseSnapshot = baseSnapshot;
|
|
26
34
|
this.runtime = runtime;
|
|
27
35
|
this.submitAttachFn = submitAttachFn;
|
|
28
36
|
this.getCreateChildSummarizerNodeFn = getCreateChildSummarizerNodeFn;
|
|
29
37
|
this.deleteChildSummarizerNodeFn = deleteChildSummarizerNodeFn;
|
|
38
|
+
this.dataStoreChanged = dataStoreChanged;
|
|
39
|
+
this.aliasMap = aliasMap;
|
|
30
40
|
this.contexts = contexts;
|
|
31
41
|
// Stores tracked by the Domain
|
|
32
42
|
this.pendingAttach = new Map();
|
|
@@ -35,6 +45,14 @@ export class DataStores {
|
|
|
35
45
|
this.disposeOnce = new Lazy(() => this.contexts.dispose());
|
|
36
46
|
this.dispose = () => this.disposeOnce.value;
|
|
37
47
|
this.logger = ChildLogger.create(baseLogger);
|
|
48
|
+
const baseDataStoresGCDetailsP = new LazyPromise(async () => {
|
|
49
|
+
return getDataStoreBaseGCDetails();
|
|
50
|
+
});
|
|
51
|
+
// Returns the base summary GC details for the data store with the given id.
|
|
52
|
+
const dataStoreBaseGCDetails = async (dataStoreId) => {
|
|
53
|
+
const baseGCDetails = await baseDataStoresGCDetailsP;
|
|
54
|
+
return baseGCDetails.get(dataStoreId);
|
|
55
|
+
};
|
|
38
56
|
// Extract stores stored inside the snapshot
|
|
39
57
|
const fluidDataStores = new Map();
|
|
40
58
|
if (baseSnapshot) {
|
|
@@ -52,7 +70,7 @@ export class DataStores {
|
|
|
52
70
|
}
|
|
53
71
|
// If we have a detached container, then create local data store contexts.
|
|
54
72
|
if (this.runtime.attachState !== AttachState.Detached) {
|
|
55
|
-
dataStoreContext = new RemotedFluidDataStoreContext(key, value, this.runtime, this.runtime.storage, this.runtime.scope, this.getCreateChildSummarizerNodeFn(key, { type: CreateSummarizerNodeSource.FromSummary }));
|
|
73
|
+
dataStoreContext = new RemotedFluidDataStoreContext(key, value, async () => dataStoreBaseGCDetails(key), this.runtime, this.runtime.storage, this.runtime.scope, this.getCreateChildSummarizerNodeFn(key, { type: CreateSummarizerNodeSource.FromSummary }));
|
|
56
74
|
}
|
|
57
75
|
else {
|
|
58
76
|
if (typeof value !== "object") {
|
|
@@ -63,11 +81,13 @@ export class DataStores {
|
|
|
63
81
|
}
|
|
64
82
|
this.contexts.addBoundOrRemoted(dataStoreContext);
|
|
65
83
|
}
|
|
66
|
-
this.
|
|
67
|
-
|
|
68
|
-
dataStoreCount: fluidDataStores.size,
|
|
84
|
+
this.containerLoadStats = {
|
|
85
|
+
containerLoadDataStoreCount: fluidDataStores.size,
|
|
69
86
|
referencedDataStoreCount: fluidDataStores.size - unreferencedDataStoreCount,
|
|
70
|
-
}
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
aliases() {
|
|
90
|
+
return this.aliasMap;
|
|
71
91
|
}
|
|
72
92
|
processAttachMessage(message, local) {
|
|
73
93
|
var _a, _b;
|
|
@@ -96,19 +116,54 @@ export class DataStores {
|
|
|
96
116
|
// Include the type of attach message which is the pkg of the store to be
|
|
97
117
|
// used by RemotedFluidDataStoreContext in case it is not in the snapshot.
|
|
98
118
|
const pkg = [attachMessage.type];
|
|
99
|
-
const remotedFluidDataStoreContext = new RemotedFluidDataStoreContext(attachMessage.id, snapshotTree,
|
|
119
|
+
const remotedFluidDataStoreContext = new RemotedFluidDataStoreContext(attachMessage.id, snapshotTree,
|
|
120
|
+
// New data stores begin with empty GC details since GC hasn't run on them yet.
|
|
121
|
+
async () => { return {}; }, this.runtime, new BlobCacheStorageService(this.runtime.storage, flatBlobs), this.runtime.scope, this.getCreateChildSummarizerNodeFn(attachMessage.id, {
|
|
100
122
|
type: CreateSummarizerNodeSource.FromAttach,
|
|
101
123
|
sequenceNumber: message.sequenceNumber,
|
|
102
124
|
snapshot: (_b = attachMessage.snapshot) !== null && _b !== void 0 ? _b : {
|
|
103
125
|
entries: [createAttributesBlob(pkg, true /* isRootDataStore */, this.runtime.disableIsolatedChannels)],
|
|
104
126
|
},
|
|
105
127
|
}), pkg);
|
|
106
|
-
// Resolve pending gets and store off any new ones
|
|
107
128
|
this.contexts.addBoundOrRemoted(remotedFluidDataStoreContext);
|
|
108
129
|
// Equivalent of nextTick() - Prefetch once all current ops have completed
|
|
109
130
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
110
131
|
Promise.resolve().then(async () => remotedFluidDataStoreContext.realize());
|
|
111
132
|
}
|
|
133
|
+
processAliasMessage(message, localOpMetadata, local) {
|
|
134
|
+
const aliasMessage = message.contents;
|
|
135
|
+
if (!isDataStoreAliasMessage(aliasMessage)) {
|
|
136
|
+
throw new DataCorruptionError("malformedDataStoreAliasMessage", Object.assign({}, extractSafePropertiesFromMessage(message)));
|
|
137
|
+
}
|
|
138
|
+
const resolve = localOpMetadata;
|
|
139
|
+
const aliasResult = this.processAliasMessageCore(aliasMessage);
|
|
140
|
+
if (local) {
|
|
141
|
+
resolve(aliasResult);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
processAliasMessageCore(aliasMessage) {
|
|
145
|
+
const existingMapping = this.aliasMap.get(aliasMessage.alias);
|
|
146
|
+
if (existingMapping !== undefined) {
|
|
147
|
+
return false;
|
|
148
|
+
}
|
|
149
|
+
// Unlikely scenario, but we may receive an alias OP with the alias value
|
|
150
|
+
// equal to one of the ids supplied to `createRootDataStore` in the past
|
|
151
|
+
const maybeContextWithAliasAsId = this.contexts.get(aliasMessage.alias);
|
|
152
|
+
if (maybeContextWithAliasAsId !== undefined) {
|
|
153
|
+
return false;
|
|
154
|
+
}
|
|
155
|
+
const currentContext = this.contexts.get(aliasMessage.internalId);
|
|
156
|
+
if (currentContext === undefined) {
|
|
157
|
+
this.logger.sendErrorEvent({
|
|
158
|
+
eventName: "AliasFluidDataStoreNotFound",
|
|
159
|
+
fluidDataStoreId: aliasMessage.internalId,
|
|
160
|
+
});
|
|
161
|
+
return false;
|
|
162
|
+
}
|
|
163
|
+
this.aliasMap.set(aliasMessage.alias, currentContext.id);
|
|
164
|
+
currentContext.setRoot();
|
|
165
|
+
return true;
|
|
166
|
+
}
|
|
112
167
|
bindFluidDataStore(fluidDataStoreRuntime) {
|
|
113
168
|
const id = fluidDataStoreRuntime.id;
|
|
114
169
|
const localContext = this.contexts.getUnbound(id);
|
|
@@ -159,9 +214,13 @@ export class DataStores {
|
|
|
159
214
|
const context = this.contexts.get(envelope.address);
|
|
160
215
|
assert(!!context, 0x162 /* "There should be a store context for the op" */);
|
|
161
216
|
context.process(transformed, local, localMessageMetadata);
|
|
217
|
+
// Notify that a data store changed. This is used to detect if a deleted data store is being used.
|
|
218
|
+
this.dataStoreChanged(envelope.address);
|
|
162
219
|
}
|
|
163
220
|
async getDataStore(id, wait) {
|
|
164
|
-
|
|
221
|
+
var _a;
|
|
222
|
+
const internalId = (_a = this.aliasMap.get(id)) !== null && _a !== void 0 ? _a : id;
|
|
223
|
+
const context = await this.contexts.getBoundOrRemoted(internalId, wait);
|
|
165
224
|
if (context === undefined) {
|
|
166
225
|
// The requested data store does not exits. Throw a 404 response exception.
|
|
167
226
|
const request = { url: id };
|
|
@@ -211,33 +270,6 @@ export class DataStores {
|
|
|
211
270
|
}
|
|
212
271
|
}
|
|
213
272
|
}
|
|
214
|
-
/**
|
|
215
|
-
* Notifies this object to take the snapshot of the container.
|
|
216
|
-
* @deprecated - Use summarize to get summary of the container runtime.
|
|
217
|
-
*/
|
|
218
|
-
async snapshot() {
|
|
219
|
-
// Iterate over each store and ask it to snapshot
|
|
220
|
-
const fluidDataStoreSnapshotsP = Array.from(this.contexts).map(async ([fluidDataStoreId, value]) => {
|
|
221
|
-
const summaryTree = await value.summarize(true /* fullTree */, false /* trackState */);
|
|
222
|
-
assert(summaryTree.summary.type === SummaryType.Tree, 0x164 /* "summarize should always return a tree when fullTree is true" */);
|
|
223
|
-
// back-compat summary - Remove this once snapshot is removed.
|
|
224
|
-
const snapshot = convertSummaryTreeToITree(summaryTree.summary);
|
|
225
|
-
// If ID exists then previous commit is still valid
|
|
226
|
-
return {
|
|
227
|
-
fluidDataStoreId,
|
|
228
|
-
snapshot,
|
|
229
|
-
};
|
|
230
|
-
});
|
|
231
|
-
const entries = [];
|
|
232
|
-
// Add in module references to the store snapshots
|
|
233
|
-
const fluidDataStoreSnapshots = await Promise.all(fluidDataStoreSnapshotsP);
|
|
234
|
-
// Sort for better diffing of snapshots (in replay tool, used to find bugs in snapshotting logic)
|
|
235
|
-
fluidDataStoreSnapshots.sort((a, b) => a === null || a === void 0 ? void 0 : a.fluidDataStoreId.localeCompare(b.fluidDataStoreId));
|
|
236
|
-
for (const fluidDataStoreSnapshot of fluidDataStoreSnapshots) {
|
|
237
|
-
entries.push(new TreeTreeEntry(fluidDataStoreSnapshot.fluidDataStoreId, fluidDataStoreSnapshot.snapshot));
|
|
238
|
-
}
|
|
239
|
-
return entries;
|
|
240
|
-
}
|
|
241
273
|
get size() {
|
|
242
274
|
return this.contexts.size;
|
|
243
275
|
}
|
|
@@ -292,8 +324,8 @@ export class DataStores {
|
|
|
292
324
|
/**
|
|
293
325
|
* Generates data used for garbage collection. It does the following:
|
|
294
326
|
* 1. Calls into each child data store context to get its GC data.
|
|
295
|
-
* 2.
|
|
296
|
-
*
|
|
327
|
+
* 2. Prefixes the child context's id to the GC nodes in the child's GC data. This makes sure that the node can be
|
|
328
|
+
* identified as belonging to the child.
|
|
297
329
|
* 3. Adds a GC node for this channel to the nodes received from the children. All these nodes together represent
|
|
298
330
|
* the GC data of this channel.
|
|
299
331
|
* @param fullGC - true to bypass optimizations and force full generation of GC data.
|
|
@@ -326,7 +358,7 @@ export class DataStores {
|
|
|
326
358
|
updateUsedRoutes(usedRoutes, gcTimestamp) {
|
|
327
359
|
var _a;
|
|
328
360
|
// Get a map of data store ids to routes used in it.
|
|
329
|
-
const usedDataStoreRoutes =
|
|
361
|
+
const usedDataStoreRoutes = unpackChildNodesUsedRoutes(usedRoutes);
|
|
330
362
|
// Verify that the used routes are correct.
|
|
331
363
|
for (const [id] of usedDataStoreRoutes) {
|
|
332
364
|
assert(this.contexts.has(id), 0x167 /* "Used route does not belong to any known data store" */);
|
package/lib/dataStores.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dataStores.js","sourceRoot":"","sources":["../src/dataStores.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { ITelemetryLogger, ITelemetryBaseLogger, IDisposable } from \"@fluidframework/common-definitions\";\nimport { DataCorruptionError, extractSafePropertiesFromMessage } from \"@fluidframework/container-utils\";\nimport {\n ISequencedDocumentMessage,\n ISnapshotTree,\n ITreeEntry,\n SummaryType,\n} from \"@fluidframework/protocol-definitions\";\nimport {\n channelsTreeName,\n CreateChildSummarizerNodeFn,\n CreateChildSummarizerNodeParam,\n CreateSummarizerNodeSource,\n IAttachMessage,\n IEnvelope,\n IFluidDataStoreChannel,\n IFluidDataStoreContextDetached,\n IGarbageCollectionData,\n IInboundSignalMessage,\n InboundAttachMessage,\n ISummarizeResult,\n ISummaryTreeWithStats,\n} from \"@fluidframework/runtime-definitions\";\nimport {\n convertSnapshotTreeToSummaryTree,\n convertSummaryTreeToITree,\n convertToSummaryTree,\n create404Response,\n responseToException,\n SummaryTreeBuilder,\n} from \"@fluidframework/runtime-utils\";\nimport { ChildLogger, TelemetryDataTag } from \"@fluidframework/telemetry-utils\";\nimport { AttachState } from \"@fluidframework/container-definitions\";\nimport { BlobCacheStorageService, buildSnapshotTree } from \"@fluidframework/driver-utils\";\nimport { assert, Lazy } from \"@fluidframework/common-utils\";\nimport { v4 as uuid } from \"uuid\";\nimport { TreeTreeEntry } from \"@fluidframework/protocol-base\";\nimport { GCDataBuilder, getChildNodesUsedRoutes } from \"@fluidframework/garbage-collector\";\nimport { DataStoreContexts } from \"./dataStoreContexts\";\nimport { ContainerRuntime } from \"./containerRuntime\";\nimport {\n FluidDataStoreContext,\n RemotedFluidDataStoreContext,\n LocalFluidDataStoreContext,\n createAttributesBlob,\n LocalDetachedFluidDataStoreContext,\n} from \"./dataStoreContext\";\nimport { IContainerRuntimeMetadata, nonDataStorePaths, rootHasIsolatedChannels } from \"./summaryFormat\";\nimport { IUsedStateStats } from \"./garbageCollection\";\n\n /**\n * This class encapsulates data store handling. Currently it is only used by the container runtime,\n * but eventually could be hosted on any channel once we formalize the channel api boundary.\n */\nexport class DataStores implements IDisposable {\n // Stores tracked by the Domain\n private readonly pendingAttach = new Map<string, IAttachMessage>();\n // 0.24 back-compat attachingBeforeSummary\n public readonly attachOpFiredForDataStore = new Set<string>();\n\n private readonly logger: ITelemetryLogger;\n\n private readonly disposeOnce = new Lazy<void>(() => this.contexts.dispose());\n\n constructor(\n private readonly baseSnapshot: ISnapshotTree | undefined,\n private readonly runtime: ContainerRuntime,\n private readonly submitAttachFn: (attachContent: any) => void,\n private readonly getCreateChildSummarizerNodeFn:\n (id: string, createParam: CreateChildSummarizerNodeParam) => CreateChildSummarizerNodeFn,\n private readonly deleteChildSummarizerNodeFn: (id: string) => void,\n baseLogger: ITelemetryBaseLogger,\n private readonly contexts: DataStoreContexts = new DataStoreContexts(baseLogger),\n ) {\n this.logger = ChildLogger.create(baseLogger);\n // Extract stores stored inside the snapshot\n const fluidDataStores = new Map<string, ISnapshotTree>();\n\n if (baseSnapshot) {\n for (const [key, value] of Object.entries(baseSnapshot.trees)) {\n fluidDataStores.set(key, value);\n }\n }\n\n let unreferencedDataStoreCount = 0;\n // Create a context for each of them\n for (const [key, value] of fluidDataStores) {\n let dataStoreContext: FluidDataStoreContext;\n\n // counting number of unreferenced data stores\n if (value.unreferenced) {\n unreferencedDataStoreCount++;\n }\n // If we have a detached container, then create local data store contexts.\n if (this.runtime.attachState !== AttachState.Detached) {\n dataStoreContext = new RemotedFluidDataStoreContext(\n key,\n value,\n this.runtime,\n this.runtime.storage,\n this.runtime.scope,\n this.getCreateChildSummarizerNodeFn(key, { type: CreateSummarizerNodeSource.FromSummary }));\n } else {\n if (typeof value !== \"object\") {\n throw new Error(\"Snapshot should be there to load from!!\");\n }\n const snapshotTree = value;\n dataStoreContext = new LocalFluidDataStoreContext(\n key,\n undefined,\n this.runtime,\n this.runtime.storage,\n this.runtime.scope,\n this.getCreateChildSummarizerNodeFn(key, { type: CreateSummarizerNodeSource.FromSummary }),\n (cr: IFluidDataStoreChannel) => this.bindFluidDataStore(cr),\n snapshotTree,\n undefined,\n );\n }\n this.contexts.addBoundOrRemoted(dataStoreContext);\n }\n this.logger.sendTelemetryEvent({\n eventName: \"ContainerLoadStats\",\n dataStoreCount: fluidDataStores.size,\n referencedDataStoreCount: fluidDataStores.size - unreferencedDataStoreCount,\n });\n }\n\n public processAttachMessage(message: ISequencedDocumentMessage, local: boolean) {\n const attachMessage = message.contents as InboundAttachMessage;\n // The local object has already been attached\n if (local) {\n assert(this.pendingAttach.has(attachMessage.id),\n 0x15e /* \"Local object does not have matching attach message id\" */);\n this.contexts.get(attachMessage.id)?.emit(\"attached\");\n this.pendingAttach.delete(attachMessage.id);\n return;\n }\n\n // If a non-local operation then go and create the object, otherwise mark it as officially attached.\n if (this.contexts.has(attachMessage.id)) {\n // TODO: dataStoreId may require a different tag from PackageData #7488\n const error = new DataCorruptionError(\n \"duplicateDataStoreCreatedWithExistingId\",\n {\n ...extractSafePropertiesFromMessage(message),\n dataStoreId: {\n value: attachMessage.id,\n tag: TelemetryDataTag.PackageData,\n },\n },\n );\n throw error;\n }\n\n const flatBlobs = new Map<string, ArrayBufferLike>();\n let snapshotTree: ISnapshotTree | undefined;\n if (attachMessage.snapshot) {\n snapshotTree = buildSnapshotTree(attachMessage.snapshot.entries, flatBlobs);\n }\n\n // Include the type of attach message which is the pkg of the store to be\n // used by RemotedFluidDataStoreContext in case it is not in the snapshot.\n const pkg = [attachMessage.type];\n const remotedFluidDataStoreContext = new RemotedFluidDataStoreContext(\n attachMessage.id,\n snapshotTree,\n this.runtime,\n new BlobCacheStorageService(this.runtime.storage, flatBlobs),\n this.runtime.scope,\n this.getCreateChildSummarizerNodeFn(\n attachMessage.id,\n {\n type: CreateSummarizerNodeSource.FromAttach,\n sequenceNumber: message.sequenceNumber,\n snapshot: attachMessage.snapshot ?? {\n entries: [createAttributesBlob(\n pkg,\n true /* isRootDataStore */,\n this.runtime.disableIsolatedChannels,\n )],\n },\n }),\n pkg);\n\n // Resolve pending gets and store off any new ones\n this.contexts.addBoundOrRemoted(remotedFluidDataStoreContext);\n\n // Equivalent of nextTick() - Prefetch once all current ops have completed\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\n Promise.resolve().then(async () => remotedFluidDataStoreContext.realize());\n }\n\n public bindFluidDataStore(fluidDataStoreRuntime: IFluidDataStoreChannel): void {\n const id = fluidDataStoreRuntime.id;\n const localContext = this.contexts.getUnbound(id);\n assert(!!localContext, 0x15f /* \"Could not find unbound context to bind\" */);\n\n // If the container is detached, we don't need to send OP or add to pending attach because\n // we will summarize it while uploading the create new summary and make it known to other\n // clients.\n if (this.runtime.attachState !== AttachState.Detached) {\n localContext.emit(\"attaching\");\n const message = localContext.generateAttachMessage();\n\n this.pendingAttach.set(id, message);\n this.submitAttachFn(message);\n this.attachOpFiredForDataStore.add(id);\n }\n\n this.contexts.bind(fluidDataStoreRuntime.id);\n }\n\n public createDetachedDataStoreCore(\n pkg: Readonly<string[]>,\n isRoot: boolean,\n id = uuid()): IFluidDataStoreContextDetached\n {\n const context = new LocalDetachedFluidDataStoreContext(\n id,\n pkg,\n this.runtime,\n this.runtime.storage,\n this.runtime.scope,\n this.getCreateChildSummarizerNodeFn(id, { type: CreateSummarizerNodeSource.Local }),\n (cr: IFluidDataStoreChannel) => this.bindFluidDataStore(cr),\n isRoot,\n );\n this.contexts.addUnbound(context);\n return context;\n }\n\n public _createFluidDataStoreContext(pkg: string[], id: string, isRoot: boolean, props?: any) {\n const context = new LocalFluidDataStoreContext(\n id,\n pkg,\n this.runtime,\n this.runtime.storage,\n this.runtime.scope,\n this.getCreateChildSummarizerNodeFn(id, { type: CreateSummarizerNodeSource.Local }),\n (cr: IFluidDataStoreChannel) => this.bindFluidDataStore(cr),\n undefined,\n isRoot,\n props,\n );\n this.contexts.addUnbound(context);\n return context;\n }\n\n public get disposed() {return this.disposeOnce.evaluated;}\n public readonly dispose = () => this.disposeOnce.value;\n\n public resubmitDataStoreOp(content: any, localOpMetadata: unknown) {\n const envelope = content as IEnvelope;\n const context = this.contexts.get(envelope.address);\n assert(!!context, 0x160 /* \"There should be a store context for the op\" */);\n context.reSubmit(envelope.contents, localOpMetadata);\n }\n\n public async applyStashedOp(content: any): Promise<unknown> {\n const envelope = content as IEnvelope;\n const context = this.contexts.get(envelope.address);\n assert(!!context, 0x161 /* \"There should be a store context for the op\" */);\n return context.applyStashedOp(envelope.contents);\n }\n\n public async applyStashedAttachOp(message: IAttachMessage) {\n this.pendingAttach.set(message.id, message);\n // eslint-disable-next-line @typescript-eslint/consistent-type-assertions\n this.processAttachMessage({ contents: message } as ISequencedDocumentMessage, false);\n }\n\n public processFluidDataStoreOp(message: ISequencedDocumentMessage, local: boolean, localMessageMetadata: unknown) {\n const envelope = message.contents as IEnvelope;\n const transformed = { ...message, contents: envelope.contents };\n const context = this.contexts.get(envelope.address);\n assert(!!context, 0x162 /* \"There should be a store context for the op\" */);\n context.process(transformed, local, localMessageMetadata);\n }\n\n public async getDataStore(id: string, wait: boolean): Promise<FluidDataStoreContext> {\n const context = await this.contexts.getBoundOrRemoted(id, wait);\n\n if (context === undefined) {\n // The requested data store does not exits. Throw a 404 response exception.\n const request = { url: id };\n throw responseToException(create404Response(request), request);\n }\n\n return context;\n }\n\n public processSignal(address: string, message: IInboundSignalMessage, local: boolean) {\n const context = this.contexts.get(address);\n if (!context) {\n // Attach message may not have been processed yet\n assert(!local, 0x163 /* \"Missing datastore for local signal\" */);\n this.logger.sendTelemetryEvent({\n eventName: \"SignalFluidDataStoreNotFound\",\n fluidDataStoreId: address,\n });\n return;\n }\n\n context.processSignal(message, local);\n }\n\n public setConnectionState(connected: boolean, clientId?: string) {\n for (const [fluidDataStore, context] of this.contexts) {\n try {\n context.setConnectionState(connected, clientId);\n } catch (error) {\n this.logger.sendErrorEvent({\n eventName: \"SetConnectionStateError\",\n clientId,\n fluidDataStore,\n }, error);\n }\n }\n }\n\n public setAttachState(attachState: AttachState.Attaching | AttachState.Attached): void {\n let eventName: \"attaching\" | \"attached\";\n if (attachState === AttachState.Attaching) {\n eventName = \"attaching\";\n } else {\n eventName = \"attached\";\n }\n for (const [,context] of this.contexts) {\n // Fire only for bounded stores.\n if (!this.contexts.isNotBound(context.id)) {\n context.emit(eventName);\n }\n }\n }\n\n /**\n * Notifies this object to take the snapshot of the container.\n * @deprecated - Use summarize to get summary of the container runtime.\n */\n public async snapshot(): Promise<ITreeEntry[]> {\n // Iterate over each store and ask it to snapshot\n const fluidDataStoreSnapshotsP = Array.from(this.contexts).map(async ([fluidDataStoreId, value]) => {\n const summaryTree = await value.summarize(true /* fullTree */, false /* trackState */);\n assert(\n summaryTree.summary.type === SummaryType.Tree,\n 0x164 /* \"summarize should always return a tree when fullTree is true\" */);\n // back-compat summary - Remove this once snapshot is removed.\n const snapshot = convertSummaryTreeToITree(summaryTree.summary);\n\n // If ID exists then previous commit is still valid\n return {\n fluidDataStoreId,\n snapshot,\n };\n });\n\n const entries: ITreeEntry[] = [];\n\n // Add in module references to the store snapshots\n const fluidDataStoreSnapshots = await Promise.all(fluidDataStoreSnapshotsP);\n\n // Sort for better diffing of snapshots (in replay tool, used to find bugs in snapshotting logic)\n fluidDataStoreSnapshots.sort((a, b) => a?.fluidDataStoreId.localeCompare(b.fluidDataStoreId));\n\n for (const fluidDataStoreSnapshot of fluidDataStoreSnapshots) {\n entries.push(new TreeTreeEntry(\n fluidDataStoreSnapshot.fluidDataStoreId,\n fluidDataStoreSnapshot.snapshot,\n ));\n }\n return entries;\n }\n\n public get size(): number {\n return this.contexts.size;\n }\n\n public async summarize(fullTree: boolean, trackState: boolean): Promise<ISummaryTreeWithStats> {\n const summaryBuilder = new SummaryTreeBuilder();\n\n // Iterate over each store and ask it to snapshot\n await Promise.all(Array.from(this.contexts)\n .filter(([_, context]) => {\n // Summarizer works only with clients with no local changes!\n assert(context.attachState !== AttachState.Attaching,\n 0x165 /* \"Summarizer cannot work if client has local changes\" */);\n return context.attachState === AttachState.Attached;\n }).map(async ([contextId, context]) => {\n const contextSummary = await context.summarize(fullTree, trackState);\n summaryBuilder.addWithStats(contextId, contextSummary);\n }));\n\n return summaryBuilder.getSummaryTree();\n }\n\n public createSummary(): ISummaryTreeWithStats {\n const builder = new SummaryTreeBuilder();\n // Attaching graph of some stores can cause other stores to get bound too.\n // So keep taking summary until no new stores get bound.\n let notBoundContextsLength: number;\n do {\n const builderTree = builder.summary.tree;\n notBoundContextsLength = this.contexts.notBoundLength();\n // Iterate over each data store and ask it to snapshot\n Array.from(this.contexts)\n .filter(([key, _]) =>\n // Take summary of bounded data stores only, make sure we haven't summarized them already\n // and no attach op has been fired for that data store because for loader versions <= 0.24\n // we set attach state as \"attaching\" before taking createNew summary.\n !(this.contexts.isNotBound(key)\n || builderTree[key]\n || this.attachOpFiredForDataStore.has(key)),\n )\n .map(([key, value]) => {\n let dataStoreSummary: ISummarizeResult;\n if (value.isLoaded) {\n const snapshot = value.generateAttachMessage().snapshot;\n dataStoreSummary = convertToSummaryTree(snapshot, true);\n } else {\n // If this data store is not yet loaded, then there should be no changes in the snapshot from\n // which it was created as it is detached container. So just use the previous snapshot.\n assert(!!this.baseSnapshot,\n 0x166 /* \"BaseSnapshot should be there as detached container loaded from snapshot\" */);\n dataStoreSummary = convertSnapshotTreeToSummaryTree(this.baseSnapshot.trees[key]);\n }\n builder.addWithStats(key, dataStoreSummary);\n });\n } while (notBoundContextsLength !== this.contexts.notBoundLength());\n\n return builder.getSummaryTree();\n }\n\n /**\n * Generates data used for garbage collection. It does the following:\n * 1. Calls into each child data store context to get its GC data.\n * 2. Prefixs the child context's id to the GC nodes in the child's GC data. This makes sure that the node can be\n * idenfied as belonging to the child.\n * 3. Adds a GC node for this channel to the nodes received from the children. All these nodes together represent\n * the GC data of this channel.\n * @param fullGC - true to bypass optimizations and force full generation of GC data.\n */\n public async getGCData(fullGC: boolean = false): Promise<IGarbageCollectionData> {\n const builder = new GCDataBuilder();\n // Iterate over each store and get their GC data.\n await Promise.all(Array.from(this.contexts)\n .filter(([_, context]) => {\n // Get GC data only for attached contexts. Detached contexts are not connected in the GC reference\n // graph so any references they might have won't be connected as well.\n return context.attachState === AttachState.Attached;\n }).map(async ([contextId, context]) => {\n const contextGCData = await context.getGCData(fullGC);\n // Prefix the child's id to the ids of its GC nodes so they can be identified as belonging to the child.\n // This also gradually builds the id of each node to be a path from the root.\n builder.prefixAndAddNodes(contextId, contextGCData.gcNodes);\n }));\n\n // Get the outbound routes and add a GC node for this channel.\n builder.addNode(\"/\", await this.getOutboundRoutes());\n return builder.getGCData();\n }\n\n /**\n * After GC has run, called to notify this Container's data stores of routes that are used in it.\n * @param usedRoutes - The routes that are used in all data stores in this Container.\n * @param gcTimestamp - The time when GC was run that generated these used routes. If any node node becomes\n * unreferenced as part of this GC run, this should be used to update the time when it happens.\n * @returns the statistics of the used state of the data stores.\n */\n public updateUsedRoutes(usedRoutes: string[], gcTimestamp?: number): IUsedStateStats {\n // Get a map of data store ids to routes used in it.\n const usedDataStoreRoutes = getChildNodesUsedRoutes(usedRoutes);\n\n // Verify that the used routes are correct.\n for (const [id] of usedDataStoreRoutes) {\n assert(this.contexts.has(id), 0x167 /* \"Used route does not belong to any known data store\" */);\n }\n\n // Update the used routes in each data store. Used routes is empty for unused data stores.\n for (const [contextId, context] of this.contexts) {\n context.updateUsedRoutes(usedDataStoreRoutes.get(contextId) ?? [], gcTimestamp);\n }\n\n // Return the number of data stores that are unused.\n const dataStoreCount = this.contexts.size;\n return {\n totalNodeCount: dataStoreCount,\n unusedNodeCount: dataStoreCount - usedDataStoreRoutes.size,\n };\n }\n\n /**\n * When running GC in test mode, this is called to delete objects whose routes are unused. This enables testing\n * scenarios with accessing deleted content.\n * @param unusedRoutes - The routes that are unused in all data stores in this Container.\n */\n public deleteUnusedRoutes(unusedRoutes: string[]) {\n for (const route of unusedRoutes) {\n const dataStoreId = route.split(\"/\")[1];\n // Delete the contexts of unused data stores.\n this.contexts.delete(dataStoreId);\n // Delete the summarizer node of the unused data stores.\n this.deleteChildSummarizerNodeFn(dataStoreId);\n }\n }\n\n /**\n * Returns the outbound routes of this channel. Only root data stores are considered referenced and their paths are\n * part of outbound routes.\n */\n private async getOutboundRoutes(): Promise<string[]> {\n const outboundRoutes: string[] = [];\n for (const [contextId, context] of this.contexts) {\n const isRootDataStore = await context.isRoot();\n if (isRootDataStore) {\n outboundRoutes.push(`/${contextId}`);\n }\n }\n return outboundRoutes;\n }\n}\n\nexport function getSummaryForDatastores(\n snapshot: ISnapshotTree | undefined,\n metadata?: IContainerRuntimeMetadata,\n): ISnapshotTree | undefined {\n if (!snapshot) {\n return undefined;\n }\n\n if (rootHasIsolatedChannels(metadata)) {\n const datastoresSnapshot = snapshot.trees[channelsTreeName];\n assert(!!datastoresSnapshot, 0x168 /* `expected ${channelsTreeName} tree in snapshot` */);\n return datastoresSnapshot;\n } else {\n // back-compat: strip out all non-datastore paths before giving to DataStores object.\n const datastoresTrees: ISnapshotTree[\"trees\"] = {};\n for (const [key, value] of Object.entries(snapshot.trees)) {\n if (!nonDataStorePaths.includes(key)) {\n datastoresTrees[key] = value;\n }\n }\n return {\n ...snapshot,\n trees: datastoresTrees,\n };\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"dataStores.js","sourceRoot":"","sources":["../src/dataStores.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { ITelemetryLogger, ITelemetryBaseLogger, IDisposable } from \"@fluidframework/common-definitions\";\nimport { DataCorruptionError, extractSafePropertiesFromMessage } from \"@fluidframework/container-utils\";\nimport {\n ISequencedDocumentMessage,\n ISnapshotTree,\n} from \"@fluidframework/protocol-definitions\";\nimport {\n channelsTreeName,\n CreateChildSummarizerNodeFn,\n CreateChildSummarizerNodeParam,\n CreateSummarizerNodeSource,\n IAttachMessage,\n IEnvelope,\n IFluidDataStoreChannel,\n IFluidDataStoreContextDetached,\n IGarbageCollectionData,\n IGarbageCollectionSummaryDetails,\n IInboundSignalMessage,\n InboundAttachMessage,\n ISummarizeResult,\n ISummaryTreeWithStats,\n} from \"@fluidframework/runtime-definitions\";\nimport {\n convertSnapshotTreeToSummaryTree,\n convertToSummaryTree,\n create404Response,\n responseToException,\n SummaryTreeBuilder,\n} from \"@fluidframework/runtime-utils\";\nimport { ChildLogger, TelemetryDataTag } from \"@fluidframework/telemetry-utils\";\nimport { AttachState } from \"@fluidframework/container-definitions\";\nimport { BlobCacheStorageService, buildSnapshotTree } from \"@fluidframework/driver-utils\";\nimport { assert, Lazy, LazyPromise } from \"@fluidframework/common-utils\";\nimport { v4 as uuid } from \"uuid\";\nimport { GCDataBuilder, unpackChildNodesUsedRoutes } from \"@fluidframework/garbage-collector\";\nimport { DataStoreContexts } from \"./dataStoreContexts\";\nimport { ContainerRuntime } from \"./containerRuntime\";\nimport {\n FluidDataStoreContext,\n RemotedFluidDataStoreContext,\n LocalFluidDataStoreContext,\n createAttributesBlob,\n LocalDetachedFluidDataStoreContext,\n} from \"./dataStoreContext\";\nimport { IContainerRuntimeMetadata, nonDataStorePaths, rootHasIsolatedChannels } from \"./summaryFormat\";\nimport { IUsedStateStats } from \"./garbageCollection\";\n\ntype PendingAliasResolve = (success: boolean) => void;\n\n/**\n * Interface for an op to be used for assigning an\n * alias to a datastore\n */\ninterface IDataStoreAliasMessage {\n /** The internal id of the datastore */\n readonly internalId: string;\n /** The alias name to be assigned to the datastore */\n readonly alias: string;\n}\n\n/**\n * Type guard that returns true if the given alias message is actually an instance of\n * a class which implements @see IDataStoreAliasMessage\n * @param maybeDataStoreAliasMessage - message object to be validated\n * @returns True if the @see IDataStoreAliasMessage is fully implemented, false otherwise\n */\nconst isDataStoreAliasMessage = (\n maybeDataStoreAliasMessage: any,\n): maybeDataStoreAliasMessage is IDataStoreAliasMessage => {\n return typeof maybeDataStoreAliasMessage?.internalId === \"string\"\n && typeof maybeDataStoreAliasMessage?.alias === \"string\";\n};\n\n /**\n * This class encapsulates data store handling. Currently it is only used by the container runtime,\n * but eventually could be hosted on any channel once we formalize the channel api boundary.\n */\nexport class DataStores implements IDisposable {\n // Stores tracked by the Domain\n private readonly pendingAttach = new Map<string, IAttachMessage>();\n // 0.24 back-compat attachingBeforeSummary\n public readonly attachOpFiredForDataStore = new Set<string>();\n\n private readonly logger: ITelemetryLogger;\n\n private readonly disposeOnce = new Lazy<void>(() => this.contexts.dispose());\n\n public readonly containerLoadStats: {\n // number of dataStores during loadContainer\n readonly containerLoadDataStoreCount: number;\n // number of unreferenced dataStores during loadContainer\n readonly referencedDataStoreCount: number;\n };\n\n constructor(\n private readonly baseSnapshot: ISnapshotTree | undefined,\n private readonly runtime: ContainerRuntime,\n private readonly submitAttachFn: (attachContent: any) => void,\n private readonly getCreateChildSummarizerNodeFn:\n (id: string, createParam: CreateChildSummarizerNodeParam) => CreateChildSummarizerNodeFn,\n private readonly deleteChildSummarizerNodeFn: (id: string) => void,\n baseLogger: ITelemetryBaseLogger,\n getDataStoreBaseGCDetails: () => Promise<Map<string, IGarbageCollectionSummaryDetails>>,\n private readonly dataStoreChanged: (id: string) => void,\n private readonly aliasMap: Map<string, string>,\n private readonly contexts: DataStoreContexts = new DataStoreContexts(baseLogger),\n ) {\n this.logger = ChildLogger.create(baseLogger);\n\n const baseDataStoresGCDetailsP = new LazyPromise(async () => {\n return getDataStoreBaseGCDetails();\n });\n // Returns the base summary GC details for the data store with the given id.\n const dataStoreBaseGCDetails = async (dataStoreId: string) => {\n const baseGCDetails = await baseDataStoresGCDetailsP;\n return baseGCDetails.get(dataStoreId);\n };\n\n // Extract stores stored inside the snapshot\n const fluidDataStores = new Map<string, ISnapshotTree>();\n if (baseSnapshot) {\n for (const [key, value] of Object.entries(baseSnapshot.trees)) {\n fluidDataStores.set(key, value);\n }\n }\n\n let unreferencedDataStoreCount = 0;\n // Create a context for each of them\n for (const [key, value] of fluidDataStores) {\n let dataStoreContext: FluidDataStoreContext;\n\n // counting number of unreferenced data stores\n if (value.unreferenced) {\n unreferencedDataStoreCount++;\n }\n // If we have a detached container, then create local data store contexts.\n if (this.runtime.attachState !== AttachState.Detached) {\n dataStoreContext = new RemotedFluidDataStoreContext(\n key,\n value,\n async () => dataStoreBaseGCDetails(key),\n this.runtime,\n this.runtime.storage,\n this.runtime.scope,\n this.getCreateChildSummarizerNodeFn(key, { type: CreateSummarizerNodeSource.FromSummary }));\n } else {\n if (typeof value !== \"object\") {\n throw new Error(\"Snapshot should be there to load from!!\");\n }\n const snapshotTree = value;\n dataStoreContext = new LocalFluidDataStoreContext(\n key,\n undefined,\n this.runtime,\n this.runtime.storage,\n this.runtime.scope,\n this.getCreateChildSummarizerNodeFn(key, { type: CreateSummarizerNodeSource.FromSummary }),\n (cr: IFluidDataStoreChannel) => this.bindFluidDataStore(cr),\n snapshotTree,\n undefined,\n );\n }\n this.contexts.addBoundOrRemoted(dataStoreContext);\n }\n this.containerLoadStats = {\n containerLoadDataStoreCount: fluidDataStores.size,\n referencedDataStoreCount: fluidDataStores.size - unreferencedDataStoreCount,\n };\n }\n\n public aliases(): ReadonlyMap<string, string> {\n return this.aliasMap;\n }\n\n public processAttachMessage(message: ISequencedDocumentMessage, local: boolean) {\n const attachMessage = message.contents as InboundAttachMessage;\n // The local object has already been attached\n if (local) {\n assert(this.pendingAttach.has(attachMessage.id),\n 0x15e /* \"Local object does not have matching attach message id\" */);\n this.contexts.get(attachMessage.id)?.emit(\"attached\");\n this.pendingAttach.delete(attachMessage.id);\n return;\n }\n\n // If a non-local operation then go and create the object, otherwise mark it as officially attached.\n if (this.contexts.has(attachMessage.id)) {\n // TODO: dataStoreId may require a different tag from PackageData #7488\n const error = new DataCorruptionError(\n \"duplicateDataStoreCreatedWithExistingId\",\n {\n ...extractSafePropertiesFromMessage(message),\n dataStoreId: {\n value: attachMessage.id,\n tag: TelemetryDataTag.PackageData,\n },\n },\n );\n throw error;\n }\n\n const flatBlobs = new Map<string, ArrayBufferLike>();\n let snapshotTree: ISnapshotTree | undefined;\n if (attachMessage.snapshot) {\n snapshotTree = buildSnapshotTree(attachMessage.snapshot.entries, flatBlobs);\n }\n\n // Include the type of attach message which is the pkg of the store to be\n // used by RemotedFluidDataStoreContext in case it is not in the snapshot.\n const pkg = [attachMessage.type];\n const remotedFluidDataStoreContext = new RemotedFluidDataStoreContext(\n attachMessage.id,\n snapshotTree,\n // New data stores begin with empty GC details since GC hasn't run on them yet.\n async () => { return {}; },\n this.runtime,\n new BlobCacheStorageService(this.runtime.storage, flatBlobs),\n this.runtime.scope,\n this.getCreateChildSummarizerNodeFn(\n attachMessage.id,\n {\n type: CreateSummarizerNodeSource.FromAttach,\n sequenceNumber: message.sequenceNumber,\n snapshot: attachMessage.snapshot ?? {\n entries: [createAttributesBlob(\n pkg,\n true /* isRootDataStore */,\n this.runtime.disableIsolatedChannels,\n )],\n },\n }),\n pkg);\n\n this.contexts.addBoundOrRemoted(remotedFluidDataStoreContext);\n\n // Equivalent of nextTick() - Prefetch once all current ops have completed\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\n Promise.resolve().then(async () => remotedFluidDataStoreContext.realize());\n }\n\n public processAliasMessage(\n message: ISequencedDocumentMessage,\n localOpMetadata: unknown,\n local: boolean,\n ): void {\n const aliasMessage = message.contents as IDataStoreAliasMessage;\n if (!isDataStoreAliasMessage(aliasMessage)) {\n throw new DataCorruptionError(\n \"malformedDataStoreAliasMessage\",\n {\n ...extractSafePropertiesFromMessage(message),\n },\n );\n }\n\n const resolve = localOpMetadata as PendingAliasResolve;\n const aliasResult = this.processAliasMessageCore(aliasMessage);\n if (local) {\n resolve(aliasResult);\n }\n }\n\n private processAliasMessageCore(aliasMessage: IDataStoreAliasMessage): boolean {\n const existingMapping = this.aliasMap.get(aliasMessage.alias);\n if (existingMapping !== undefined) {\n return false;\n }\n\n // Unlikely scenario, but we may receive an alias OP with the alias value\n // equal to one of the ids supplied to `createRootDataStore` in the past\n const maybeContextWithAliasAsId = this.contexts.get(aliasMessage.alias);\n if (maybeContextWithAliasAsId !== undefined) {\n return false;\n }\n\n const currentContext = this.contexts.get(aliasMessage.internalId);\n if (currentContext === undefined) {\n this.logger.sendErrorEvent({\n eventName: \"AliasFluidDataStoreNotFound\",\n fluidDataStoreId: aliasMessage.internalId,\n });\n return false;\n }\n\n this.aliasMap.set(aliasMessage.alias, currentContext.id);\n currentContext.setRoot();\n return true;\n }\n\n public bindFluidDataStore(fluidDataStoreRuntime: IFluidDataStoreChannel): void {\n const id = fluidDataStoreRuntime.id;\n const localContext = this.contexts.getUnbound(id);\n assert(!!localContext, 0x15f /* \"Could not find unbound context to bind\" */);\n\n // If the container is detached, we don't need to send OP or add to pending attach because\n // we will summarize it while uploading the create new summary and make it known to other\n // clients.\n if (this.runtime.attachState !== AttachState.Detached) {\n localContext.emit(\"attaching\");\n const message = localContext.generateAttachMessage();\n\n this.pendingAttach.set(id, message);\n this.submitAttachFn(message);\n this.attachOpFiredForDataStore.add(id);\n }\n\n this.contexts.bind(fluidDataStoreRuntime.id);\n }\n\n public createDetachedDataStoreCore(\n pkg: Readonly<string[]>,\n isRoot: boolean,\n id = uuid()): IFluidDataStoreContextDetached\n {\n const context = new LocalDetachedFluidDataStoreContext(\n id,\n pkg,\n this.runtime,\n this.runtime.storage,\n this.runtime.scope,\n this.getCreateChildSummarizerNodeFn(id, { type: CreateSummarizerNodeSource.Local }),\n (cr: IFluidDataStoreChannel) => this.bindFluidDataStore(cr),\n isRoot,\n );\n this.contexts.addUnbound(context);\n return context;\n }\n\n public _createFluidDataStoreContext(pkg: string[], id: string, isRoot: boolean, props?: any) {\n const context = new LocalFluidDataStoreContext(\n id,\n pkg,\n this.runtime,\n this.runtime.storage,\n this.runtime.scope,\n this.getCreateChildSummarizerNodeFn(id, { type: CreateSummarizerNodeSource.Local }),\n (cr: IFluidDataStoreChannel) => this.bindFluidDataStore(cr),\n undefined,\n isRoot,\n props,\n );\n this.contexts.addUnbound(context);\n return context;\n }\n\n public get disposed() {return this.disposeOnce.evaluated;}\n public readonly dispose = () => this.disposeOnce.value;\n\n public resubmitDataStoreOp(content: any, localOpMetadata: unknown) {\n const envelope = content as IEnvelope;\n const context = this.contexts.get(envelope.address);\n assert(!!context, 0x160 /* \"There should be a store context for the op\" */);\n context.reSubmit(envelope.contents, localOpMetadata);\n }\n\n public async applyStashedOp(content: any): Promise<unknown> {\n const envelope = content as IEnvelope;\n const context = this.contexts.get(envelope.address);\n assert(!!context, 0x161 /* \"There should be a store context for the op\" */);\n return context.applyStashedOp(envelope.contents);\n }\n\n public async applyStashedAttachOp(message: IAttachMessage) {\n this.pendingAttach.set(message.id, message);\n // eslint-disable-next-line @typescript-eslint/consistent-type-assertions\n this.processAttachMessage({ contents: message } as ISequencedDocumentMessage, false);\n }\n\n public processFluidDataStoreOp(message: ISequencedDocumentMessage, local: boolean, localMessageMetadata: unknown) {\n const envelope = message.contents as IEnvelope;\n const transformed = { ...message, contents: envelope.contents };\n const context = this.contexts.get(envelope.address);\n assert(!!context, 0x162 /* \"There should be a store context for the op\" */);\n context.process(transformed, local, localMessageMetadata);\n\n // Notify that a data store changed. This is used to detect if a deleted data store is being used.\n this.dataStoreChanged(envelope.address);\n }\n\n public async getDataStore(id: string, wait: boolean): Promise<FluidDataStoreContext> {\n const internalId = this.aliasMap.get(id) ?? id;\n\n const context = await this.contexts.getBoundOrRemoted(internalId, wait);\n if (context === undefined) {\n // The requested data store does not exits. Throw a 404 response exception.\n const request = { url: id };\n throw responseToException(create404Response(request), request);\n }\n\n return context;\n }\n\n public processSignal(address: string, message: IInboundSignalMessage, local: boolean) {\n const context = this.contexts.get(address);\n if (!context) {\n // Attach message may not have been processed yet\n assert(!local, 0x163 /* \"Missing datastore for local signal\" */);\n this.logger.sendTelemetryEvent({\n eventName: \"SignalFluidDataStoreNotFound\",\n fluidDataStoreId: address,\n });\n return;\n }\n\n context.processSignal(message, local);\n }\n\n public setConnectionState(connected: boolean, clientId?: string) {\n for (const [fluidDataStore, context] of this.contexts) {\n try {\n context.setConnectionState(connected, clientId);\n } catch (error) {\n this.logger.sendErrorEvent({\n eventName: \"SetConnectionStateError\",\n clientId,\n fluidDataStore,\n }, error);\n }\n }\n }\n\n public setAttachState(attachState: AttachState.Attaching | AttachState.Attached): void {\n let eventName: \"attaching\" | \"attached\";\n if (attachState === AttachState.Attaching) {\n eventName = \"attaching\";\n } else {\n eventName = \"attached\";\n }\n for (const [,context] of this.contexts) {\n // Fire only for bounded stores.\n if (!this.contexts.isNotBound(context.id)) {\n context.emit(eventName);\n }\n }\n }\n\n public get size(): number {\n return this.contexts.size;\n }\n\n public async summarize(fullTree: boolean, trackState: boolean): Promise<ISummaryTreeWithStats> {\n const summaryBuilder = new SummaryTreeBuilder();\n\n // Iterate over each store and ask it to snapshot\n await Promise.all(Array.from(this.contexts)\n .filter(([_, context]) => {\n // Summarizer works only with clients with no local changes!\n assert(context.attachState !== AttachState.Attaching,\n 0x165 /* \"Summarizer cannot work if client has local changes\" */);\n return context.attachState === AttachState.Attached;\n }).map(async ([contextId, context]) => {\n const contextSummary = await context.summarize(fullTree, trackState);\n summaryBuilder.addWithStats(contextId, contextSummary);\n }));\n\n return summaryBuilder.getSummaryTree();\n }\n\n public createSummary(): ISummaryTreeWithStats {\n const builder = new SummaryTreeBuilder();\n // Attaching graph of some stores can cause other stores to get bound too.\n // So keep taking summary until no new stores get bound.\n let notBoundContextsLength: number;\n do {\n const builderTree = builder.summary.tree;\n notBoundContextsLength = this.contexts.notBoundLength();\n // Iterate over each data store and ask it to snapshot\n Array.from(this.contexts)\n .filter(([key, _]) =>\n // Take summary of bounded data stores only, make sure we haven't summarized them already\n // and no attach op has been fired for that data store because for loader versions <= 0.24\n // we set attach state as \"attaching\" before taking createNew summary.\n !(this.contexts.isNotBound(key)\n || builderTree[key]\n || this.attachOpFiredForDataStore.has(key)),\n )\n .map(([key, value]) => {\n let dataStoreSummary: ISummarizeResult;\n if (value.isLoaded) {\n const snapshot = value.generateAttachMessage().snapshot;\n dataStoreSummary = convertToSummaryTree(snapshot, true);\n } else {\n // If this data store is not yet loaded, then there should be no changes in the snapshot from\n // which it was created as it is detached container. So just use the previous snapshot.\n assert(!!this.baseSnapshot,\n 0x166 /* \"BaseSnapshot should be there as detached container loaded from snapshot\" */);\n dataStoreSummary = convertSnapshotTreeToSummaryTree(this.baseSnapshot.trees[key]);\n }\n builder.addWithStats(key, dataStoreSummary);\n });\n } while (notBoundContextsLength !== this.contexts.notBoundLength());\n\n return builder.getSummaryTree();\n }\n\n /**\n * Generates data used for garbage collection. It does the following:\n * 1. Calls into each child data store context to get its GC data.\n * 2. Prefixes the child context's id to the GC nodes in the child's GC data. This makes sure that the node can be\n * identified as belonging to the child.\n * 3. Adds a GC node for this channel to the nodes received from the children. All these nodes together represent\n * the GC data of this channel.\n * @param fullGC - true to bypass optimizations and force full generation of GC data.\n */\n public async getGCData(fullGC: boolean = false): Promise<IGarbageCollectionData> {\n const builder = new GCDataBuilder();\n // Iterate over each store and get their GC data.\n await Promise.all(Array.from(this.contexts)\n .filter(([_, context]) => {\n // Get GC data only for attached contexts. Detached contexts are not connected in the GC reference\n // graph so any references they might have won't be connected as well.\n return context.attachState === AttachState.Attached;\n }).map(async ([contextId, context]) => {\n const contextGCData = await context.getGCData(fullGC);\n // Prefix the child's id to the ids of its GC nodes so they can be identified as belonging to the child.\n // This also gradually builds the id of each node to be a path from the root.\n builder.prefixAndAddNodes(contextId, contextGCData.gcNodes);\n }));\n\n // Get the outbound routes and add a GC node for this channel.\n builder.addNode(\"/\", await this.getOutboundRoutes());\n return builder.getGCData();\n }\n\n /**\n * After GC has run, called to notify this Container's data stores of routes that are used in it.\n * @param usedRoutes - The routes that are used in all data stores in this Container.\n * @param gcTimestamp - The time when GC was run that generated these used routes. If any node node becomes\n * unreferenced as part of this GC run, this should be used to update the time when it happens.\n * @returns the statistics of the used state of the data stores.\n */\n public updateUsedRoutes(usedRoutes: string[], gcTimestamp?: number): IUsedStateStats {\n // Get a map of data store ids to routes used in it.\n const usedDataStoreRoutes = unpackChildNodesUsedRoutes(usedRoutes);\n\n // Verify that the used routes are correct.\n for (const [id] of usedDataStoreRoutes) {\n assert(this.contexts.has(id), 0x167 /* \"Used route does not belong to any known data store\" */);\n }\n\n // Update the used routes in each data store. Used routes is empty for unused data stores.\n for (const [contextId, context] of this.contexts) {\n context.updateUsedRoutes(usedDataStoreRoutes.get(contextId) ?? [], gcTimestamp);\n }\n\n // Return the number of data stores that are unused.\n const dataStoreCount = this.contexts.size;\n return {\n totalNodeCount: dataStoreCount,\n unusedNodeCount: dataStoreCount - usedDataStoreRoutes.size,\n };\n }\n\n /**\n * When running GC in test mode, this is called to delete objects whose routes are unused. This enables testing\n * scenarios with accessing deleted content.\n * @param unusedRoutes - The routes that are unused in all data stores in this Container.\n */\n public deleteUnusedRoutes(unusedRoutes: string[]) {\n for (const route of unusedRoutes) {\n const dataStoreId = route.split(\"/\")[1];\n // Delete the contexts of unused data stores.\n this.contexts.delete(dataStoreId);\n // Delete the summarizer node of the unused data stores.\n this.deleteChildSummarizerNodeFn(dataStoreId);\n }\n }\n\n /**\n * Returns the outbound routes of this channel. Only root data stores are considered referenced and their paths are\n * part of outbound routes.\n */\n private async getOutboundRoutes(): Promise<string[]> {\n const outboundRoutes: string[] = [];\n for (const [contextId, context] of this.contexts) {\n const isRootDataStore = await context.isRoot();\n if (isRootDataStore) {\n outboundRoutes.push(`/${contextId}`);\n }\n }\n return outboundRoutes;\n }\n}\n\nexport function getSummaryForDatastores(\n snapshot: ISnapshotTree | undefined,\n metadata?: IContainerRuntimeMetadata,\n): ISnapshotTree | undefined {\n if (!snapshot) {\n return undefined;\n }\n\n if (rootHasIsolatedChannels(metadata)) {\n const datastoresSnapshot = snapshot.trees[channelsTreeName];\n assert(!!datastoresSnapshot, 0x168 /* `expected ${channelsTreeName} tree in snapshot` */);\n return datastoresSnapshot;\n } else {\n // back-compat: strip out all non-datastore paths before giving to DataStores object.\n const datastoresTrees: ISnapshotTree[\"trees\"] = {};\n for (const [key, value] of Object.entries(snapshot.trees)) {\n if (!nonDataStorePaths.includes(key)) {\n datastoresTrees[key] = value;\n }\n }\n return {\n ...snapshot,\n trees: datastoresTrees,\n };\n }\n}\n"]}
|