@fluidframework/datastore 2.0.0-rc.2.0.2 → 2.0.0-rc.3.0.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/CHANGELOG.md +23 -0
- package/api-report/datastore.api.md +7 -5
- package/dist/channelContext.d.ts +5 -4
- package/dist/channelContext.d.ts.map +1 -1
- package/dist/channelContext.js +10 -10
- package/dist/channelContext.js.map +1 -1
- package/dist/channelDeltaConnection.d.ts +2 -2
- package/dist/channelDeltaConnection.d.ts.map +1 -1
- package/dist/channelDeltaConnection.js +5 -5
- package/dist/channelDeltaConnection.js.map +1 -1
- package/dist/channelStorageService.d.ts +2 -2
- package/dist/channelStorageService.d.ts.map +1 -1
- package/dist/channelStorageService.js +2 -2
- package/dist/channelStorageService.js.map +1 -1
- package/dist/dataStoreRuntime.d.ts +10 -8
- package/dist/dataStoreRuntime.d.ts.map +1 -1
- package/dist/dataStoreRuntime.js +114 -97
- package/dist/dataStoreRuntime.js.map +1 -1
- package/dist/fluidHandle.d.ts +1 -1
- package/dist/fluidHandle.d.ts.map +1 -1
- package/dist/fluidHandle.js +2 -2
- package/dist/fluidHandle.js.map +1 -1
- package/dist/legacy.d.ts +19 -0
- package/dist/localChannelContext.d.ts +7 -6
- package/dist/localChannelContext.d.ts.map +1 -1
- package/dist/localChannelContext.js +16 -16
- package/dist/localChannelContext.js.map +1 -1
- package/dist/localChannelStorageService.d.ts.map +1 -1
- package/dist/localChannelStorageService.js +2 -2
- package/dist/localChannelStorageService.js.map +1 -1
- package/dist/packageVersion.d.ts +9 -0
- package/dist/packageVersion.d.ts.map +1 -0
- package/dist/packageVersion.js +12 -0
- package/dist/packageVersion.js.map +1 -0
- package/dist/public.d.ts +12 -0
- package/dist/remoteChannelContext.d.ts +3 -2
- package/dist/remoteChannelContext.d.ts.map +1 -1
- package/dist/remoteChannelContext.js +12 -12
- package/dist/remoteChannelContext.js.map +1 -1
- package/internal.d.ts +11 -0
- package/legacy.d.ts +11 -0
- package/lib/channelContext.d.ts +5 -4
- package/lib/channelContext.d.ts.map +1 -1
- package/lib/channelContext.js +4 -4
- package/lib/channelContext.js.map +1 -1
- package/lib/channelDeltaConnection.d.ts +2 -2
- package/lib/channelDeltaConnection.d.ts.map +1 -1
- package/lib/channelDeltaConnection.js +2 -2
- package/lib/channelDeltaConnection.js.map +1 -1
- package/lib/channelStorageService.d.ts +2 -2
- package/lib/channelStorageService.d.ts.map +1 -1
- package/lib/channelStorageService.js +1 -1
- package/lib/channelStorageService.js.map +1 -1
- package/lib/dataStoreRuntime.d.ts +10 -8
- package/lib/dataStoreRuntime.d.ts.map +1 -1
- package/lib/dataStoreRuntime.js +52 -35
- package/lib/dataStoreRuntime.js.map +1 -1
- package/lib/fluidHandle.d.ts +1 -1
- package/lib/fluidHandle.d.ts.map +1 -1
- package/lib/fluidHandle.js +1 -1
- package/lib/fluidHandle.js.map +1 -1
- package/lib/legacy.d.ts +19 -0
- package/lib/localChannelContext.d.ts +7 -6
- package/lib/localChannelContext.d.ts.map +1 -1
- package/lib/localChannelContext.js +2 -2
- package/lib/localChannelContext.js.map +1 -1
- package/lib/localChannelStorageService.d.ts.map +1 -1
- package/lib/localChannelStorageService.js +1 -1
- package/lib/localChannelStorageService.js.map +1 -1
- package/lib/packageVersion.d.ts +9 -0
- package/lib/packageVersion.d.ts.map +1 -0
- package/lib/packageVersion.js +9 -0
- package/lib/packageVersion.js.map +1 -0
- package/lib/public.d.ts +12 -0
- package/lib/remoteChannelContext.d.ts +3 -2
- package/lib/remoteChannelContext.d.ts.map +1 -1
- package/lib/remoteChannelContext.js +2 -2
- package/lib/remoteChannelContext.js.map +1 -1
- package/package.json +38 -57
- package/src/channelContext.ts +12 -12
- package/src/channelDeltaConnection.ts +4 -4
- package/src/channelStorageService.ts +3 -3
- package/src/dataStoreRuntime.ts +104 -76
- package/src/fluidHandle.ts +2 -2
- package/src/localChannelContext.ts +11 -10
- package/src/localChannelStorageService.ts +2 -2
- package/src/packageVersion.ts +9 -0
- package/src/remoteChannelContext.ts +13 -13
- package/api-extractor-cjs.json +0 -8
- package/dist/datastore-alpha.d.ts +0 -334
- package/dist/datastore-beta.d.ts +0 -46
- package/dist/datastore-public.d.ts +0 -46
- package/dist/datastore-untrimmed.d.ts +0 -341
- package/lib/datastore-alpha.d.ts +0 -334
- package/lib/datastore-beta.d.ts +0 -46
- package/lib/datastore-public.d.ts +0 -46
- package/lib/datastore-untrimmed.d.ts +0 -341
- package/lib/test/channelStorageService.spec.js +0 -70
- package/lib/test/channelStorageService.spec.js.map +0 -1
- package/lib/test/dataStoreRuntime.spec.js +0 -121
- package/lib/test/dataStoreRuntime.spec.js.map +0 -1
- package/lib/test/localChannelContext.spec.js +0 -41
- package/lib/test/localChannelContext.spec.js.map +0 -1
- package/lib/test/localChannelStorageService.spec.js +0 -72
- package/lib/test/localChannelStorageService.spec.js.map +0 -1
- package/lib/test/remoteChannelContext.spec.js +0 -33
- package/lib/test/remoteChannelContext.spec.js.map +0 -1
- package/lib/test/types/validateDatastorePrevious.generated.js +0 -16
- package/lib/test/types/validateDatastorePrevious.generated.js.map +0 -1
- /package/{dist → lib}/tsdoc-metadata.json +0 -0
package/dist/dataStoreRuntime.js
CHANGED
|
@@ -6,18 +6,19 @@
|
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
7
|
exports.mixinSummaryHandler = exports.mixinRequestHandler = exports.FluidDataStoreRuntime = exports.DataStoreMessageType = void 0;
|
|
8
8
|
const client_utils_1 = require("@fluid-internal/client-utils");
|
|
9
|
-
const telemetry_utils_1 = require("@fluidframework/telemetry-utils");
|
|
10
|
-
const core_utils_1 = require("@fluidframework/core-utils");
|
|
11
9
|
const container_definitions_1 = require("@fluidframework/container-definitions");
|
|
12
|
-
const
|
|
10
|
+
const internal_1 = require("@fluidframework/core-utils/internal");
|
|
11
|
+
const internal_2 = require("@fluidframework/driver-utils/internal");
|
|
13
12
|
const protocol_definitions_1 = require("@fluidframework/protocol-definitions");
|
|
14
|
-
const
|
|
15
|
-
const
|
|
13
|
+
const internal_3 = require("@fluidframework/runtime-definitions/internal");
|
|
14
|
+
const internal_4 = require("@fluidframework/runtime-utils/internal");
|
|
15
|
+
const internal_5 = require("@fluidframework/telemetry-utils/internal");
|
|
16
16
|
const uuid_1 = require("uuid");
|
|
17
17
|
const channelContext_js_1 = require("./channelContext.js");
|
|
18
|
+
const fluidHandle_js_1 = require("./fluidHandle.js");
|
|
18
19
|
const localChannelContext_js_1 = require("./localChannelContext.js");
|
|
20
|
+
const packageVersion_js_1 = require("./packageVersion.js");
|
|
19
21
|
const remoteChannelContext_js_1 = require("./remoteChannelContext.js");
|
|
20
|
-
const fluidHandle_js_1 = require("./fluidHandle.js");
|
|
21
22
|
/**
|
|
22
23
|
* @alpha
|
|
23
24
|
*/
|
|
@@ -48,7 +49,7 @@ class FluidDataStoreRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
48
49
|
return this._attachState;
|
|
49
50
|
}
|
|
50
51
|
get absolutePath() {
|
|
51
|
-
return (0,
|
|
52
|
+
return (0, internal_4.generateHandleContextPath)(this.id, this.routeContext);
|
|
52
53
|
}
|
|
53
54
|
get routeContext() {
|
|
54
55
|
return this.dataStoreContext.IFluidHandleContext;
|
|
@@ -106,18 +107,18 @@ class FluidDataStoreRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
106
107
|
this._disposed = false;
|
|
107
108
|
this.contexts = new Map();
|
|
108
109
|
this.pendingAttach = new Set();
|
|
109
|
-
this.deferredAttached = new
|
|
110
|
+
this.deferredAttached = new internal_1.Deferred();
|
|
110
111
|
this.localChannelContextQueue = new Map();
|
|
111
112
|
this.notBoundedChannelContextSet = new Set();
|
|
112
113
|
// A list of handles that are bound when the data store is not visible. We have to make them visible when the data
|
|
113
114
|
// store becomes visible.
|
|
114
115
|
this.pendingHandlesToMakeVisible = new Set();
|
|
115
|
-
(0,
|
|
116
|
-
this.mc = (0,
|
|
116
|
+
(0, internal_1.assert)(!dataStoreContext.id.includes("/"), 0x30e /* Id cannot contain slashes. DataStoreContext should have validated this. */);
|
|
117
|
+
this.mc = (0, internal_5.createChildMonitoringContext)({
|
|
117
118
|
logger: dataStoreContext.logger,
|
|
118
119
|
namespace: "FluidDataStoreRuntime",
|
|
119
120
|
properties: {
|
|
120
|
-
all: { dataStoreId: (0, uuid_1.v4)() },
|
|
121
|
+
all: { dataStoreId: (0, uuid_1.v4)(), dataStoreVersion: packageVersion_js_1.pkgVersion },
|
|
121
122
|
},
|
|
122
123
|
});
|
|
123
124
|
this.id = dataStoreContext.id;
|
|
@@ -152,13 +153,13 @@ class FluidDataStoreRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
152
153
|
}
|
|
153
154
|
else {
|
|
154
155
|
channelContext = new remoteChannelContext_js_1.RemoteChannelContext(this, dataStoreContext, dataStoreContext.storage, (content, localOpMetadata) => this.submitChannelOp(path, content, localOpMetadata), (address) => this.setChannelDirty(address), (srcHandle, outboundHandle) => this.addedGCOutboundReference(srcHandle, outboundHandle), path, tree.trees[path], this.sharedObjectRegistry, undefined /* extraBlobs */, this.dataStoreContext.getCreateChildSummarizerNodeFn(path, {
|
|
155
|
-
type:
|
|
156
|
+
type: internal_3.CreateSummarizerNodeSource.FromSummary,
|
|
156
157
|
}));
|
|
157
158
|
}
|
|
158
159
|
this.contexts.set(path, channelContext);
|
|
159
160
|
});
|
|
160
161
|
}
|
|
161
|
-
this.entryPoint = new fluidHandle_js_1.FluidObjectHandle(new
|
|
162
|
+
this.entryPoint = new fluidHandle_js_1.FluidObjectHandle(new internal_1.LazyPromise(async () => provideEntryPoint(this)), "", this.objectsRoutingContext);
|
|
162
163
|
this.attachListener();
|
|
163
164
|
this._attachState = dataStoreContext.attachState;
|
|
164
165
|
/**
|
|
@@ -174,11 +175,11 @@ class FluidDataStoreRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
174
175
|
if (existing) {
|
|
175
176
|
this.visibilityState =
|
|
176
177
|
dataStoreContext.attachState === container_definitions_1.AttachState.Detached
|
|
177
|
-
?
|
|
178
|
-
:
|
|
178
|
+
? internal_3.VisibilityState.LocallyVisible
|
|
179
|
+
: internal_3.VisibilityState.GloballyVisible;
|
|
179
180
|
}
|
|
180
181
|
else {
|
|
181
|
-
this.visibilityState =
|
|
182
|
+
this.visibilityState = internal_3.VisibilityState.NotVisible;
|
|
182
183
|
}
|
|
183
184
|
// If it's existing we know it has been attached.
|
|
184
185
|
if (existing) {
|
|
@@ -201,7 +202,7 @@ class FluidDataStoreRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
201
202
|
}
|
|
202
203
|
async request(request) {
|
|
203
204
|
try {
|
|
204
|
-
const parser =
|
|
205
|
+
const parser = internal_4.RequestParser.create(request);
|
|
205
206
|
const id = parser.pathParts[0];
|
|
206
207
|
if (id === "_channels" || id === "_custom") {
|
|
207
208
|
return await this.request(parser.createSubRequest(1));
|
|
@@ -215,21 +216,21 @@ class FluidDataStoreRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
215
216
|
}
|
|
216
217
|
catch (error) {
|
|
217
218
|
this.mc.logger.sendErrorEvent({ eventName: "GetChannelFailedInRequest" }, error);
|
|
218
|
-
return (0,
|
|
219
|
+
return (0, internal_4.createResponseError)(500, `Failed to get Channel: ${error}`, request);
|
|
219
220
|
}
|
|
220
221
|
}
|
|
221
222
|
// Otherwise defer to an attached request handler
|
|
222
|
-
return (0,
|
|
223
|
+
return (0, internal_4.create404Response)(request);
|
|
223
224
|
}
|
|
224
225
|
catch (error) {
|
|
225
|
-
return (0,
|
|
226
|
+
return (0, internal_4.exceptionToResponse)(error);
|
|
226
227
|
}
|
|
227
228
|
}
|
|
228
229
|
async getChannel(id) {
|
|
229
230
|
this.verifyNotClosed();
|
|
230
231
|
const context = this.contexts.get(id);
|
|
231
232
|
if (context === undefined) {
|
|
232
|
-
throw new
|
|
233
|
+
throw new internal_5.LoggingError("Channel does not exist");
|
|
233
234
|
}
|
|
234
235
|
return context.getChannel();
|
|
235
236
|
}
|
|
@@ -241,10 +242,10 @@ class FluidDataStoreRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
241
242
|
*/
|
|
242
243
|
validateChannelId(id) {
|
|
243
244
|
if (id.includes("/")) {
|
|
244
|
-
throw new
|
|
245
|
+
throw new internal_5.UsageError(`Id cannot contain slashes: ${id}`);
|
|
245
246
|
}
|
|
246
247
|
if (id.startsWith("_")) {
|
|
247
|
-
throw new
|
|
248
|
+
throw new internal_5.UsageError(`Id cannot start with underscore: ${id}`);
|
|
248
249
|
}
|
|
249
250
|
}
|
|
250
251
|
/**
|
|
@@ -258,7 +259,7 @@ class FluidDataStoreRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
258
259
|
const id = channel.id;
|
|
259
260
|
this.validateChannelId(id);
|
|
260
261
|
this.verifyNotClosed();
|
|
261
|
-
(0,
|
|
262
|
+
(0, internal_1.assert)(!this.contexts.has(id), 0x865 /* addChannel() with existing ID */);
|
|
262
263
|
const type = channel.attributes.type;
|
|
263
264
|
const factory = this.sharedObjectRegistry.get(channel.attributes.type);
|
|
264
265
|
if (factory === undefined) {
|
|
@@ -281,21 +282,21 @@ class FluidDataStoreRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
281
282
|
// - uuids
|
|
282
283
|
// In first two cases we will encode result as strings in more compact form, with leading underscore,
|
|
283
284
|
// to ensure no overlap with user-provided DDS names (see validateChannelId())
|
|
284
|
-
if (this.visibilityState !==
|
|
285
|
+
if (this.visibilityState !== internal_3.VisibilityState.GloballyVisible) {
|
|
285
286
|
// container is detached, only one client observes content, no way to hit collisions with other clients.
|
|
286
|
-
id = (0,
|
|
287
|
+
id = (0, internal_4.encodeCompactIdToString)(2 * this.contexts.size, "_");
|
|
287
288
|
}
|
|
288
289
|
else {
|
|
289
290
|
// Due to back-compat, we could not depend yet on generateDocumentUniqueId() being there.
|
|
290
291
|
// We can remove the need to leverage uuid() as fall-back in couple releases.
|
|
291
292
|
const res = this.dataStoreContext.containerRuntime.generateDocumentUniqueId?.() ?? (0, uuid_1.v4)();
|
|
292
|
-
id = typeof res === "number" ? (0,
|
|
293
|
+
id = typeof res === "number" ? (0, internal_4.encodeCompactIdToString)(2 * res + 1, "_") : res;
|
|
293
294
|
}
|
|
294
|
-
(0,
|
|
295
|
+
(0, internal_1.assert)(!id.includes("/"), 0x8fc /* slash */);
|
|
295
296
|
}
|
|
296
297
|
this.verifyNotClosed();
|
|
297
|
-
(0,
|
|
298
|
-
(0,
|
|
298
|
+
(0, internal_1.assert)(!this.contexts.has(id), 0x179 /* "createChannel() with existing ID" */);
|
|
299
|
+
(0, internal_1.assert)(type !== undefined, 0x209 /* "Factory Type should be defined" */);
|
|
299
300
|
const factory = this.sharedObjectRegistry.get(type);
|
|
300
301
|
if (factory === undefined) {
|
|
301
302
|
throw new Error(`Channel Factory ${type} not registered`);
|
|
@@ -320,7 +321,7 @@ class FluidDataStoreRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
320
321
|
* @param channel - channel to be registered.
|
|
321
322
|
*/
|
|
322
323
|
bindChannel(channel) {
|
|
323
|
-
(0,
|
|
324
|
+
(0, internal_1.assert)(this.notBoundedChannelContextSet.has(channel.id), 0x17b /* "Channel to be bound should be in not bounded set" */);
|
|
324
325
|
this.notBoundedChannelContextSet.delete(channel.id);
|
|
325
326
|
// If our data store is attached, then attach the channel.
|
|
326
327
|
if (this.isAttached) {
|
|
@@ -352,10 +353,10 @@ class FluidDataStoreRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
352
353
|
* globally visible.
|
|
353
354
|
*/
|
|
354
355
|
makeVisibleAndAttachGraph() {
|
|
355
|
-
if (this.visibilityState !==
|
|
356
|
+
if (this.visibilityState !== internal_3.VisibilityState.NotVisible) {
|
|
356
357
|
return;
|
|
357
358
|
}
|
|
358
|
-
this.visibilityState =
|
|
359
|
+
this.visibilityState = internal_3.VisibilityState.LocallyVisible;
|
|
359
360
|
this.pendingHandlesToMakeVisible.forEach((handle) => {
|
|
360
361
|
handle.attachGraph();
|
|
361
362
|
});
|
|
@@ -370,7 +371,7 @@ class FluidDataStoreRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
370
371
|
}
|
|
371
372
|
bind(handle) {
|
|
372
373
|
// If visible, attach the incoming handle's graph. Else, this will be done when we become visible.
|
|
373
|
-
if (this.visibilityState !==
|
|
374
|
+
if (this.visibilityState !== internal_3.VisibilityState.NotVisible) {
|
|
374
375
|
handle.attachGraph();
|
|
375
376
|
return;
|
|
376
377
|
}
|
|
@@ -381,7 +382,7 @@ class FluidDataStoreRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
381
382
|
for (const [, object] of this.contexts) {
|
|
382
383
|
object.setConnectionState(connected, clientId);
|
|
383
384
|
}
|
|
384
|
-
(0,
|
|
385
|
+
(0, internal_5.raiseConnectedEvent)(this.logger, this, connected, clientId);
|
|
385
386
|
}
|
|
386
387
|
getQuorum() {
|
|
387
388
|
return this.quorum;
|
|
@@ -395,7 +396,7 @@ class FluidDataStoreRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
395
396
|
}
|
|
396
397
|
createRemoteChannelContext(attachMessage, summarizerNodeParams) {
|
|
397
398
|
const flatBlobs = new Map();
|
|
398
|
-
const snapshotTree = (0,
|
|
399
|
+
const snapshotTree = (0, internal_2.buildSnapshotTree)(attachMessage.snapshot.entries, flatBlobs);
|
|
399
400
|
return new remoteChannelContext_js_1.RemoteChannelContext(this, this.dataStoreContext, this.dataStoreContext.storage, (content, localContentMetadata) => this.submitChannelOp(attachMessage.id, content, localContentMetadata), (address) => this.setChannelDirty(address), (srcHandle, outboundHandle) => this.addedGCOutboundReference(srcHandle, outboundHandle), attachMessage.id, snapshotTree, this.sharedObjectRegistry, flatBlobs, this.dataStoreContext.getCreateChildSummarizerNodeFn(attachMessage.id, summarizerNodeParams), attachMessage.type);
|
|
400
401
|
}
|
|
401
402
|
process(message, local, localOpMetadata) {
|
|
@@ -407,7 +408,7 @@ class FluidDataStoreRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
407
408
|
const attachMessage = message.contents;
|
|
408
409
|
const id = attachMessage.id;
|
|
409
410
|
// We need to process the GC Data for both local and remote attach messages
|
|
410
|
-
(0,
|
|
411
|
+
(0, internal_4.processAttachMessageGCData)(attachMessage.snapshot, (nodeId, toPath) => {
|
|
411
412
|
// Note: nodeId will be "/" unless and until we support sub-DDS GC Nodes
|
|
412
413
|
const fromPath = `/${this.id}/${id}${nodeId === "/" ? "" : nodeId}`;
|
|
413
414
|
this.dataStoreContext.addedGCOutboundRoute?.(fromPath, toPath);
|
|
@@ -415,12 +416,12 @@ class FluidDataStoreRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
415
416
|
// If a non-local operation then go and create the object
|
|
416
417
|
// Otherwise mark it as officially attached.
|
|
417
418
|
if (local) {
|
|
418
|
-
(0,
|
|
419
|
+
(0, internal_1.assert)(this.pendingAttach.delete(id), 0x17c /* "Unexpected attach (local) channel OP" */);
|
|
419
420
|
}
|
|
420
421
|
else {
|
|
421
|
-
(0,
|
|
422
|
+
(0, internal_1.assert)(!this.contexts.has(id), 0x17d /* "Unexpected attach channel OP" */);
|
|
422
423
|
const summarizerNodeParams = {
|
|
423
|
-
type:
|
|
424
|
+
type: internal_3.CreateSummarizerNodeSource.FromAttach,
|
|
424
425
|
sequenceNumber: message.sequenceNumber,
|
|
425
426
|
snapshot: attachMessage.snapshot,
|
|
426
427
|
};
|
|
@@ -437,7 +438,7 @@ class FluidDataStoreRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
437
438
|
this.emit("op", message);
|
|
438
439
|
}
|
|
439
440
|
catch (error) {
|
|
440
|
-
throw
|
|
441
|
+
throw internal_5.DataProcessingError.wrapIfUnrecognized(error, "fluidDataStoreRuntimeFailedToProcessMessage", message);
|
|
441
442
|
}
|
|
442
443
|
}
|
|
443
444
|
processSignal(message, local) {
|
|
@@ -496,7 +497,7 @@ class FluidDataStoreRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
496
497
|
* @param fullGC - true to bypass optimizations and force full generation of GC data.
|
|
497
498
|
*/
|
|
498
499
|
async getGCData(fullGC = false) {
|
|
499
|
-
const builder = new
|
|
500
|
+
const builder = new internal_4.GCDataBuilder();
|
|
500
501
|
// Iterate over each channel context and get their GC data.
|
|
501
502
|
await Promise.all(Array.from(this.contexts)
|
|
502
503
|
.filter(([contextId, _]) => {
|
|
@@ -520,10 +521,10 @@ class FluidDataStoreRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
520
521
|
*/
|
|
521
522
|
updateUsedRoutes(usedRoutes) {
|
|
522
523
|
// Get a map of channel ids to routes used in it.
|
|
523
|
-
const usedContextRoutes = (0,
|
|
524
|
+
const usedContextRoutes = (0, internal_4.unpackChildNodesUsedRoutes)(usedRoutes);
|
|
524
525
|
// Verify that the used routes are correct.
|
|
525
526
|
for (const [id] of usedContextRoutes) {
|
|
526
|
-
(0,
|
|
527
|
+
(0, internal_1.assert)(this.contexts.has(id), 0x17e /* "Used route does not belong to any known context" */);
|
|
527
528
|
}
|
|
528
529
|
// Update the used routes in each context. Used routes is empty for unused context.
|
|
529
530
|
for (const [contextId, context] of this.contexts) {
|
|
@@ -550,13 +551,13 @@ class FluidDataStoreRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
550
551
|
* @param telemetryContext - summary data passed through the layers for telemetry purposes
|
|
551
552
|
*/
|
|
552
553
|
async summarize(fullTree = false, trackState = true, telemetryContext) {
|
|
553
|
-
const summaryBuilder = new
|
|
554
|
+
const summaryBuilder = new internal_4.SummaryTreeBuilder();
|
|
554
555
|
// Iterate over each data store and ask it to summarize
|
|
555
556
|
await Promise.all(Array.from(this.contexts)
|
|
556
557
|
.filter(([contextId, _]) => {
|
|
557
558
|
const isAttached = this.isChannelAttached(contextId);
|
|
558
559
|
// We are not expecting local dds! Summary may not capture local state.
|
|
559
|
-
(0,
|
|
560
|
+
(0, internal_1.assert)(isAttached, 0x17f /* "Not expecting detached channels during summarize" */);
|
|
560
561
|
// If the object is registered - and we have received the sequenced op creating the object
|
|
561
562
|
// (i.e. it has a base mapping) - then we go ahead and summarize
|
|
562
563
|
return isAttached;
|
|
@@ -568,19 +569,19 @@ class FluidDataStoreRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
568
569
|
return summaryBuilder.getSummaryTree();
|
|
569
570
|
}
|
|
570
571
|
getAttachSummary(telemetryContext) {
|
|
571
|
-
const summaryBuilder = new
|
|
572
|
+
const summaryBuilder = new internal_4.SummaryTreeBuilder();
|
|
572
573
|
this.visitLocalBoundContextsDuringAttach((contextId, context) => {
|
|
573
574
|
let summaryTree;
|
|
574
575
|
if (context.isLoaded) {
|
|
575
576
|
const contextSummary = context.getAttachSummary(telemetryContext);
|
|
576
|
-
(0,
|
|
577
|
+
(0, internal_1.assert)(contextSummary.summary.type === protocol_definitions_1.SummaryType.Tree, 0x180 /* "getAttachSummary should always return a tree" */);
|
|
577
578
|
summaryTree = { stats: contextSummary.stats, summary: contextSummary.summary };
|
|
578
579
|
}
|
|
579
580
|
else {
|
|
580
581
|
// If this channel is not yet loaded, then there should be no changes in the snapshot from which
|
|
581
582
|
// it was created as it is detached container. So just use the previous snapshot.
|
|
582
|
-
(0,
|
|
583
|
-
summaryTree = (0,
|
|
583
|
+
(0, internal_1.assert)(!!this.dataStoreContext.baseSnapshot, 0x181 /* "BaseSnapshot should be there as detached container loaded from snapshot" */);
|
|
584
|
+
summaryTree = (0, internal_4.convertSnapshotTreeToSummaryTree)(this.dataStoreContext.baseSnapshot.trees[contextId]);
|
|
584
585
|
}
|
|
585
586
|
summaryBuilder.addWithStats(contextId, summaryTree);
|
|
586
587
|
});
|
|
@@ -590,7 +591,7 @@ class FluidDataStoreRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
590
591
|
* Get the GC Data for the initial state being attached so remote clients can learn of this DataStore's outbound routes
|
|
591
592
|
*/
|
|
592
593
|
getAttachGCData(telemetryContext) {
|
|
593
|
-
const gcDataBuilder = new
|
|
594
|
+
const gcDataBuilder = new internal_4.GCDataBuilder();
|
|
594
595
|
this.visitLocalBoundContextsDuringAttach((contextId, context) => {
|
|
595
596
|
if (context.isLoaded) {
|
|
596
597
|
const contextGCData = context.getAttachGCData(telemetryContext);
|
|
@@ -627,7 +628,7 @@ class FluidDataStoreRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
627
628
|
// );
|
|
628
629
|
for (const [contextId, context] of this.contexts) {
|
|
629
630
|
if (!(context instanceof localChannelContext_js_1.LocalChannelContextBase)) {
|
|
630
|
-
throw new
|
|
631
|
+
throw new internal_5.LoggingError("Should only be called with local channel handles");
|
|
631
632
|
}
|
|
632
633
|
if (!this.notBoundedChannelContextSet.has(contextId)) {
|
|
633
634
|
visitor(contextId, context);
|
|
@@ -640,7 +641,7 @@ class FluidDataStoreRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
640
641
|
/**
|
|
641
642
|
* Submits the signal to be sent to other clients.
|
|
642
643
|
* @param type - Type of the signal.
|
|
643
|
-
* @param content - Content of the signal.
|
|
644
|
+
* @param content - Content of the signal. Should be a JSON serializable object or primitive.
|
|
644
645
|
* @param targetClientId - When specified, the signal is only sent to the provided client id.
|
|
645
646
|
*/
|
|
646
647
|
submitSignal(type, content, targetClientId) {
|
|
@@ -664,14 +665,14 @@ class FluidDataStoreRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
664
665
|
return;
|
|
665
666
|
}
|
|
666
667
|
channel.handle.attachGraph();
|
|
667
|
-
(0,
|
|
668
|
-
(0,
|
|
668
|
+
(0, internal_1.assert)(this.isAttached, 0x182 /* "Data store should be attached to attach the channel." */);
|
|
669
|
+
(0, internal_1.assert)(this.visibilityState === internal_3.VisibilityState.GloballyVisible, 0x2d0 /* "Data store should be globally visible to attach channels." */);
|
|
669
670
|
const summarizeResult = (0, channelContext_js_1.summarizeChannel)(channel, true /* fullTree */, false /* trackState */);
|
|
670
671
|
// We need to include the channel's GC Data so remote clients can learn of this channel's outbound routes
|
|
671
672
|
const gcData = channel.getGCData(/* fullGC: */ true);
|
|
672
|
-
(0,
|
|
673
|
+
(0, internal_4.addBlobToSummary)(summarizeResult, internal_3.gcDataBlobKey, JSON.stringify(gcData));
|
|
673
674
|
// Attach message needs the summary in ITree format. Convert the ISummaryTree into an ITree.
|
|
674
|
-
const snapshot = (0,
|
|
675
|
+
const snapshot = (0, internal_4.convertSummaryTreeToITree)(summarizeResult.summary);
|
|
675
676
|
const message = {
|
|
676
677
|
id: channel.id,
|
|
677
678
|
snapshot,
|
|
@@ -704,7 +705,7 @@ class FluidDataStoreRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
704
705
|
// For Operations, find the right channel and trigger resubmission on it.
|
|
705
706
|
const envelope = content;
|
|
706
707
|
const channelContext = this.contexts.get(envelope.address);
|
|
707
|
-
(0,
|
|
708
|
+
(0, internal_1.assert)(!!channelContext, 0x183 /* "There should be a channel context for the op" */);
|
|
708
709
|
channelContext.reSubmit(envelope.contents, localOpMetadata);
|
|
709
710
|
break;
|
|
710
711
|
}
|
|
@@ -713,7 +714,7 @@ class FluidDataStoreRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
713
714
|
this.submit(type, content, localOpMetadata);
|
|
714
715
|
break;
|
|
715
716
|
default:
|
|
716
|
-
(0,
|
|
717
|
+
(0, internal_1.unreachableCase)(type);
|
|
717
718
|
}
|
|
718
719
|
}
|
|
719
720
|
/**
|
|
@@ -728,12 +729,12 @@ class FluidDataStoreRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
728
729
|
// For Operations, find the right channel and trigger resubmission on it.
|
|
729
730
|
const envelope = content;
|
|
730
731
|
const channelContext = this.contexts.get(envelope.address);
|
|
731
|
-
(0,
|
|
732
|
+
(0, internal_1.assert)(!!channelContext, 0x2ed /* "There should be a channel context for the op" */);
|
|
732
733
|
channelContext.rollback(envelope.contents, localOpMetadata);
|
|
733
734
|
break;
|
|
734
735
|
}
|
|
735
736
|
default:
|
|
736
|
-
throw new
|
|
737
|
+
throw new internal_5.LoggingError(`Can't rollback ${type} message`);
|
|
737
738
|
}
|
|
738
739
|
}
|
|
739
740
|
async applyStashedOp(content) {
|
|
@@ -742,7 +743,7 @@ class FluidDataStoreRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
742
743
|
case DataStoreMessageType.Attach: {
|
|
743
744
|
const attachMessage = content.content;
|
|
744
745
|
const flatBlobs = new Map();
|
|
745
|
-
const snapshotTree = (0,
|
|
746
|
+
const snapshotTree = (0, internal_2.buildSnapshotTree)(attachMessage.snapshot.entries, flatBlobs);
|
|
746
747
|
const channelContext = this.createRehydratedLocalChannelContext(attachMessage.id, snapshotTree, flatBlobs);
|
|
747
748
|
await channelContext.getChannel();
|
|
748
749
|
this.contexts.set(attachMessage.id, channelContext);
|
|
@@ -758,12 +759,12 @@ class FluidDataStoreRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
758
759
|
case DataStoreMessageType.ChannelOp: {
|
|
759
760
|
const envelope = content.content;
|
|
760
761
|
const channelContext = this.contexts.get(envelope.address);
|
|
761
|
-
(0,
|
|
762
|
+
(0, internal_1.assert)(!!channelContext, 0x184 /* "There should be a channel context for the op" */);
|
|
762
763
|
await channelContext.getChannel();
|
|
763
764
|
return channelContext.applyStashedOp(envelope.contents);
|
|
764
765
|
}
|
|
765
766
|
default:
|
|
766
|
-
(0,
|
|
767
|
+
(0, internal_1.unreachableCase)(type);
|
|
767
768
|
}
|
|
768
769
|
}
|
|
769
770
|
setChannelDirty(address) {
|
|
@@ -778,44 +779,26 @@ class FluidDataStoreRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
778
779
|
contents: envelope.contents,
|
|
779
780
|
};
|
|
780
781
|
const channelContext = this.contexts.get(envelope.address);
|
|
781
|
-
(0,
|
|
782
|
+
(0, internal_1.assert)(!!channelContext, 0x185 /* "Channel not found" */);
|
|
782
783
|
channelContext.processOp(transformed, local, localOpMetadata);
|
|
783
784
|
return channelContext;
|
|
784
785
|
}
|
|
785
786
|
attachListener() {
|
|
786
787
|
this.setMaxListeners(Number.MAX_SAFE_INTEGER);
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
* store can move to "attaching" state in 2 scenarios:
|
|
792
|
-
* 1) Before attachGraph() is called - When a data store is created and bound in an attached container.
|
|
793
|
-
* 2) After attachGraph() is called - When a detached container is attached.
|
|
794
|
-
*
|
|
795
|
-
* The basic idea is that all local object should become locally visible before they are globally visible.
|
|
796
|
-
*/
|
|
797
|
-
this.attachGraph();
|
|
798
|
-
this._attachState = container_definitions_1.AttachState.Attaching;
|
|
799
|
-
(0, core_utils_1.assert)(this.visibilityState === runtime_definitions_1.VisibilityState.LocallyVisible, 0x2d1 /* "Data store should be locally visible before it can become globally visible." */);
|
|
800
|
-
// Mark the data store globally visible and make its child channels visible as well.
|
|
801
|
-
this.visibilityState = runtime_definitions_1.VisibilityState.GloballyVisible;
|
|
802
|
-
this.localChannelContextQueue.forEach((channel) => {
|
|
803
|
-
channel.makeVisible();
|
|
804
|
-
});
|
|
805
|
-
this.localChannelContextQueue.clear();
|
|
806
|
-
// This promise resolution will be moved to attached event once we fix the scheduler.
|
|
807
|
-
this.deferredAttached.resolve();
|
|
808
|
-
this.emit("attaching");
|
|
788
|
+
// back-compat, to be removed in the future.
|
|
789
|
+
// Added in "2.0.0-rc.2.0.0" timeframe.
|
|
790
|
+
this.dataStoreContext.once?.("attaching", () => {
|
|
791
|
+
this.setAttachState(container_definitions_1.AttachState.Attaching);
|
|
809
792
|
});
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
this.
|
|
793
|
+
// back-compat, to be removed in the future.
|
|
794
|
+
// Added in "2.0.0-rc.2.0.0" timeframe.
|
|
795
|
+
this.dataStoreContext.once?.("attached", () => {
|
|
796
|
+
this.setAttachState(container_definitions_1.AttachState.Attached);
|
|
814
797
|
});
|
|
815
798
|
}
|
|
816
799
|
verifyNotClosed() {
|
|
817
800
|
if (this._disposed) {
|
|
818
|
-
throw new
|
|
801
|
+
throw new internal_5.LoggingError("Runtime is closed");
|
|
819
802
|
}
|
|
820
803
|
}
|
|
821
804
|
/**
|
|
@@ -832,16 +815,50 @@ class FluidDataStoreRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
832
815
|
// in the summarizer and the data will help us plan this.
|
|
833
816
|
this.mc.logger.sendTelemetryEvent({
|
|
834
817
|
eventName,
|
|
835
|
-
...(0,
|
|
818
|
+
...(0, internal_5.tagCodeArtifacts)({
|
|
836
819
|
channelType,
|
|
837
820
|
channelId,
|
|
838
821
|
fluidDataStoreId: this.id,
|
|
839
822
|
fluidDataStorePackagePath: this.dataStoreContext.packagePath.join("/"),
|
|
840
823
|
}),
|
|
841
|
-
stack: (0,
|
|
824
|
+
stack: (0, internal_5.generateStack)(),
|
|
842
825
|
});
|
|
843
826
|
this.localChangesTelemetryCount--;
|
|
844
827
|
}
|
|
828
|
+
setAttachState(attachState) {
|
|
829
|
+
switch (attachState) {
|
|
830
|
+
case container_definitions_1.AttachState.Attaching:
|
|
831
|
+
/**
|
|
832
|
+
* back-compat 0.59.1000 - Ideally, attachGraph() should have already been called making the data store
|
|
833
|
+
* locally visible. However, before visibility state was added, this may not have been the case and data
|
|
834
|
+
* store can move to "attaching" state in 2 scenarios:
|
|
835
|
+
* 1) Before attachGraph() is called - When a data store is created and bound in an attached container.
|
|
836
|
+
* 2) After attachGraph() is called - When a detached container is attached.
|
|
837
|
+
*
|
|
838
|
+
* The basic idea is that all local object should become locally visible before they are globally visible.
|
|
839
|
+
*/
|
|
840
|
+
this.attachGraph();
|
|
841
|
+
this._attachState = container_definitions_1.AttachState.Attaching;
|
|
842
|
+
(0, internal_1.assert)(this.visibilityState === internal_3.VisibilityState.LocallyVisible, 0x2d1 /* "Data store should be locally visible before it can become globally visible." */);
|
|
843
|
+
// Mark the data store globally visible and make its child channels visible as well.
|
|
844
|
+
this.visibilityState = internal_3.VisibilityState.GloballyVisible;
|
|
845
|
+
this.localChannelContextQueue.forEach((channel) => {
|
|
846
|
+
channel.makeVisible();
|
|
847
|
+
});
|
|
848
|
+
this.localChannelContextQueue.clear();
|
|
849
|
+
// This promise resolution will be moved to attached event once we fix the scheduler.
|
|
850
|
+
this.deferredAttached.resolve();
|
|
851
|
+
this.emit("attaching");
|
|
852
|
+
break;
|
|
853
|
+
case container_definitions_1.AttachState.Attached:
|
|
854
|
+
(0, internal_1.assert)(this.visibilityState === internal_3.VisibilityState.GloballyVisible, 0x2d2 /* "Data store should be globally visible when its attached." */);
|
|
855
|
+
this._attachState = container_definitions_1.AttachState.Attached;
|
|
856
|
+
this.emit("attached");
|
|
857
|
+
break;
|
|
858
|
+
default:
|
|
859
|
+
(0, internal_1.unreachableCase)(attachState, "unreached");
|
|
860
|
+
}
|
|
861
|
+
}
|
|
845
862
|
}
|
|
846
863
|
exports.FluidDataStoreRuntime = FluidDataStoreRuntime;
|
|
847
864
|
/**
|
|
@@ -849,7 +866,7 @@ exports.FluidDataStoreRuntime = FluidDataStoreRuntime;
|
|
|
849
866
|
* Request handler is only called when data store can't resolve request, i.e. for custom requests.
|
|
850
867
|
* @param Base - base class, inherits from FluidDataStoreRuntime
|
|
851
868
|
* @param requestHandler - request handler to mix in
|
|
852
|
-
* @
|
|
869
|
+
* @alpha
|
|
853
870
|
*/
|
|
854
871
|
const mixinRequestHandler = (requestHandler, Base = FluidDataStoreRuntime) => class RuntimeWithRequestHandler extends Base {
|
|
855
872
|
async request(request) {
|
|
@@ -872,7 +889,7 @@ const mixinSummaryHandler = (handler, Base = FluidDataStoreRuntime) => class Run
|
|
|
872
889
|
addBlob(summary, path, content) {
|
|
873
890
|
const firstName = path.shift();
|
|
874
891
|
if (firstName === undefined) {
|
|
875
|
-
throw new
|
|
892
|
+
throw new internal_5.LoggingError("Path can't be empty");
|
|
876
893
|
}
|
|
877
894
|
let blob = {
|
|
878
895
|
type: protocol_definitions_1.SummaryType.Blob,
|
|
@@ -899,7 +916,7 @@ const mixinSummaryHandler = (handler, Base = FluidDataStoreRuntime) => class Run
|
|
|
899
916
|
}
|
|
900
917
|
catch (e) {
|
|
901
918
|
// Any error coming from app-provided handler should be marked as DataProcessingError
|
|
902
|
-
throw
|
|
919
|
+
throw internal_5.DataProcessingError.wrapIfUnrecognized(e, "mixinSummaryHandler");
|
|
903
920
|
}
|
|
904
921
|
return summary;
|
|
905
922
|
}
|