@fluidframework/container-runtime 0.56.0 → 0.57.0-51086
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 +65 -25
- package/dist/containerRuntime.d.ts.map +1 -1
- package/dist/containerRuntime.js +149 -79
- package/dist/containerRuntime.js.map +1 -1
- package/dist/dataStore.d.ts +62 -0
- package/dist/dataStore.d.ts.map +1 -0
- package/dist/dataStore.js +135 -0
- package/dist/dataStore.js.map +1 -0
- 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 +47 -21
- package/dist/garbageCollection.d.ts.map +1 -1
- package/dist/garbageCollection.js +195 -61
- package/dist/garbageCollection.js.map +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -1
- 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/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 +6 -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 -28
- 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 +65 -25
- package/lib/containerRuntime.d.ts.map +1 -1
- package/lib/containerRuntime.js +150 -80
- package/lib/containerRuntime.js.map +1 -1
- package/lib/dataStore.d.ts +62 -0
- package/lib/dataStore.d.ts.map +1 -0
- package/lib/dataStore.js +130 -0
- package/lib/dataStore.js.map +1 -0
- 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 +47 -21
- package/lib/garbageCollection.d.ts.map +1 -1
- package/lib/garbageCollection.js +197 -63
- package/lib/garbageCollection.js.map +1 -1
- package/lib/index.d.ts +3 -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/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 +6 -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 -28
- 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 +231 -103
- package/src/dataStore.ts +187 -0
- package/src/dataStoreContext.ts +1 -1
- package/src/dataStores.ts +18 -38
- package/src/garbageCollection.ts +283 -105
- package/src/index.ts +3 -1
- package/src/packageVersion.ts +1 -1
- package/src/runningSummarizer.ts +25 -16
- package/src/summarizerTypes.ts +6 -8
- package/src/summaryGenerator.ts +72 -23
package/src/dataStore.ts
ADDED
|
@@ -0,0 +1,187 @@
|
|
|
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 { IFluidRouter, IRequest, IResponse } from "@fluidframework/core-interfaces";
|
|
10
|
+
import { 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
|
+
/**
|
|
40
|
+
* Encapsulates the return codes of the aliasing API
|
|
41
|
+
*/
|
|
42
|
+
export enum AliasResult {
|
|
43
|
+
/**
|
|
44
|
+
* The datastore has been successfully aliased
|
|
45
|
+
*/
|
|
46
|
+
Success = "Success",
|
|
47
|
+
/**
|
|
48
|
+
* There is already a datastore bound to the provided alias
|
|
49
|
+
*/
|
|
50
|
+
Conflict = "Conflict",
|
|
51
|
+
/**
|
|
52
|
+
* The datastore is currently in the process of being aliased
|
|
53
|
+
*/
|
|
54
|
+
Aliasing = "Aliasing",
|
|
55
|
+
/**
|
|
56
|
+
* The datastore has been attempted to be aliased before
|
|
57
|
+
*/
|
|
58
|
+
AlreadyAliased = "AlreadyAliased",
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* A fluid router with the capability of being assigned an alias
|
|
63
|
+
*/
|
|
64
|
+
export interface IDataStore extends IFluidRouter {
|
|
65
|
+
/**
|
|
66
|
+
* Attempt to assign an alias to the datastore.
|
|
67
|
+
* If the operation succeeds, the datastore can be referenced
|
|
68
|
+
* by the supplied alias.
|
|
69
|
+
*
|
|
70
|
+
* @param alias - Given alias for this datastore.
|
|
71
|
+
*/
|
|
72
|
+
trySetAlias(alias: string): Promise<AliasResult>;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export const channelToDataStore = (
|
|
76
|
+
fluidDataStoreChannel: IFluidDataStoreChannel,
|
|
77
|
+
internalId: string,
|
|
78
|
+
runtime: ContainerRuntime,
|
|
79
|
+
datastores: DataStores,
|
|
80
|
+
logger: ITelemetryLogger,
|
|
81
|
+
): IDataStore => new DataStore(fluidDataStoreChannel, internalId, runtime, datastores, logger);
|
|
82
|
+
|
|
83
|
+
enum AliasState {
|
|
84
|
+
Aliased = "Aliased",
|
|
85
|
+
Aliasing = "Aliasing",
|
|
86
|
+
None = "None",
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
class DataStore implements IDataStore {
|
|
90
|
+
private aliasState: AliasState = AliasState.None;
|
|
91
|
+
private alias: string | undefined;
|
|
92
|
+
|
|
93
|
+
async trySetAlias(alias: string): Promise<AliasResult> {
|
|
94
|
+
switch (this.aliasState) {
|
|
95
|
+
// If we're already aliasing, throw an exception
|
|
96
|
+
case AliasState.Aliasing:
|
|
97
|
+
return AliasResult.Aliasing;
|
|
98
|
+
// If this datastore is already aliased, return true only if this
|
|
99
|
+
// is a repeated call for the same alias
|
|
100
|
+
case AliasState.Aliased:
|
|
101
|
+
return this.alias === alias ? AliasResult.Success : AliasResult.AlreadyAliased;
|
|
102
|
+
// There is no current or past alias operation for this datastore,
|
|
103
|
+
// it is safe to continue execution
|
|
104
|
+
case AliasState.None: break;
|
|
105
|
+
default: unreachableCase(this.aliasState);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
this.aliasState = AliasState.Aliasing;
|
|
109
|
+
const message: IDataStoreAliasMessage = {
|
|
110
|
+
internalId: this.internalId,
|
|
111
|
+
alias,
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
this.fluidDataStoreChannel.bindToContext();
|
|
115
|
+
|
|
116
|
+
if (this.runtime.attachState === AttachState.Detached) {
|
|
117
|
+
const localResult = this.datastores.processAliasMessageCore(message);
|
|
118
|
+
// Explicitly Lock-out future attempts of aliasing,
|
|
119
|
+
// regardless of result
|
|
120
|
+
this.aliasState = AliasState.Aliased;
|
|
121
|
+
return localResult ? AliasResult.Success : AliasResult.Conflict;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
const aliased = await this.ackBasedPromise<boolean>((resolve) => {
|
|
125
|
+
this.runtime.submitDataStoreAliasOp(message, resolve);
|
|
126
|
+
}).then((succeeded) => {
|
|
127
|
+
// Explicitly Lock-out future attempts of aliasing,
|
|
128
|
+
// regardless of result
|
|
129
|
+
this.aliasState = AliasState.Aliased;
|
|
130
|
+
if (succeeded) {
|
|
131
|
+
this.alias = alias;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
return succeeded;
|
|
135
|
+
}).catch((error) => {
|
|
136
|
+
this.logger.sendErrorEvent({
|
|
137
|
+
eventName: "AliasingException",
|
|
138
|
+
alias: {
|
|
139
|
+
value: alias,
|
|
140
|
+
tag: TelemetryDataTag.UserData,
|
|
141
|
+
},
|
|
142
|
+
internalId: {
|
|
143
|
+
value: this.internalId,
|
|
144
|
+
tag: TelemetryDataTag.PackageData,
|
|
145
|
+
},
|
|
146
|
+
}, error);
|
|
147
|
+
this.aliasState = AliasState.None;
|
|
148
|
+
return false;
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
return aliased ? AliasResult.Success : AliasResult.Conflict;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
async request(request: IRequest): Promise<IResponse> {
|
|
155
|
+
return this.fluidDataStoreChannel.request(request);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
constructor(
|
|
159
|
+
private readonly fluidDataStoreChannel: IFluidDataStoreChannel,
|
|
160
|
+
private readonly internalId: string,
|
|
161
|
+
private readonly runtime: ContainerRuntime,
|
|
162
|
+
private datastores: DataStores,
|
|
163
|
+
private readonly logger: ITelemetryLogger,
|
|
164
|
+
) { }
|
|
165
|
+
public get IFluidRouter() { return this.fluidDataStoreChannel; }
|
|
166
|
+
|
|
167
|
+
private async ackBasedPromise<T>(
|
|
168
|
+
executor: (resolve: (value: T | PromiseLike<T>) => void,
|
|
169
|
+
reject: (reason?: any) => void) => void,
|
|
170
|
+
): Promise<T> {
|
|
171
|
+
let rejectBecauseDispose: () => void;
|
|
172
|
+
return new Promise<T>((resolve, reject) => {
|
|
173
|
+
rejectBecauseDispose =
|
|
174
|
+
() => reject(new Error("ContainerRuntime disposed while this ack-based Promise was pending"));
|
|
175
|
+
|
|
176
|
+
if (this.runtime.disposed) {
|
|
177
|
+
rejectBecauseDispose();
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
this.runtime.on("dispose", rejectBecauseDispose);
|
|
182
|
+
executor(resolve, reject);
|
|
183
|
+
}).finally(() => {
|
|
184
|
+
this.runtime.off("dispose", rejectBecauseDispose);
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
}
|
package/src/dataStoreContext.ts
CHANGED
|
@@ -750,7 +750,7 @@ export class RemoteFluidDataStoreContext extends FluidDataStoreContext {
|
|
|
750
750
|
});
|
|
751
751
|
}
|
|
752
752
|
|
|
753
|
-
private readonly initialSnapshotDetailsP =
|
|
753
|
+
private readonly initialSnapshotDetailsP = new LazyPromise<ISnapshotDetails>(async () => {
|
|
754
754
|
let tree: ISnapshotTree | undefined;
|
|
755
755
|
let isRootDataStore = true;
|
|
756
756
|
|
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,11 @@ 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: (dataStorePath: string, packagePath?: readonly string[]) => void,
|
|
119
95
|
private readonly aliasMap: Map<string, string>,
|
|
120
96
|
private readonly writeGCDataAtRoot: boolean,
|
|
121
97
|
private readonly contexts: DataStoreContexts = new DataStoreContexts(baseLogger),
|
|
@@ -290,7 +266,7 @@ export class DataStores implements IDisposable {
|
|
|
290
266
|
}
|
|
291
267
|
}
|
|
292
268
|
|
|
293
|
-
|
|
269
|
+
public processAliasMessageCore(aliasMessage: IDataStoreAliasMessage): boolean {
|
|
294
270
|
if (this.alreadyProcessed(aliasMessage.alias)) {
|
|
295
271
|
return false;
|
|
296
272
|
}
|
|
@@ -411,7 +387,7 @@ export class DataStores implements IDisposable {
|
|
|
411
387
|
context.process(transformed, local, localMessageMetadata);
|
|
412
388
|
|
|
413
389
|
// Notify that a data store changed. This is used to detect if a deleted data store is being used.
|
|
414
|
-
this.dataStoreChanged(envelope.address);
|
|
390
|
+
this.dataStoreChanged(`/${envelope.address}`, context.isLoaded ? context.packagePath : undefined);
|
|
415
391
|
}
|
|
416
392
|
|
|
417
393
|
public async getDataStore(id: string, wait: boolean): Promise<FluidDataStoreContext> {
|
|
@@ -582,9 +558,8 @@ export class DataStores implements IDisposable {
|
|
|
582
558
|
* @param usedRoutes - The routes that are used in all data stores in this Container.
|
|
583
559
|
* @param gcTimestamp - The time when GC was run that generated these used routes. If any node node becomes
|
|
584
560
|
* 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
561
|
*/
|
|
587
|
-
public updateUsedRoutes(usedRoutes: string[], gcTimestamp?: number)
|
|
562
|
+
public updateUsedRoutes(usedRoutes: string[], gcTimestamp?: number) {
|
|
588
563
|
// Get a map of data store ids to routes used in it.
|
|
589
564
|
const usedDataStoreRoutes = unpackChildNodesUsedRoutes(usedRoutes);
|
|
590
565
|
|
|
@@ -597,13 +572,6 @@ export class DataStores implements IDisposable {
|
|
|
597
572
|
for (const [contextId, context] of this.contexts) {
|
|
598
573
|
context.updateUsedRoutes(usedDataStoreRoutes.get(contextId) ?? [], gcTimestamp);
|
|
599
574
|
}
|
|
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
575
|
}
|
|
608
576
|
|
|
609
577
|
/**
|
|
@@ -635,6 +603,18 @@ export class DataStores implements IDisposable {
|
|
|
635
603
|
}
|
|
636
604
|
return outboundRoutes;
|
|
637
605
|
}
|
|
606
|
+
|
|
607
|
+
/**
|
|
608
|
+
* Returns the package path of the node with the given path. This is used by GC to log when an inactive / deleted
|
|
609
|
+
* node is used.
|
|
610
|
+
*/
|
|
611
|
+
public getNodePackagePath(nodePath: string): readonly string[] | undefined {
|
|
612
|
+
// Currently, only return the data store package path for the node since GC is only interested in data stores.
|
|
613
|
+
const dataStoreId = nodePath.split("/")[1];
|
|
614
|
+
const context = this.contexts.get(dataStoreId);
|
|
615
|
+
assert(context !== undefined, "Data store with given id does not exist");
|
|
616
|
+
return context.isLoaded ? context.packagePath : undefined;
|
|
617
|
+
}
|
|
638
618
|
}
|
|
639
619
|
|
|
640
620
|
export function getSummaryForDatastores(
|