@fluidframework/container-runtime 1.2.1 → 2.0.0-internal.1.0.0
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/batchTracker.js +1 -1
- package/dist/batchTracker.js.map +1 -1
- package/dist/blobManager.d.ts +81 -25
- package/dist/blobManager.d.ts.map +1 -1
- package/dist/blobManager.js +301 -100
- package/dist/blobManager.js.map +1 -1
- package/dist/containerRuntime.d.ts +66 -49
- package/dist/containerRuntime.d.ts.map +1 -1
- package/dist/containerRuntime.js +129 -164
- package/dist/containerRuntime.js.map +1 -1
- package/dist/dataStore.js +29 -24
- package/dist/dataStore.js.map +1 -1
- package/dist/dataStoreContext.d.ts +3 -4
- package/dist/dataStoreContext.d.ts.map +1 -1
- package/dist/dataStoreContext.js +16 -23
- package/dist/dataStoreContext.js.map +1 -1
- package/dist/dataStores.d.ts +6 -3
- package/dist/dataStores.d.ts.map +1 -1
- package/dist/dataStores.js +13 -5
- package/dist/dataStores.js.map +1 -1
- package/dist/garbageCollection.d.ts.map +1 -1
- package/dist/garbageCollection.js +17 -12
- package/dist/garbageCollection.js.map +1 -1
- package/dist/opProperties.d.ts +7 -0
- package/dist/opProperties.d.ts.map +1 -0
- package/dist/opProperties.js +20 -0
- package/dist/opProperties.js.map +1 -0
- 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 +28 -4
- package/dist/runningSummarizer.d.ts.map +1 -1
- package/dist/runningSummarizer.js +93 -26
- package/dist/runningSummarizer.js.map +1 -1
- package/dist/summarizer.d.ts +0 -2
- package/dist/summarizer.d.ts.map +1 -1
- package/dist/summarizer.js +34 -15
- package/dist/summarizer.js.map +1 -1
- package/dist/summarizerHeuristics.d.ts +26 -4
- package/dist/summarizerHeuristics.d.ts.map +1 -1
- package/dist/summarizerHeuristics.js +95 -18
- package/dist/summarizerHeuristics.js.map +1 -1
- package/dist/summarizerTypes.d.ts +30 -10
- package/dist/summarizerTypes.d.ts.map +1 -1
- package/dist/summarizerTypes.js.map +1 -1
- package/dist/summaryCollection.js +1 -1
- package/dist/summaryCollection.js.map +1 -1
- package/dist/summaryFormat.d.ts +0 -5
- package/dist/summaryFormat.d.ts.map +1 -1
- package/dist/summaryFormat.js.map +1 -1
- package/dist/summaryGenerator.d.ts +1 -0
- package/dist/summaryGenerator.d.ts.map +1 -1
- package/dist/summaryGenerator.js +11 -9
- package/dist/summaryGenerator.js.map +1 -1
- package/lib/batchTracker.js +1 -1
- package/lib/batchTracker.js.map +1 -1
- package/lib/blobManager.d.ts +81 -25
- package/lib/blobManager.d.ts.map +1 -1
- package/lib/blobManager.js +302 -101
- package/lib/blobManager.js.map +1 -1
- package/lib/containerRuntime.d.ts +66 -49
- package/lib/containerRuntime.d.ts.map +1 -1
- package/lib/containerRuntime.js +131 -166
- package/lib/containerRuntime.js.map +1 -1
- package/lib/dataStore.js +29 -24
- package/lib/dataStore.js.map +1 -1
- package/lib/dataStoreContext.d.ts +3 -4
- package/lib/dataStoreContext.d.ts.map +1 -1
- package/lib/dataStoreContext.js +17 -24
- package/lib/dataStoreContext.js.map +1 -1
- package/lib/dataStores.d.ts +6 -3
- package/lib/dataStores.d.ts.map +1 -1
- package/lib/dataStores.js +13 -5
- package/lib/dataStores.js.map +1 -1
- package/lib/garbageCollection.d.ts.map +1 -1
- package/lib/garbageCollection.js +17 -12
- package/lib/garbageCollection.js.map +1 -1
- package/lib/opProperties.d.ts +7 -0
- package/lib/opProperties.d.ts.map +1 -0
- package/lib/opProperties.js +16 -0
- package/lib/opProperties.js.map +1 -0
- 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 +28 -4
- package/lib/runningSummarizer.d.ts.map +1 -1
- package/lib/runningSummarizer.js +93 -26
- package/lib/runningSummarizer.js.map +1 -1
- package/lib/summarizer.d.ts +0 -2
- package/lib/summarizer.d.ts.map +1 -1
- package/lib/summarizer.js +36 -17
- package/lib/summarizer.js.map +1 -1
- package/lib/summarizerHeuristics.d.ts +26 -4
- package/lib/summarizerHeuristics.d.ts.map +1 -1
- package/lib/summarizerHeuristics.js +95 -18
- package/lib/summarizerHeuristics.js.map +1 -1
- package/lib/summarizerTypes.d.ts +30 -10
- package/lib/summarizerTypes.d.ts.map +1 -1
- package/lib/summarizerTypes.js.map +1 -1
- package/lib/summaryCollection.js +1 -1
- package/lib/summaryCollection.js.map +1 -1
- package/lib/summaryFormat.d.ts +0 -5
- package/lib/summaryFormat.d.ts.map +1 -1
- package/lib/summaryFormat.js.map +1 -1
- package/lib/summaryGenerator.d.ts +1 -0
- package/lib/summaryGenerator.d.ts.map +1 -1
- package/lib/summaryGenerator.js +11 -9
- package/lib/summaryGenerator.js.map +1 -1
- package/package.json +55 -21
- package/src/batchTracker.ts +1 -1
- package/src/blobManager.ts +364 -119
- package/src/containerRuntime.ts +232 -216
- package/src/dataStore.ts +49 -37
- package/src/dataStoreContext.ts +16 -23
- package/src/dataStores.ts +27 -16
- package/src/garbageCollection.ts +13 -7
- package/src/opProperties.ts +19 -0
- package/src/packageVersion.ts +1 -1
- package/src/runningSummarizer.ts +108 -23
- package/src/summarizer.ts +47 -28
- package/src/summarizerHeuristics.ts +133 -19
- package/src/summarizerTypes.ts +37 -10
- package/src/summaryCollection.ts +1 -1
- package/src/summaryFormat.ts +0 -6
- package/src/summaryGenerator.ts +40 -22
- package/dist/opTelemetry.d.ts +0 -22
- package/dist/opTelemetry.d.ts.map +0 -1
- package/dist/opTelemetry.js +0 -59
- package/dist/opTelemetry.js.map +0 -1
- package/lib/opTelemetry.d.ts +0 -22
- package/lib/opTelemetry.d.ts.map +0 -1
- package/lib/opTelemetry.js +0 -55
- package/lib/opTelemetry.js.map +0 -1
- package/src/opTelemetry.ts +0 -71
package/src/dataStore.ts
CHANGED
|
@@ -54,6 +54,7 @@ enum AliasState {
|
|
|
54
54
|
class DataStore implements IDataStore {
|
|
55
55
|
private aliasState: AliasState = AliasState.None;
|
|
56
56
|
private alias: string | undefined;
|
|
57
|
+
private readonly pendingAliases: Map<string, Promise<AliasResult>>;
|
|
57
58
|
private aliasResult: Promise<AliasResult> | undefined;
|
|
58
59
|
|
|
59
60
|
async trySetAlias(alias: string): Promise<AliasResult> {
|
|
@@ -75,14 +76,25 @@ class DataStore implements IDataStore {
|
|
|
75
76
|
case AliasState.Aliased:
|
|
76
77
|
return this.alias === alias ? "Success" : "AlreadyAliased";
|
|
77
78
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
79
|
+
case AliasState.None: {
|
|
80
|
+
const existingAlias = this.pendingAliases.get(alias);
|
|
81
|
+
if (existingAlias !== undefined) {
|
|
82
|
+
// There is already another datastore which will be aliased
|
|
83
|
+
// to the same name
|
|
84
|
+
return "Conflict";
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// There is no current or past alias operation for this datastore,
|
|
88
|
+
// or for this alias, so it is safe to continue execution
|
|
89
|
+
break;
|
|
90
|
+
}
|
|
91
|
+
|
|
81
92
|
default: unreachableCase(this.aliasState);
|
|
82
93
|
}
|
|
83
94
|
|
|
84
95
|
this.aliasState = AliasState.Aliasing;
|
|
85
96
|
this.aliasResult = this.trySetAliasInternal(alias);
|
|
97
|
+
this.pendingAliases.set(alias, this.aliasResult);
|
|
86
98
|
return this.aliasResult;
|
|
87
99
|
}
|
|
88
100
|
|
|
@@ -92,13 +104,7 @@ class DataStore implements IDataStore {
|
|
|
92
104
|
alias,
|
|
93
105
|
};
|
|
94
106
|
|
|
95
|
-
|
|
96
|
-
// older versions, we still have to call bindToContext.
|
|
97
|
-
if (this.fluidDataStoreChannel.makeVisibleAndAttachGraph !== undefined) {
|
|
98
|
-
this.fluidDataStoreChannel.makeVisibleAndAttachGraph();
|
|
99
|
-
} else {
|
|
100
|
-
this.fluidDataStoreChannel.bindToContext();
|
|
101
|
-
}
|
|
107
|
+
this.fluidDataStoreChannel.makeVisibleAndAttachGraph();
|
|
102
108
|
|
|
103
109
|
if (this.runtime.attachState === AttachState.Detached) {
|
|
104
110
|
const localResult = this.datastores.processAliasMessageCore(message);
|
|
@@ -108,34 +114,37 @@ class DataStore implements IDataStore {
|
|
|
108
114
|
return localResult ? "Success" : "Conflict";
|
|
109
115
|
}
|
|
110
116
|
|
|
111
|
-
const aliased = await this
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
117
|
+
const aliased = await this
|
|
118
|
+
.ackBasedPromise<boolean>((resolve) => {
|
|
119
|
+
this.runtime.submitDataStoreAliasOp(message, resolve);
|
|
120
|
+
})
|
|
121
|
+
.catch((error) => {
|
|
122
|
+
this.logger.sendErrorEvent({
|
|
123
|
+
eventName: "AliasingException",
|
|
124
|
+
alias: {
|
|
125
|
+
value: alias,
|
|
126
|
+
tag: TelemetryDataTag.UserData,
|
|
127
|
+
},
|
|
128
|
+
internalId: {
|
|
129
|
+
value: this.internalId,
|
|
130
|
+
tag: TelemetryDataTag.CodeArtifact,
|
|
131
|
+
},
|
|
132
|
+
}, error);
|
|
133
|
+
|
|
134
|
+
return false;
|
|
135
|
+
}).finally(() => {
|
|
136
|
+
this.pendingAliases.delete(alias);
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
if (!aliased) {
|
|
134
140
|
this.aliasState = AliasState.None;
|
|
135
|
-
|
|
136
|
-
|
|
141
|
+
this.aliasResult = undefined;
|
|
142
|
+
return "Conflict";
|
|
143
|
+
}
|
|
137
144
|
|
|
138
|
-
|
|
145
|
+
this.alias = alias;
|
|
146
|
+
this.aliasState = AliasState.Aliased;
|
|
147
|
+
return "Success";
|
|
139
148
|
}
|
|
140
149
|
|
|
141
150
|
async request(request: IRequest): Promise<IResponse> {
|
|
@@ -148,7 +157,10 @@ class DataStore implements IDataStore {
|
|
|
148
157
|
private readonly runtime: ContainerRuntime,
|
|
149
158
|
private readonly datastores: DataStores,
|
|
150
159
|
private readonly logger: ITelemetryLogger,
|
|
151
|
-
) {
|
|
160
|
+
) {
|
|
161
|
+
this.pendingAliases = datastores.pendingAliases;
|
|
162
|
+
}
|
|
163
|
+
|
|
152
164
|
public get IFluidRouter() { return this.fluidDataStoreChannel; }
|
|
153
165
|
|
|
154
166
|
private async ackBasedPromise<T>(
|
package/src/dataStoreContext.ts
CHANGED
|
@@ -13,7 +13,6 @@ import {
|
|
|
13
13
|
import {
|
|
14
14
|
IAudience,
|
|
15
15
|
IDeltaManager,
|
|
16
|
-
BindState,
|
|
17
16
|
AttachState,
|
|
18
17
|
ILoaderOptions,
|
|
19
18
|
} from "@fluidframework/container-definitions";
|
|
@@ -232,7 +231,9 @@ export abstract class FluidDataStoreContext extends TypedEventEmitter<IFluidData
|
|
|
232
231
|
protected registry: IFluidDataStoreRegistry | undefined;
|
|
233
232
|
|
|
234
233
|
protected detachedRuntimeCreation = false;
|
|
235
|
-
|
|
234
|
+
// back-compat (for tests) - can be removed in 2.0.0-alpha.2.0.0, or earlier if compat tests drop n/n-2 coverage
|
|
235
|
+
// @ts-expect-error - This shouldn't be referenced in the current version, but needs to be here for back-compat
|
|
236
|
+
private readonly bindToContext: () => void;
|
|
236
237
|
protected channel: IFluidDataStoreChannel | undefined;
|
|
237
238
|
private loaded = false;
|
|
238
239
|
protected pending: ISequencedDocumentMessage[] | undefined = [];
|
|
@@ -260,7 +261,6 @@ export abstract class FluidDataStoreContext extends TypedEventEmitter<IFluidData
|
|
|
260
261
|
constructor(
|
|
261
262
|
props: IFluidDataStoreContextProps,
|
|
262
263
|
private readonly existing: boolean,
|
|
263
|
-
private bindState: BindState,
|
|
264
264
|
public readonly isLocalDataStore: boolean,
|
|
265
265
|
private readonly makeLocallyVisibleFn: () => void,
|
|
266
266
|
) {
|
|
@@ -282,11 +282,8 @@ export abstract class FluidDataStoreContext extends TypedEventEmitter<IFluidData
|
|
|
282
282
|
this.containerRuntime.attachState : AttachState.Detached;
|
|
283
283
|
|
|
284
284
|
this.bindToContext = () => {
|
|
285
|
-
assert(this.bindState === BindState.NotBound, 0x13b /* "datastore context is already in bound state" */);
|
|
286
|
-
this.bindState = BindState.Binding;
|
|
287
285
|
assert(this.channel !== undefined, 0x13c /* "undefined channel on datastore context" */);
|
|
288
286
|
this.makeLocallyVisible();
|
|
289
|
-
this.bindState = BindState.Bound;
|
|
290
287
|
};
|
|
291
288
|
|
|
292
289
|
const thisSummarizeInternal =
|
|
@@ -319,7 +316,7 @@ export abstract class FluidDataStoreContext extends TypedEventEmitter<IFluidData
|
|
|
319
316
|
}
|
|
320
317
|
|
|
321
318
|
private rejectDeferredRealize(reason: string, packageName?: string): never {
|
|
322
|
-
throw new LoggingError(reason, { packageName: { value: packageName, tag: TelemetryDataTag.
|
|
319
|
+
throw new LoggingError(reason, { packageName: { value: packageName, tag: TelemetryDataTag.CodeArtifact } });
|
|
323
320
|
}
|
|
324
321
|
|
|
325
322
|
public async realize(): Promise<IFluidDataStoreChannel> {
|
|
@@ -328,7 +325,12 @@ export abstract class FluidDataStoreContext extends TypedEventEmitter<IFluidData
|
|
|
328
325
|
this.channelDeferred = new Deferred<IFluidDataStoreChannel>();
|
|
329
326
|
this.realizeCore(this.existing).catch((error) => {
|
|
330
327
|
const errorWrapped = DataProcessingError.wrapIfUnrecognized(error, "realizeFluidDataStoreContext");
|
|
331
|
-
errorWrapped.addTelemetryProperties({
|
|
328
|
+
errorWrapped.addTelemetryProperties({
|
|
329
|
+
fluidDataStoreId: {
|
|
330
|
+
value: this.id,
|
|
331
|
+
tag: TelemetryDataTag.CodeArtifact,
|
|
332
|
+
},
|
|
333
|
+
});
|
|
332
334
|
this.channelDeferred?.reject(errorWrapped);
|
|
333
335
|
this.logger.sendErrorEvent({ eventName: "RealizeError" }, errorWrapped);
|
|
334
336
|
});
|
|
@@ -690,7 +692,10 @@ export abstract class FluidDataStoreContext extends TypedEventEmitter<IFluidData
|
|
|
690
692
|
} catch (error) {
|
|
691
693
|
this.channelDeferred?.reject(error);
|
|
692
694
|
this.logger.sendErrorEvent(
|
|
693
|
-
{ eventName: "BindRuntimeError", fluidDataStoreId: {
|
|
695
|
+
{ eventName: "BindRuntimeError", fluidDataStoreId: {
|
|
696
|
+
value: this.id,
|
|
697
|
+
tag: TelemetryDataTag.CodeArtifact,
|
|
698
|
+
} },
|
|
694
699
|
error);
|
|
695
700
|
}
|
|
696
701
|
}
|
|
@@ -783,7 +788,6 @@ export class RemoteFluidDataStoreContext extends FluidDataStoreContext {
|
|
|
783
788
|
super(
|
|
784
789
|
props,
|
|
785
790
|
true /* existing */,
|
|
786
|
-
BindState.Bound,
|
|
787
791
|
false /* isLocalDataStore */,
|
|
788
792
|
() => {
|
|
789
793
|
throw new Error("Already attached");
|
|
@@ -809,11 +813,7 @@ export class RemoteFluidDataStoreContext extends FluidDataStoreContext {
|
|
|
809
813
|
|
|
810
814
|
const localReadAndParse = async <T>(id: string) => readAndParse<T>(this.storage, id);
|
|
811
815
|
if (tree) {
|
|
812
|
-
|
|
813
|
-
tree = loadedSummary.baseSummary;
|
|
814
|
-
// Prepend outstanding ops to pending queue of ops to process.
|
|
815
|
-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
816
|
-
this.pending = loadedSummary.outstandingOps.concat(this.pending!);
|
|
816
|
+
tree = await this.summarizerNode.loadBaseSummary(tree, localReadAndParse);
|
|
817
817
|
}
|
|
818
818
|
|
|
819
819
|
if (!!tree && tree.blobs[dataStoreAttributesBlobName] !== undefined) {
|
|
@@ -892,7 +892,6 @@ export class LocalFluidDataStoreContextBase extends FluidDataStoreContext {
|
|
|
892
892
|
super(
|
|
893
893
|
props,
|
|
894
894
|
props.snapshotTree !== undefined ? true : false /* existing */,
|
|
895
|
-
props.snapshotTree ? BindState.Bound : BindState.NotBound,
|
|
896
895
|
true /* isLocalDataStore */,
|
|
897
896
|
props.makeLocallyVisibleFn,
|
|
898
897
|
);
|
|
@@ -1040,13 +1039,7 @@ export class LocalDetachedFluidDataStoreContext
|
|
|
1040
1039
|
super.bindRuntime(dataStoreChannel);
|
|
1041
1040
|
|
|
1042
1041
|
if (await this.isRoot()) {
|
|
1043
|
-
|
|
1044
|
-
// For older versions, we still have to call bindToContext.
|
|
1045
|
-
if (dataStoreChannel.makeVisibleAndAttachGraph !== undefined) {
|
|
1046
|
-
dataStoreChannel.makeVisibleAndAttachGraph();
|
|
1047
|
-
} else {
|
|
1048
|
-
dataStoreChannel.bindToContext();
|
|
1049
|
-
}
|
|
1042
|
+
dataStoreChannel.makeVisibleAndAttachGraph();
|
|
1050
1043
|
}
|
|
1051
1044
|
}
|
|
1052
1045
|
|
package/src/dataStores.ts
CHANGED
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
ISnapshotTree,
|
|
13
13
|
} from "@fluidframework/protocol-definitions";
|
|
14
14
|
import {
|
|
15
|
+
AliasResult,
|
|
15
16
|
channelsTreeName,
|
|
16
17
|
CreateChildSummarizerNodeFn,
|
|
17
18
|
CreateChildSummarizerNodeParam,
|
|
@@ -28,11 +29,11 @@ import {
|
|
|
28
29
|
ITelemetryContext,
|
|
29
30
|
} from "@fluidframework/runtime-definitions";
|
|
30
31
|
import {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
32
|
+
convertSnapshotTreeToSummaryTree,
|
|
33
|
+
convertToSummaryTree,
|
|
34
|
+
create404Response,
|
|
35
|
+
responseToException,
|
|
36
|
+
SummaryTreeBuilder,
|
|
36
37
|
} from "@fluidframework/runtime-utils";
|
|
37
38
|
import { ChildLogger, LoggingError, TelemetryDataTag } from "@fluidframework/telemetry-utils";
|
|
38
39
|
import { AttachState } from "@fluidframework/container-definitions";
|
|
@@ -55,10 +56,10 @@ import { GCNodeType } from "./garbageCollection";
|
|
|
55
56
|
|
|
56
57
|
type PendingAliasResolve = (success: boolean) => void;
|
|
57
58
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
59
|
+
/**
|
|
60
|
+
* This class encapsulates data store handling. Currently it is only used by the container runtime,
|
|
61
|
+
* but eventually could be hosted on any channel once we formalize the channel api boundary.
|
|
62
|
+
*/
|
|
62
63
|
export class DataStores implements IDisposable {
|
|
63
64
|
// Stores tracked by the Domain
|
|
64
65
|
private readonly pendingAttach = new Map<string, IAttachMessage>();
|
|
@@ -82,6 +83,7 @@ export class DataStores implements IDisposable {
|
|
|
82
83
|
// The handle to the container runtime. This is used mainly for GC purposes to represent outbound reference from
|
|
83
84
|
// the container runtime to other nodes.
|
|
84
85
|
private readonly containerRuntimeHandle: IFluidHandle;
|
|
86
|
+
private readonly pendingAliasMap: Map<string, Promise<AliasResult>> = new Map<string, Promise<AliasResult>>();
|
|
85
87
|
|
|
86
88
|
constructor(
|
|
87
89
|
private readonly baseSnapshot: ISnapshotTree | undefined,
|
|
@@ -173,10 +175,19 @@ export class DataStores implements IDisposable {
|
|
|
173
175
|
};
|
|
174
176
|
}
|
|
175
177
|
|
|
176
|
-
public aliases(): ReadonlyMap<string, string> {
|
|
178
|
+
public get aliases(): ReadonlyMap<string, string> {
|
|
177
179
|
return this.aliasMap;
|
|
178
180
|
}
|
|
179
181
|
|
|
182
|
+
public get pendingAliases(): Map<string, Promise<AliasResult>> {
|
|
183
|
+
return this.pendingAliasMap;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
public async waitIfPendingAlias(maybeAlias: string): Promise<AliasResult> {
|
|
187
|
+
const pendingAliasPromise = this.pendingAliases.get(maybeAlias);
|
|
188
|
+
return pendingAliasPromise === undefined ? "Success" : pendingAliasPromise;
|
|
189
|
+
}
|
|
190
|
+
|
|
180
191
|
public processAttachMessage(message: ISequencedDocumentMessage, local: boolean) {
|
|
181
192
|
const attachMessage = message.contents as InboundAttachMessage;
|
|
182
193
|
|
|
@@ -191,7 +202,7 @@ export class DataStores implements IDisposable {
|
|
|
191
202
|
return;
|
|
192
203
|
}
|
|
193
204
|
|
|
194
|
-
|
|
205
|
+
// If a non-local operation then go and create the object, otherwise mark it as officially attached.
|
|
195
206
|
if (this.alreadyProcessed(attachMessage.id)) {
|
|
196
207
|
// TODO: dataStoreId may require a different tag from PackageData #7488
|
|
197
208
|
const error = new DataCorruptionError(
|
|
@@ -201,7 +212,7 @@ export class DataStores implements IDisposable {
|
|
|
201
212
|
...extractSafePropertiesFromMessage(message),
|
|
202
213
|
dataStoreId: {
|
|
203
214
|
value: attachMessage.id,
|
|
204
|
-
tag: TelemetryDataTag.
|
|
215
|
+
tag: TelemetryDataTag.CodeArtifact,
|
|
205
216
|
},
|
|
206
217
|
},
|
|
207
218
|
);
|
|
@@ -351,7 +362,7 @@ export class DataStores implements IDisposable {
|
|
|
351
362
|
return context;
|
|
352
363
|
}
|
|
353
364
|
|
|
354
|
-
public _createFluidDataStoreContext(pkg: string[], id: string,
|
|
365
|
+
public _createFluidDataStoreContext(pkg: string[], id: string, props?: any) {
|
|
355
366
|
assert(!id.includes("/"), 0x30d /* Id cannot contain slashes */);
|
|
356
367
|
const context = new LocalFluidDataStoreContext({
|
|
357
368
|
id,
|
|
@@ -365,7 +376,7 @@ export class DataStores implements IDisposable {
|
|
|
365
376
|
),
|
|
366
377
|
makeLocallyVisibleFn: () => this.makeDataStoreLocallyVisible(id),
|
|
367
378
|
snapshotTree: undefined,
|
|
368
|
-
isRootDataStore:
|
|
379
|
+
isRootDataStore: false,
|
|
369
380
|
writeGCDataAtRoot: this.writeGCDataAtRoot,
|
|
370
381
|
disableIsolatedChannels: this.runtime.disableIsolatedChannels,
|
|
371
382
|
createProps: props,
|
|
@@ -440,7 +451,7 @@ export class DataStores implements IDisposable {
|
|
|
440
451
|
eventName: "SignalFluidDataStoreNotFound",
|
|
441
452
|
fluidDataStoreId: {
|
|
442
453
|
value: address,
|
|
443
|
-
tag: TelemetryDataTag.
|
|
454
|
+
tag: TelemetryDataTag.CodeArtifact,
|
|
444
455
|
},
|
|
445
456
|
});
|
|
446
457
|
return;
|
|
@@ -470,7 +481,7 @@ export class DataStores implements IDisposable {
|
|
|
470
481
|
} else {
|
|
471
482
|
eventName = "attached";
|
|
472
483
|
}
|
|
473
|
-
for (const [,context] of this.contexts) {
|
|
484
|
+
for (const [, context] of this.contexts) {
|
|
474
485
|
// Fire only for bounded stores.
|
|
475
486
|
if (!this.contexts.isNotBound(context.id)) {
|
|
476
487
|
context.emit(eventName);
|
package/src/garbageCollection.ts
CHANGED
|
@@ -63,7 +63,7 @@ export const gcBlobPrefix = "__gc";
|
|
|
63
63
|
// Feature gate key to turn GC on / off.
|
|
64
64
|
const runGCKey = "Fluid.GarbageCollection.RunGC";
|
|
65
65
|
// Feature gate key to turn GC sweep on / off.
|
|
66
|
-
const runSweepKey = "Fluid.GarbageCollection.RunSweep";
|
|
66
|
+
// const runSweepKey = "Fluid.GarbageCollection.RunSweep";
|
|
67
67
|
// Feature gate key to turn GC test mode on / off.
|
|
68
68
|
const gcTestModeKey = "Fluid.GarbageCollection.GCTestMode";
|
|
69
69
|
// Feature gate key to write GC data at the root of the summary tree.
|
|
@@ -486,7 +486,7 @@ export class GarbageCollector implements IGarbageCollector {
|
|
|
486
486
|
|
|
487
487
|
// Set the Session Expiry only if the flag is enabled or the test option is set.
|
|
488
488
|
if (this.mc.config.getBoolean(runSessionExpiryKey) && this.gcEnabled) {
|
|
489
|
-
this.sessionExpiryTimeoutMs = defaultSessionExpiryDurationMs;
|
|
489
|
+
this.sessionExpiryTimeoutMs = this.gcOptions.sessionExpiryTimeoutMs ?? defaultSessionExpiryDurationMs;
|
|
490
490
|
}
|
|
491
491
|
}
|
|
492
492
|
|
|
@@ -503,14 +503,19 @@ export class GarbageCollector implements IGarbageCollector {
|
|
|
503
503
|
(timer) => { this.sessionExpiryTimer = timer; },
|
|
504
504
|
);
|
|
505
505
|
|
|
506
|
+
// TEMPORARY: Hardcode a default of 2 days which is the value used in the ODSP driver.
|
|
507
|
+
// This unblocks the Sweep Log (see logSweepEvents function).
|
|
508
|
+
// This will be removed before sweep is fully implemented.
|
|
509
|
+
const snapshotCacheExpiryMs = createParams.snapshotCacheExpiryMs ?? 2 * 24 * 60 * 60 * 1000;
|
|
510
|
+
|
|
506
511
|
/**
|
|
507
512
|
* Sweep timeout is the time after which unreferenced content can be swept.
|
|
508
513
|
* Sweep timeout = session expiry timeout + snapshot cache expiry timeout + one day buffer. The buffer is
|
|
509
514
|
* added to account for any clock skew. We use server timestamps throughout so the skew should be minimal
|
|
510
515
|
* but make it one day to be safe.
|
|
511
516
|
*/
|
|
512
|
-
if (
|
|
513
|
-
this.sweepTimeoutMs = this.sessionExpiryTimeoutMs +
|
|
517
|
+
if (snapshotCacheExpiryMs !== undefined) {
|
|
518
|
+
this.sweepTimeoutMs = this.sessionExpiryTimeoutMs + snapshotCacheExpiryMs + oneDayMs;
|
|
514
519
|
}
|
|
515
520
|
}
|
|
516
521
|
|
|
@@ -538,9 +543,10 @@ export class GarbageCollector implements IGarbageCollector {
|
|
|
538
543
|
* 3. Sweep should be enabled for this container (this.sweepEnabled). This can be overridden via runSweep
|
|
539
544
|
* feature flag.
|
|
540
545
|
*/
|
|
541
|
-
this.shouldRunSweep =
|
|
542
|
-
|
|
543
|
-
&&
|
|
546
|
+
this.shouldRunSweep = false; // disable while TEMPORARY measure hardcoding snapshotCacheExpiryMs is here
|
|
547
|
+
// this.shouldRunGC
|
|
548
|
+
// && this.sweepTimeoutMs !== undefined
|
|
549
|
+
// && (this.mc.config.getBoolean(runSweepKey) ?? this.sweepEnabled);
|
|
544
550
|
|
|
545
551
|
this.trackGCState = this.mc.config.getBoolean(trackGCStateKey) === true;
|
|
546
552
|
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
|
+
* Licensed under the MIT License.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { ISequencedDocumentMessage, ISequencedDocumentSystemMessage } from "@fluidframework/protocol-definitions";
|
|
7
|
+
|
|
8
|
+
export const opSize = (op: ISequencedDocumentMessage): number => {
|
|
9
|
+
// Some messages may already have string contents,
|
|
10
|
+
// so stringifying them again will add inaccurate overhead.
|
|
11
|
+
const content = typeof op.contents === "string" ?
|
|
12
|
+
op.contents :
|
|
13
|
+
JSON.stringify(op.contents) ?? "";
|
|
14
|
+
const data = opHasData(op) ? op.data : "";
|
|
15
|
+
return content.length + data.length;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
const opHasData = (op: ISequencedDocumentMessage): op is ISequencedDocumentSystemMessage =>
|
|
19
|
+
(op as ISequencedDocumentSystemMessage).data !== undefined;
|
package/src/packageVersion.ts
CHANGED