@fluidframework/container-runtime 0.56.7 → 0.57.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/blobManager.d.ts.map +1 -1
- package/dist/blobManager.js +9 -1
- package/dist/blobManager.js.map +1 -1
- package/dist/connectionTelemetry.d.ts.map +1 -1
- package/dist/connectionTelemetry.js +6 -6
- package/dist/connectionTelemetry.js.map +1 -1
- package/dist/containerRuntime.d.ts +68 -28
- package/dist/containerRuntime.d.ts.map +1 -1
- package/dist/containerRuntime.js +148 -89
- package/dist/containerRuntime.js.map +1 -1
- package/dist/dataStore.d.ts +27 -0
- package/dist/dataStore.d.ts.map +1 -0
- package/dist/dataStore.js +113 -0
- package/dist/dataStore.js.map +1 -0
- package/dist/dataStoreContext.d.ts +1 -7
- package/dist/dataStoreContext.d.ts.map +1 -1
- package/dist/dataStoreContext.js +10 -6
- package/dist/dataStoreContext.js.map +1 -1
- package/dist/dataStores.d.ts +9 -5
- package/dist/dataStores.d.ts.map +1 -1
- package/dist/dataStores.js +14 -19
- package/dist/dataStores.js.map +1 -1
- package/dist/garbageCollection.d.ts +66 -27
- package/dist/garbageCollection.d.ts.map +1 -1
- package/dist/garbageCollection.js +272 -97
- 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 +2 -1
- package/dist/index.js.map +1 -1
- package/dist/packageVersion.d.ts +1 -1
- package/dist/packageVersion.js +1 -1
- package/dist/packageVersion.js.map +1 -1
- package/dist/runningSummarizer.d.ts +1 -0
- package/dist/runningSummarizer.d.ts.map +1 -1
- package/dist/runningSummarizer.js +23 -15
- package/dist/runningSummarizer.js.map +1 -1
- package/dist/summarizerTypes.d.ts +4 -6
- package/dist/summarizerTypes.d.ts.map +1 -1
- package/dist/summarizerTypes.js.map +1 -1
- package/dist/summaryGenerator.d.ts +2 -1
- package/dist/summaryGenerator.d.ts.map +1 -1
- package/dist/summaryGenerator.js +46 -29
- package/dist/summaryGenerator.js.map +1 -1
- package/lib/blobManager.d.ts.map +1 -1
- package/lib/blobManager.js +9 -1
- package/lib/blobManager.js.map +1 -1
- package/lib/connectionTelemetry.d.ts.map +1 -1
- package/lib/connectionTelemetry.js +6 -6
- package/lib/connectionTelemetry.js.map +1 -1
- package/lib/containerRuntime.d.ts +68 -28
- package/lib/containerRuntime.d.ts.map +1 -1
- package/lib/containerRuntime.js +149 -90
- package/lib/containerRuntime.js.map +1 -1
- package/lib/dataStore.d.ts +27 -0
- package/lib/dataStore.d.ts.map +1 -0
- package/lib/dataStore.js +108 -0
- package/lib/dataStore.js.map +1 -0
- package/lib/dataStoreContext.d.ts +1 -7
- package/lib/dataStoreContext.d.ts.map +1 -1
- package/lib/dataStoreContext.js +10 -6
- package/lib/dataStoreContext.js.map +1 -1
- package/lib/dataStores.d.ts +9 -5
- package/lib/dataStores.d.ts.map +1 -1
- package/lib/dataStores.js +13 -18
- package/lib/dataStores.js.map +1 -1
- package/lib/garbageCollection.d.ts +66 -27
- package/lib/garbageCollection.d.ts.map +1 -1
- package/lib/garbageCollection.js +274 -99
- 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 +1 -1
- package/lib/index.js.map +1 -1
- package/lib/packageVersion.d.ts +1 -1
- package/lib/packageVersion.js +1 -1
- package/lib/packageVersion.js.map +1 -1
- package/lib/runningSummarizer.d.ts +1 -0
- package/lib/runningSummarizer.d.ts.map +1 -1
- package/lib/runningSummarizer.js +23 -15
- package/lib/runningSummarizer.js.map +1 -1
- package/lib/summarizerTypes.d.ts +4 -6
- package/lib/summarizerTypes.d.ts.map +1 -1
- package/lib/summarizerTypes.js.map +1 -1
- package/lib/summaryGenerator.d.ts +2 -1
- package/lib/summaryGenerator.d.ts.map +1 -1
- package/lib/summaryGenerator.js +46 -29
- package/lib/summaryGenerator.js.map +1 -1
- package/package.json +13 -13
- package/src/blobManager.ts +12 -1
- package/src/connectionTelemetry.ts +7 -6
- package/src/containerRuntime.ts +244 -115
- package/src/dataStore.ts +151 -0
- package/src/dataStoreContext.ts +11 -14
- package/src/dataStores.ts +23 -38
- package/src/garbageCollection.ts +385 -150
- package/src/index.ts +2 -1
- package/src/packageVersion.ts +1 -1
- package/src/runningSummarizer.ts +25 -16
- package/src/summarizerTypes.ts +4 -8
- package/src/summaryGenerator.ts +71 -23
package/src/dataStore.ts
ADDED
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
|
+
* Licensed under the MIT License.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { ITelemetryLogger } from "@fluidframework/common-definitions";
|
|
7
|
+
import { unreachableCase } from "@fluidframework/common-utils";
|
|
8
|
+
import { AttachState } from "@fluidframework/container-definitions";
|
|
9
|
+
import { IRequest, IResponse } from "@fluidframework/core-interfaces";
|
|
10
|
+
import { AliasResult, IDataStore, IFluidDataStoreChannel } from "@fluidframework/runtime-definitions";
|
|
11
|
+
import { TelemetryDataTag } from "@fluidframework/telemetry-utils";
|
|
12
|
+
import { ContainerRuntime } from "./containerRuntime";
|
|
13
|
+
import { DataStores } from "./dataStores";
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Interface for an op to be used for assigning an
|
|
17
|
+
* alias to a datastore
|
|
18
|
+
*/
|
|
19
|
+
export interface IDataStoreAliasMessage {
|
|
20
|
+
/** The internal id of the datastore */
|
|
21
|
+
readonly internalId: string;
|
|
22
|
+
/** The alias name to be assigned to the datastore */
|
|
23
|
+
readonly alias: string;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Type guard that returns true if the given alias message is actually an instance of
|
|
28
|
+
* a class which implements @see IDataStoreAliasMessage
|
|
29
|
+
* @param maybeDataStoreAliasMessage - message object to be validated
|
|
30
|
+
* @returns True if the @see IDataStoreAliasMessage is fully implemented, false otherwise
|
|
31
|
+
*/
|
|
32
|
+
export const isDataStoreAliasMessage = (
|
|
33
|
+
maybeDataStoreAliasMessage: any,
|
|
34
|
+
): maybeDataStoreAliasMessage is IDataStoreAliasMessage => {
|
|
35
|
+
return typeof maybeDataStoreAliasMessage?.internalId === "string"
|
|
36
|
+
&& typeof maybeDataStoreAliasMessage?.alias === "string";
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
export const channelToDataStore = (
|
|
40
|
+
fluidDataStoreChannel: IFluidDataStoreChannel,
|
|
41
|
+
internalId: string,
|
|
42
|
+
runtime: ContainerRuntime,
|
|
43
|
+
datastores: DataStores,
|
|
44
|
+
logger: ITelemetryLogger,
|
|
45
|
+
): IDataStore => new DataStore(fluidDataStoreChannel, internalId, runtime, datastores, logger);
|
|
46
|
+
|
|
47
|
+
enum AliasState {
|
|
48
|
+
Aliased = "Aliased",
|
|
49
|
+
Aliasing = "Aliasing",
|
|
50
|
+
None = "None",
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
class DataStore implements IDataStore {
|
|
54
|
+
private aliasState: AliasState = AliasState.None;
|
|
55
|
+
private alias: string | undefined;
|
|
56
|
+
|
|
57
|
+
async trySetAlias(alias: string): Promise<AliasResult> {
|
|
58
|
+
switch (this.aliasState) {
|
|
59
|
+
// If we're already aliasing, throw an exception
|
|
60
|
+
case AliasState.Aliasing:
|
|
61
|
+
return "Aliasing";
|
|
62
|
+
// If this datastore is already aliased, return true only if this
|
|
63
|
+
// is a repeated call for the same alias
|
|
64
|
+
case AliasState.Aliased:
|
|
65
|
+
return this.alias === alias ? "Success" : "AlreadyAliased";
|
|
66
|
+
// There is no current or past alias operation for this datastore,
|
|
67
|
+
// it is safe to continue execution
|
|
68
|
+
case AliasState.None: break;
|
|
69
|
+
default: unreachableCase(this.aliasState);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
this.aliasState = AliasState.Aliasing;
|
|
73
|
+
const message: IDataStoreAliasMessage = {
|
|
74
|
+
internalId: this.internalId,
|
|
75
|
+
alias,
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
this.fluidDataStoreChannel.bindToContext();
|
|
79
|
+
|
|
80
|
+
if (this.runtime.attachState === AttachState.Detached) {
|
|
81
|
+
const localResult = this.datastores.processAliasMessageCore(message);
|
|
82
|
+
// Explicitly Lock-out future attempts of aliasing,
|
|
83
|
+
// regardless of result
|
|
84
|
+
this.aliasState = AliasState.Aliased;
|
|
85
|
+
return localResult ? "Success" : "Conflict";
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const aliased = await this.ackBasedPromise<boolean>((resolve) => {
|
|
89
|
+
this.runtime.submitDataStoreAliasOp(message, resolve);
|
|
90
|
+
}).then((succeeded) => {
|
|
91
|
+
// Explicitly Lock-out future attempts of aliasing,
|
|
92
|
+
// regardless of result
|
|
93
|
+
this.aliasState = AliasState.Aliased;
|
|
94
|
+
if (succeeded) {
|
|
95
|
+
this.alias = alias;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
return succeeded;
|
|
99
|
+
}).catch((error) => {
|
|
100
|
+
this.logger.sendErrorEvent({
|
|
101
|
+
eventName: "AliasingException",
|
|
102
|
+
alias: {
|
|
103
|
+
value: alias,
|
|
104
|
+
tag: TelemetryDataTag.UserData,
|
|
105
|
+
},
|
|
106
|
+
internalId: {
|
|
107
|
+
value: this.internalId,
|
|
108
|
+
tag: TelemetryDataTag.PackageData,
|
|
109
|
+
},
|
|
110
|
+
}, error);
|
|
111
|
+
this.aliasState = AliasState.None;
|
|
112
|
+
return false;
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
return aliased ? "Success" : "Conflict";
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
async request(request: IRequest): Promise<IResponse> {
|
|
119
|
+
return this.fluidDataStoreChannel.request(request);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
constructor(
|
|
123
|
+
private readonly fluidDataStoreChannel: IFluidDataStoreChannel,
|
|
124
|
+
private readonly internalId: string,
|
|
125
|
+
private readonly runtime: ContainerRuntime,
|
|
126
|
+
private datastores: DataStores,
|
|
127
|
+
private readonly logger: ITelemetryLogger,
|
|
128
|
+
) { }
|
|
129
|
+
public get IFluidRouter() { return this.fluidDataStoreChannel; }
|
|
130
|
+
|
|
131
|
+
private async ackBasedPromise<T>(
|
|
132
|
+
executor: (resolve: (value: T | PromiseLike<T>) => void,
|
|
133
|
+
reject: (reason?: any) => void) => void,
|
|
134
|
+
): Promise<T> {
|
|
135
|
+
let rejectBecauseDispose: () => void;
|
|
136
|
+
return new Promise<T>((resolve, reject) => {
|
|
137
|
+
rejectBecauseDispose =
|
|
138
|
+
() => reject(new Error("ContainerRuntime disposed while this ack-based Promise was pending"));
|
|
139
|
+
|
|
140
|
+
if (this.runtime.disposed) {
|
|
141
|
+
rejectBecauseDispose();
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
this.runtime.on("dispose", rejectBecauseDispose);
|
|
146
|
+
executor(resolve, reject);
|
|
147
|
+
}).finally(() => {
|
|
148
|
+
this.runtime.off("dispose", rejectBecauseDispose);
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
}
|
package/src/dataStoreContext.ts
CHANGED
|
@@ -106,11 +106,6 @@ export function createAttributesBlob(
|
|
|
106
106
|
|
|
107
107
|
interface ISnapshotDetails {
|
|
108
108
|
pkg: readonly string[];
|
|
109
|
-
/**
|
|
110
|
-
* This tells whether a data store is root. Root data stores are never collected.
|
|
111
|
-
* Non-root data stores may be collected if they are not used.
|
|
112
|
-
*/
|
|
113
|
-
isRootDataStore: boolean;
|
|
114
109
|
snapshot?: ISnapshotTree;
|
|
115
110
|
}
|
|
116
111
|
|
|
@@ -212,7 +207,10 @@ export abstract class FluidDataStoreContext extends TypedEventEmitter<IFluidData
|
|
|
212
207
|
}
|
|
213
208
|
|
|
214
209
|
public async isRoot(): Promise<boolean> {
|
|
215
|
-
|
|
210
|
+
// This call updates this.isRootDataStore if it has not yet been updated
|
|
211
|
+
// The initial value is stored in the initial snapshot of the data store
|
|
212
|
+
await this.getInitialSnapshotDetails();
|
|
213
|
+
return this.isRootDataStore;
|
|
216
214
|
}
|
|
217
215
|
|
|
218
216
|
protected registry: IFluidDataStoreRegistry | undefined;
|
|
@@ -225,6 +223,7 @@ export abstract class FluidDataStoreContext extends TypedEventEmitter<IFluidData
|
|
|
225
223
|
protected channelDeferred: Deferred<IFluidDataStoreChannel> | undefined;
|
|
226
224
|
private _baseSnapshot: ISnapshotTree | undefined;
|
|
227
225
|
protected _attachState: AttachState;
|
|
226
|
+
protected isRootDataStore: boolean = false;
|
|
228
227
|
protected readonly summarizerNode: ISummarizerNodeWithGC;
|
|
229
228
|
private readonly subLogger: ITelemetryLogger;
|
|
230
229
|
private readonly thresholdOpsCounter: ThresholdCounter;
|
|
@@ -450,8 +449,8 @@ export abstract class FluidDataStoreContext extends TypedEventEmitter<IFluidData
|
|
|
450
449
|
}
|
|
451
450
|
|
|
452
451
|
// Add data store's attributes to the summary.
|
|
453
|
-
const { pkg
|
|
454
|
-
const attributes = createAttributes(pkg, isRootDataStore, this.disableIsolatedChannels);
|
|
452
|
+
const { pkg } = await this.getInitialSnapshotDetails();
|
|
453
|
+
const attributes = createAttributes(pkg, this.isRootDataStore, this.disableIsolatedChannels);
|
|
455
454
|
addBlobToSummary(summarizeResult, dataStoreAttributesBlobName, JSON.stringify(attributes));
|
|
456
455
|
|
|
457
456
|
// Add GC data to the summary if it's not written at the root.
|
|
@@ -729,7 +728,6 @@ export abstract class FluidDataStoreContext extends TypedEventEmitter<IFluidData
|
|
|
729
728
|
}
|
|
730
729
|
|
|
731
730
|
export class RemoteFluidDataStoreContext extends FluidDataStoreContext {
|
|
732
|
-
private isRootDataStore: boolean | undefined;
|
|
733
731
|
private readonly initSnapshotValue: ISnapshotTree | string | undefined;
|
|
734
732
|
private readonly baseGCDetailsP: Promise<IGarbageCollectionDetailsBase>;
|
|
735
733
|
|
|
@@ -750,7 +748,7 @@ export class RemoteFluidDataStoreContext extends FluidDataStoreContext {
|
|
|
750
748
|
});
|
|
751
749
|
}
|
|
752
750
|
|
|
753
|
-
private readonly initialSnapshotDetailsP =
|
|
751
|
+
private readonly initialSnapshotDetailsP = new LazyPromise<ISnapshotDetails>(async () => {
|
|
754
752
|
let tree: ISnapshotTree | undefined;
|
|
755
753
|
let isRootDataStore = true;
|
|
756
754
|
|
|
@@ -804,11 +802,12 @@ export class RemoteFluidDataStoreContext extends FluidDataStoreContext {
|
|
|
804
802
|
}
|
|
805
803
|
}
|
|
806
804
|
|
|
805
|
+
this.isRootDataStore = isRootDataStore;
|
|
806
|
+
|
|
807
807
|
return {
|
|
808
808
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
809
809
|
pkg: this.pkg!,
|
|
810
810
|
snapshot: tree,
|
|
811
|
-
isRootDataStore,
|
|
812
811
|
};
|
|
813
812
|
});
|
|
814
813
|
|
|
@@ -846,7 +845,6 @@ export class RemoteFluidDataStoreContext extends FluidDataStoreContext {
|
|
|
846
845
|
*/
|
|
847
846
|
export class LocalFluidDataStoreContextBase extends FluidDataStoreContext {
|
|
848
847
|
private readonly snapshotTree: ISnapshotTree | undefined;
|
|
849
|
-
protected isRootDataStore: boolean | undefined;
|
|
850
848
|
/**
|
|
851
849
|
* @deprecated 0.16 Issue #1635, #3631
|
|
852
850
|
*/
|
|
@@ -862,7 +860,7 @@ export class LocalFluidDataStoreContextBase extends FluidDataStoreContext {
|
|
|
862
860
|
);
|
|
863
861
|
|
|
864
862
|
this.snapshotTree = props.snapshotTree;
|
|
865
|
-
this.isRootDataStore = props.isRootDataStore;
|
|
863
|
+
this.isRootDataStore = props.isRootDataStore ?? false;
|
|
866
864
|
this.createProps = props.createProps;
|
|
867
865
|
this.attachListeners();
|
|
868
866
|
}
|
|
@@ -938,7 +936,6 @@ export class LocalFluidDataStoreContextBase extends FluidDataStoreContext {
|
|
|
938
936
|
return {
|
|
939
937
|
pkg: this.pkg,
|
|
940
938
|
snapshot,
|
|
941
|
-
isRootDataStore: this.isRootDataStore,
|
|
942
939
|
};
|
|
943
940
|
}
|
|
944
941
|
|
package/src/dataStores.ts
CHANGED
|
@@ -50,34 +50,10 @@ import {
|
|
|
50
50
|
LocalDetachedFluidDataStoreContext,
|
|
51
51
|
} from "./dataStoreContext";
|
|
52
52
|
import { IContainerRuntimeMetadata, nonDataStorePaths, rootHasIsolatedChannels } from "./summaryFormat";
|
|
53
|
-
import {
|
|
53
|
+
import { IDataStoreAliasMessage, isDataStoreAliasMessage } from "./dataStore";
|
|
54
54
|
|
|
55
55
|
type PendingAliasResolve = (success: boolean) => void;
|
|
56
56
|
|
|
57
|
-
/**
|
|
58
|
-
* Interface for an op to be used for assigning an
|
|
59
|
-
* alias to a datastore
|
|
60
|
-
*/
|
|
61
|
-
interface IDataStoreAliasMessage {
|
|
62
|
-
/** The internal id of the datastore */
|
|
63
|
-
readonly internalId: string;
|
|
64
|
-
/** The alias name to be assigned to the datastore */
|
|
65
|
-
readonly alias: string;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* Type guard that returns true if the given alias message is actually an instance of
|
|
70
|
-
* a class which implements @see IDataStoreAliasMessage
|
|
71
|
-
* @param maybeDataStoreAliasMessage - message object to be validated
|
|
72
|
-
* @returns True if the @see IDataStoreAliasMessage is fully implemented, false otherwise
|
|
73
|
-
*/
|
|
74
|
-
const isDataStoreAliasMessage = (
|
|
75
|
-
maybeDataStoreAliasMessage: any,
|
|
76
|
-
): maybeDataStoreAliasMessage is IDataStoreAliasMessage => {
|
|
77
|
-
return typeof maybeDataStoreAliasMessage?.internalId === "string"
|
|
78
|
-
&& typeof maybeDataStoreAliasMessage?.alias === "string";
|
|
79
|
-
};
|
|
80
|
-
|
|
81
57
|
/**
|
|
82
58
|
* This class encapsulates data store handling. Currently it is only used by the container runtime,
|
|
83
59
|
* but eventually could be hosted on any channel once we formalize the channel api boundary.
|
|
@@ -111,11 +87,12 @@ export class DataStores implements IDisposable {
|
|
|
111
87
|
private readonly runtime: ContainerRuntime,
|
|
112
88
|
private readonly submitAttachFn: (attachContent: any) => void,
|
|
113
89
|
private readonly getCreateChildSummarizerNodeFn:
|
|
114
|
-
(id: string, createParam: CreateChildSummarizerNodeParam)
|
|
90
|
+
(id: string, createParam: CreateChildSummarizerNodeParam) => CreateChildSummarizerNodeFn,
|
|
115
91
|
private readonly deleteChildSummarizerNodeFn: (id: string) => void,
|
|
116
92
|
baseLogger: ITelemetryBaseLogger,
|
|
117
93
|
getBaseGCDetails: () => Promise<Map<string, IGarbageCollectionDetailsBase>>,
|
|
118
|
-
private readonly dataStoreChanged: (
|
|
94
|
+
private readonly dataStoreChanged: (
|
|
95
|
+
dataStorePath: string, timestampMs: number, packagePath?: readonly string[]) => void,
|
|
119
96
|
private readonly aliasMap: Map<string, string>,
|
|
120
97
|
private readonly writeGCDataAtRoot: boolean,
|
|
121
98
|
private readonly contexts: DataStoreContexts = new DataStoreContexts(baseLogger),
|
|
@@ -290,7 +267,7 @@ export class DataStores implements IDisposable {
|
|
|
290
267
|
}
|
|
291
268
|
}
|
|
292
269
|
|
|
293
|
-
|
|
270
|
+
public processAliasMessageCore(aliasMessage: IDataStoreAliasMessage): boolean {
|
|
294
271
|
if (this.alreadyProcessed(aliasMessage.alias)) {
|
|
295
272
|
return false;
|
|
296
273
|
}
|
|
@@ -411,7 +388,11 @@ export class DataStores implements IDisposable {
|
|
|
411
388
|
context.process(transformed, local, localMessageMetadata);
|
|
412
389
|
|
|
413
390
|
// Notify that a data store changed. This is used to detect if a deleted data store is being used.
|
|
414
|
-
this.dataStoreChanged(
|
|
391
|
+
this.dataStoreChanged(
|
|
392
|
+
`/${envelope.address}`,
|
|
393
|
+
message.timestamp,
|
|
394
|
+
context.isLoaded ? context.packagePath : undefined,
|
|
395
|
+
);
|
|
415
396
|
}
|
|
416
397
|
|
|
417
398
|
public async getDataStore(id: string, wait: boolean): Promise<FluidDataStoreContext> {
|
|
@@ -582,9 +563,8 @@ export class DataStores implements IDisposable {
|
|
|
582
563
|
* @param usedRoutes - The routes that are used in all data stores in this Container.
|
|
583
564
|
* @param gcTimestamp - The time when GC was run that generated these used routes. If any node node becomes
|
|
584
565
|
* unreferenced as part of this GC run, this should be used to update the time when it happens.
|
|
585
|
-
* @returns the statistics of the used state of the data stores.
|
|
586
566
|
*/
|
|
587
|
-
public updateUsedRoutes(usedRoutes: string[], gcTimestamp?: number)
|
|
567
|
+
public updateUsedRoutes(usedRoutes: string[], gcTimestamp?: number) {
|
|
588
568
|
// Get a map of data store ids to routes used in it.
|
|
589
569
|
const usedDataStoreRoutes = unpackChildNodesUsedRoutes(usedRoutes);
|
|
590
570
|
|
|
@@ -597,13 +577,6 @@ export class DataStores implements IDisposable {
|
|
|
597
577
|
for (const [contextId, context] of this.contexts) {
|
|
598
578
|
context.updateUsedRoutes(usedDataStoreRoutes.get(contextId) ?? [], gcTimestamp);
|
|
599
579
|
}
|
|
600
|
-
|
|
601
|
-
// Return the number of data stores that are unused.
|
|
602
|
-
const dataStoreCount = this.contexts.size;
|
|
603
|
-
return {
|
|
604
|
-
totalNodeCount: dataStoreCount,
|
|
605
|
-
unusedNodeCount: dataStoreCount - usedDataStoreRoutes.size,
|
|
606
|
-
};
|
|
607
580
|
}
|
|
608
581
|
|
|
609
582
|
/**
|
|
@@ -635,6 +608,18 @@ export class DataStores implements IDisposable {
|
|
|
635
608
|
}
|
|
636
609
|
return outboundRoutes;
|
|
637
610
|
}
|
|
611
|
+
|
|
612
|
+
/**
|
|
613
|
+
* Returns the package path of the node with the given path. This is used by GC to log when an inactive / deleted
|
|
614
|
+
* node is used.
|
|
615
|
+
*/
|
|
616
|
+
public getNodePackagePath(nodePath: string): readonly string[] | undefined {
|
|
617
|
+
// Currently, only return the data store package path for the node since GC is only interested in data stores.
|
|
618
|
+
const dataStoreId = nodePath.split("/")[1];
|
|
619
|
+
const context = this.contexts.get(dataStoreId);
|
|
620
|
+
assert(context !== undefined, 0x2b9 /* "Data store with given id does not exist" */);
|
|
621
|
+
return context.isLoaded ? context.packagePath : undefined;
|
|
622
|
+
}
|
|
638
623
|
}
|
|
639
624
|
|
|
640
625
|
export function getSummaryForDatastores(
|