@fluidframework/datastore 2.0.0-dev-rc.1.0.0.228517 → 2.0.0-dev-rc.2.0.0.245554
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/{.eslintrc.js → .eslintrc.cjs} +4 -1
- package/{.mocharc.js → .mocharc.cjs} +1 -1
- package/CHANGELOG.md +42 -0
- package/{api-extractor-esm.json → api-extractor-cjs.json} +5 -1
- package/api-extractor-lint.json +1 -1
- package/api-extractor.json +1 -1
- package/api-report/datastore.api.md +7 -11
- package/dist/channelContext.d.ts +5 -4
- package/dist/channelContext.d.ts.map +1 -1
- package/dist/channelContext.js +6 -5
- package/dist/channelContext.js.map +1 -1
- package/dist/channelDeltaConnection.d.ts +6 -3
- package/dist/channelDeltaConnection.d.ts.map +1 -1
- package/dist/channelDeltaConnection.js +46 -7
- package/dist/channelDeltaConnection.js.map +1 -1
- package/dist/dataStoreRuntime.d.ts +25 -6
- package/dist/dataStoreRuntime.d.ts.map +1 -1
- package/dist/dataStoreRuntime.js +145 -62
- package/dist/dataStoreRuntime.js.map +1 -1
- package/dist/datastore-alpha.d.ts +23 -6
- package/dist/datastore-beta.d.ts +1 -2
- package/dist/datastore-public.d.ts +1 -2
- package/dist/datastore-untrimmed.d.ts +23 -6
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -7
- package/dist/index.js.map +1 -1
- package/dist/localChannelContext.d.ts +18 -3
- package/dist/localChannelContext.d.ts.map +1 -1
- package/dist/localChannelContext.js +32 -10
- package/dist/localChannelContext.js.map +1 -1
- package/dist/package.json +3 -0
- package/dist/remoteChannelContext.d.ts +2 -2
- package/dist/remoteChannelContext.d.ts.map +1 -1
- package/dist/remoteChannelContext.js +6 -5
- package/dist/remoteChannelContext.js.map +1 -1
- package/dist/tsdoc-metadata.json +1 -1
- package/lib/{channelContext.d.mts → channelContext.d.ts} +6 -5
- package/lib/channelContext.d.ts.map +1 -0
- package/lib/{channelContext.mjs → channelContext.js} +6 -5
- package/lib/channelContext.js.map +1 -0
- package/lib/{channelDeltaConnection.d.mts → channelDeltaConnection.d.ts} +7 -4
- package/lib/channelDeltaConnection.d.ts.map +1 -0
- package/lib/channelDeltaConnection.js +92 -0
- package/lib/channelDeltaConnection.js.map +1 -0
- package/lib/{channelStorageService.d.mts → channelStorageService.d.ts} +1 -1
- package/lib/channelStorageService.d.ts.map +1 -0
- package/lib/{channelStorageService.mjs → channelStorageService.js} +1 -1
- package/lib/channelStorageService.js.map +1 -0
- package/lib/{dataStoreRuntime.d.mts → dataStoreRuntime.d.ts} +26 -7
- package/lib/dataStoreRuntime.d.ts.map +1 -0
- package/lib/{dataStoreRuntime.mjs → dataStoreRuntime.js} +142 -59
- package/lib/dataStoreRuntime.js.map +1 -0
- package/lib/{datastore-alpha.d.mts → datastore-alpha.d.ts} +23 -6
- package/lib/{datastore-public.d.mts → datastore-beta.d.ts} +1 -2
- package/lib/{datastore-beta.d.mts → datastore-public.d.ts} +1 -2
- package/lib/{datastore-untrimmed.d.mts → datastore-untrimmed.d.ts} +23 -6
- package/lib/{fluidHandle.d.mts → fluidHandle.d.ts} +1 -1
- package/lib/fluidHandle.d.ts.map +1 -0
- package/lib/{fluidHandle.mjs → fluidHandle.js} +1 -1
- package/lib/fluidHandle.js.map +1 -0
- package/lib/{index.d.mts → index.d.ts} +3 -3
- package/lib/index.d.ts.map +1 -0
- package/lib/{index.mjs → index.js} +3 -3
- package/lib/index.js.map +1 -0
- package/lib/{localChannelContext.d.mts → localChannelContext.d.ts} +19 -4
- package/lib/localChannelContext.d.ts.map +1 -0
- package/lib/{localChannelContext.mjs → localChannelContext.js} +29 -7
- package/lib/localChannelContext.js.map +1 -0
- package/lib/{localChannelStorageService.d.mts → localChannelStorageService.d.ts} +1 -1
- package/lib/localChannelStorageService.d.ts.map +1 -0
- package/lib/{localChannelStorageService.mjs → localChannelStorageService.js} +1 -1
- package/lib/localChannelStorageService.js.map +1 -0
- package/lib/{remoteChannelContext.d.mts → remoteChannelContext.d.ts} +3 -3
- package/lib/remoteChannelContext.d.ts.map +1 -0
- package/lib/{remoteChannelContext.mjs → remoteChannelContext.js} +4 -3
- package/lib/remoteChannelContext.js.map +1 -0
- package/lib/test/channelStorageService.spec.js +70 -0
- package/lib/test/channelStorageService.spec.js.map +1 -0
- package/lib/test/dataStoreRuntime.spec.js +121 -0
- package/lib/test/dataStoreRuntime.spec.js.map +1 -0
- package/lib/test/localChannelContext.spec.js +41 -0
- package/lib/test/localChannelContext.spec.js.map +1 -0
- package/lib/test/localChannelStorageService.spec.js +72 -0
- package/lib/test/localChannelStorageService.spec.js.map +1 -0
- package/lib/test/remoteChannelContext.spec.js +33 -0
- package/lib/test/remoteChannelContext.spec.js.map +1 -0
- package/lib/test/types/validateDatastorePrevious.generated.js +16 -0
- package/lib/test/types/validateDatastorePrevious.generated.js.map +1 -0
- package/package.json +48 -50
- package/src/channelContext.ts +6 -3
- package/src/channelDeltaConnection.ts +69 -5
- package/src/dataStoreRuntime.ts +181 -81
- package/src/index.ts +2 -2
- package/src/localChannelContext.ts +38 -5
- package/src/remoteChannelContext.ts +4 -2
- package/tsconfig.cjs.json +7 -0
- package/tsconfig.json +2 -5
- package/lib/channelContext.d.mts.map +0 -1
- package/lib/channelContext.mjs.map +0 -1
- package/lib/channelDeltaConnection.d.mts.map +0 -1
- package/lib/channelDeltaConnection.mjs +0 -53
- package/lib/channelDeltaConnection.mjs.map +0 -1
- package/lib/channelStorageService.d.mts.map +0 -1
- package/lib/channelStorageService.mjs.map +0 -1
- package/lib/dataStoreRuntime.d.mts.map +0 -1
- package/lib/dataStoreRuntime.mjs.map +0 -1
- package/lib/fluidHandle.d.mts.map +0 -1
- package/lib/fluidHandle.mjs.map +0 -1
- package/lib/index.d.mts.map +0 -1
- package/lib/index.mjs.map +0 -1
- package/lib/localChannelContext.d.mts.map +0 -1
- package/lib/localChannelContext.mjs.map +0 -1
- package/lib/localChannelStorageService.d.mts.map +0 -1
- package/lib/localChannelStorageService.mjs.map +0 -1
- package/lib/remoteChannelContext.d.mts.map +0 -1
- package/lib/remoteChannelContext.mjs.map +0 -1
package/dist/dataStoreRuntime.js
CHANGED
|
@@ -14,10 +14,10 @@ const protocol_definitions_1 = require("@fluidframework/protocol-definitions");
|
|
|
14
14
|
const runtime_definitions_1 = require("@fluidframework/runtime-definitions");
|
|
15
15
|
const runtime_utils_1 = require("@fluidframework/runtime-utils");
|
|
16
16
|
const uuid_1 = require("uuid");
|
|
17
|
-
const
|
|
18
|
-
const
|
|
19
|
-
const
|
|
20
|
-
const
|
|
17
|
+
const channelContext_js_1 = require("./channelContext.js");
|
|
18
|
+
const localChannelContext_js_1 = require("./localChannelContext.js");
|
|
19
|
+
const remoteChannelContext_js_1 = require("./remoteChannelContext.js");
|
|
20
|
+
const fluidHandle_js_1 = require("./fluidHandle.js");
|
|
21
21
|
/**
|
|
22
22
|
* @alpha
|
|
23
23
|
*/
|
|
@@ -138,7 +138,7 @@ class FluidDataStoreRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
138
138
|
// container from snapshot where we load detached container from a snapshot, isLocalDataStore would be
|
|
139
139
|
// true. In this case create a RehydratedLocalChannelContext.
|
|
140
140
|
if (dataStoreContext.isLocalDataStore) {
|
|
141
|
-
channelContext = new
|
|
141
|
+
channelContext = new localChannelContext_js_1.RehydratedLocalChannelContext(path, this.sharedObjectRegistry, this, this.dataStoreContext, this.dataStoreContext.storage, this.logger, (content, localOpMetadata) => this.submitChannelOp(path, content, localOpMetadata), (address) => this.setChannelDirty(address), (srcHandle, outboundHandle) => this.addedGCOutboundReference(srcHandle, outboundHandle), tree.trees[path]);
|
|
142
142
|
// This is the case of rehydrating a detached container from snapshot. Now due to delay loading of
|
|
143
143
|
// data store, if the data store is loaded after the container is attached, then we missed making
|
|
144
144
|
// the channel visible. So do it now. Otherwise, add it to local channel context queue, so
|
|
@@ -151,14 +151,14 @@ class FluidDataStoreRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
151
151
|
}
|
|
152
152
|
}
|
|
153
153
|
else {
|
|
154
|
-
channelContext = new
|
|
154
|
+
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
155
|
type: runtime_definitions_1.CreateSummarizerNodeSource.FromSummary,
|
|
156
156
|
}));
|
|
157
157
|
}
|
|
158
158
|
this.contexts.set(path, channelContext);
|
|
159
159
|
});
|
|
160
160
|
}
|
|
161
|
-
this.entryPoint = new
|
|
161
|
+
this.entryPoint = new fluidHandle_js_1.FluidObjectHandle(new core_utils_1.LazyPromise(async () => provideEntryPoint(this)), "", this.objectsRoutingContext);
|
|
162
162
|
this.attachListener();
|
|
163
163
|
this._attachState = dataStoreContext.attachState;
|
|
164
164
|
/**
|
|
@@ -233,6 +233,20 @@ class FluidDataStoreRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
233
233
|
}
|
|
234
234
|
return context.getChannel();
|
|
235
235
|
}
|
|
236
|
+
/**
|
|
237
|
+
* Validate user provided channel ID
|
|
238
|
+
* Channel ID has limitations. "/" is not allowed as IDs in storage can not have slashes - we parse tree paths and use "/" as separator.
|
|
239
|
+
* IDs cannot start with "_" as it could result in collision of IDs with auto-assigned (by FF) short IDs.
|
|
240
|
+
* @param id - channel ID.
|
|
241
|
+
*/
|
|
242
|
+
validateChannelId(id) {
|
|
243
|
+
if (id.includes("/")) {
|
|
244
|
+
throw new telemetry_utils_1.UsageError(`Id cannot contain slashes: ${id}`);
|
|
245
|
+
}
|
|
246
|
+
if (id.startsWith("_")) {
|
|
247
|
+
throw new telemetry_utils_1.UsageError(`Id cannot start with underscore: ${id}`);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
236
250
|
/**
|
|
237
251
|
* Api which allows caller to create the channel first and then add it to the runtime.
|
|
238
252
|
* The channel type should be present in the registry, otherwise the runtime would reject
|
|
@@ -242,9 +256,7 @@ class FluidDataStoreRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
242
256
|
*/
|
|
243
257
|
addChannel(channel) {
|
|
244
258
|
const id = channel.id;
|
|
245
|
-
|
|
246
|
-
throw new telemetry_utils_1.UsageError(`Id cannot contain slashes: ${id}`);
|
|
247
|
-
}
|
|
259
|
+
this.validateChannelId(id);
|
|
248
260
|
this.verifyNotClosed();
|
|
249
261
|
(0, core_utils_1.assert)(!this.contexts.has(id), 0x865 /* addChannel() with existing ID */);
|
|
250
262
|
const type = channel.attributes.type;
|
|
@@ -256,9 +268,30 @@ class FluidDataStoreRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
256
268
|
// Channels (DDS) should not be created in summarizer client.
|
|
257
269
|
this.identifyLocalChangeInSummarizer("DDSCreatedInSummarizer", id, type);
|
|
258
270
|
}
|
|
259
|
-
createChannel(
|
|
260
|
-
|
|
261
|
-
|
|
271
|
+
createChannel(idArg, type) {
|
|
272
|
+
let id;
|
|
273
|
+
if (idArg !== undefined) {
|
|
274
|
+
id = idArg;
|
|
275
|
+
this.validateChannelId(id);
|
|
276
|
+
}
|
|
277
|
+
else {
|
|
278
|
+
// We use three non-overlapping namespaces:
|
|
279
|
+
// - detached state: even numbers
|
|
280
|
+
// - attached state: odd numbers
|
|
281
|
+
// - uuids
|
|
282
|
+
// In first two cases we will encode result as strings in more compact form, with leading underscore,
|
|
283
|
+
// to ensure no overlap with user-provided DDS names (see validateChannelId())
|
|
284
|
+
if (this.visibilityState !== runtime_definitions_1.VisibilityState.GloballyVisible) {
|
|
285
|
+
// container is detached, only one client observes content, no way to hit collisions with other clients.
|
|
286
|
+
id = (0, runtime_utils_1.encodeCompactIdToString)(2 * this.contexts.size, "_");
|
|
287
|
+
}
|
|
288
|
+
else {
|
|
289
|
+
// Due to back-compat, we could not depend yet on generateDocumentUniqueId() being there.
|
|
290
|
+
// We can remove the need to leverage uuid() as fall-back in couple releases.
|
|
291
|
+
const res = this.dataStoreContext.containerRuntime.generateDocumentUniqueId?.() ?? (0, uuid_1.v4)();
|
|
292
|
+
id = typeof res === "number" ? (0, runtime_utils_1.encodeCompactIdToString)(2 * res + 1, "_") : res;
|
|
293
|
+
}
|
|
294
|
+
(0, core_utils_1.assert)(!id.includes("/"), 0x8fc /* slash */);
|
|
262
295
|
}
|
|
263
296
|
this.verifyNotClosed();
|
|
264
297
|
(0, core_utils_1.assert)(!this.contexts.has(id), 0x179 /* "createChannel() with existing ID" */);
|
|
@@ -275,7 +308,7 @@ class FluidDataStoreRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
275
308
|
}
|
|
276
309
|
createChannelContext(channel) {
|
|
277
310
|
this.notBoundedChannelContextSet.add(channel.id);
|
|
278
|
-
const context = new
|
|
311
|
+
const context = new localChannelContext_js_1.LocalChannelContext(channel, this, this.dataStoreContext, this.dataStoreContext.storage, this.logger, (content, localOpMetadata) => this.submitChannelOp(channel.id, content, localOpMetadata), (address) => this.setChannelDirty(address), (srcHandle, outboundHandle) => this.addedGCOutboundReference(srcHandle, outboundHandle));
|
|
279
312
|
this.contexts.set(channel.id, context);
|
|
280
313
|
}
|
|
281
314
|
/**
|
|
@@ -288,7 +321,7 @@ class FluidDataStoreRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
288
321
|
this.notBoundedChannelContextSet.delete(channel.id);
|
|
289
322
|
// If our data store is attached, then attach the channel.
|
|
290
323
|
if (this.isAttached) {
|
|
291
|
-
this.
|
|
324
|
+
this.makeChannelLocallyVisible(channel);
|
|
292
325
|
return;
|
|
293
326
|
}
|
|
294
327
|
/**
|
|
@@ -360,7 +393,7 @@ class FluidDataStoreRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
360
393
|
createRemoteChannelContext(attachMessage, summarizerNodeParams) {
|
|
361
394
|
const flatBlobs = new Map();
|
|
362
395
|
const snapshotTree = (0, driver_utils_1.buildSnapshotTree)(attachMessage.snapshot.entries, flatBlobs);
|
|
363
|
-
return new
|
|
396
|
+
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);
|
|
364
397
|
}
|
|
365
398
|
process(message, local, localOpMetadata) {
|
|
366
399
|
this.verifyNotClosed();
|
|
@@ -370,6 +403,12 @@ class FluidDataStoreRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
370
403
|
case DataStoreMessageType.Attach: {
|
|
371
404
|
const attachMessage = message.contents;
|
|
372
405
|
const id = attachMessage.id;
|
|
406
|
+
// We need to process the GC Data for both local and remote attach messages
|
|
407
|
+
(0, runtime_utils_1.processAttachMessageGCData)(attachMessage.snapshot, (nodeId, toPath) => {
|
|
408
|
+
// Note: nodeId will be "/" unless and until we support sub-DDS GC Nodes
|
|
409
|
+
const fromPath = `/${this.id}/${id}${nodeId === "/" ? "" : nodeId}`;
|
|
410
|
+
this.dataStoreContext.addedGCOutboundRoute?.(fromPath, toPath);
|
|
411
|
+
});
|
|
373
412
|
// If a non-local operation then go and create the object
|
|
374
413
|
// Otherwise mark it as officially attached.
|
|
375
414
|
if (local) {
|
|
@@ -526,6 +565,45 @@ class FluidDataStoreRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
526
565
|
return summaryBuilder.getSummaryTree();
|
|
527
566
|
}
|
|
528
567
|
getAttachSummary(telemetryContext) {
|
|
568
|
+
const summaryBuilder = new runtime_utils_1.SummaryTreeBuilder();
|
|
569
|
+
this.visitLocalBoundContextsDuringAttach((contextId, context) => {
|
|
570
|
+
let summaryTree;
|
|
571
|
+
if (context.isLoaded) {
|
|
572
|
+
const contextSummary = context.getAttachSummary(telemetryContext);
|
|
573
|
+
(0, core_utils_1.assert)(contextSummary.summary.type === protocol_definitions_1.SummaryType.Tree, 0x180 /* "getAttachSummary should always return a tree" */);
|
|
574
|
+
summaryTree = { stats: contextSummary.stats, summary: contextSummary.summary };
|
|
575
|
+
}
|
|
576
|
+
else {
|
|
577
|
+
// If this channel is not yet loaded, then there should be no changes in the snapshot from which
|
|
578
|
+
// it was created as it is detached container. So just use the previous snapshot.
|
|
579
|
+
(0, core_utils_1.assert)(!!this.dataStoreContext.baseSnapshot, 0x181 /* "BaseSnapshot should be there as detached container loaded from snapshot" */);
|
|
580
|
+
summaryTree = (0, runtime_utils_1.convertSnapshotTreeToSummaryTree)(this.dataStoreContext.baseSnapshot.trees[contextId]);
|
|
581
|
+
}
|
|
582
|
+
summaryBuilder.addWithStats(contextId, summaryTree);
|
|
583
|
+
});
|
|
584
|
+
return summaryBuilder.getSummaryTree();
|
|
585
|
+
}
|
|
586
|
+
/**
|
|
587
|
+
* Get the GC Data for the initial state being attached so remote clients can learn of this DataStore's outbound routes
|
|
588
|
+
*/
|
|
589
|
+
getAttachGCData(telemetryContext) {
|
|
590
|
+
const gcDataBuilder = new runtime_utils_1.GCDataBuilder();
|
|
591
|
+
this.visitLocalBoundContextsDuringAttach((contextId, context) => {
|
|
592
|
+
if (context.isLoaded) {
|
|
593
|
+
const contextGCData = context.getAttachGCData(telemetryContext);
|
|
594
|
+
// Incorporate the GC Data for this context
|
|
595
|
+
gcDataBuilder.prefixAndAddNodes(contextId, contextGCData.gcNodes);
|
|
596
|
+
}
|
|
597
|
+
// else: Rehydrating detached container case. GC doesn't run until the container is attached, so nothing to do here.
|
|
598
|
+
});
|
|
599
|
+
this.updateGCNodes(gcDataBuilder);
|
|
600
|
+
return gcDataBuilder.getGCData();
|
|
601
|
+
}
|
|
602
|
+
/**
|
|
603
|
+
* Helper method for preparing to attach this dataStore.
|
|
604
|
+
* Runs the callback for each bound context to incorporate its data however the caller specifies
|
|
605
|
+
*/
|
|
606
|
+
visitLocalBoundContextsDuringAttach(visitor) {
|
|
529
607
|
/**
|
|
530
608
|
* back-compat 0.59.1000 - getAttachSummary() is called when making a data store globally visible (previously
|
|
531
609
|
* attaching state). Ideally, attachGraph() should have already be called making it locally visible. However,
|
|
@@ -544,29 +622,14 @@ class FluidDataStoreRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
544
622
|
// assert(this.visibilityState === VisibilityState.LocallyVisible,
|
|
545
623
|
// "The data store should be locally visible when generating attach summary",
|
|
546
624
|
// );
|
|
547
|
-
const summaryBuilder = new runtime_utils_1.SummaryTreeBuilder();
|
|
548
|
-
// Craft the .attributes file for each shared object
|
|
549
625
|
for (const [contextId, context] of this.contexts) {
|
|
550
|
-
if (!(context instanceof
|
|
626
|
+
if (!(context instanceof localChannelContext_js_1.LocalChannelContextBase)) {
|
|
551
627
|
throw new telemetry_utils_1.LoggingError("Should only be called with local channel handles");
|
|
552
628
|
}
|
|
553
629
|
if (!this.notBoundedChannelContextSet.has(contextId)) {
|
|
554
|
-
|
|
555
|
-
if (context.isLoaded) {
|
|
556
|
-
const contextSummary = context.getAttachSummary(telemetryContext);
|
|
557
|
-
(0, core_utils_1.assert)(contextSummary.summary.type === protocol_definitions_1.SummaryType.Tree, 0x180 /* "getAttachSummary should always return a tree" */);
|
|
558
|
-
summaryTree = { stats: contextSummary.stats, summary: contextSummary.summary };
|
|
559
|
-
}
|
|
560
|
-
else {
|
|
561
|
-
// If this channel is not yet loaded, then there should be no changes in the snapshot from which
|
|
562
|
-
// it was created as it is detached container. So just use the previous snapshot.
|
|
563
|
-
(0, core_utils_1.assert)(!!this.dataStoreContext.baseSnapshot, 0x181 /* "BaseSnapshot should be there as detached container loaded from snapshot" */);
|
|
564
|
-
summaryTree = (0, runtime_utils_1.convertSnapshotTreeToSummaryTree)(this.dataStoreContext.baseSnapshot.trees[contextId]);
|
|
565
|
-
}
|
|
566
|
-
summaryBuilder.addWithStats(contextId, summaryTree);
|
|
630
|
+
visitor(contextId, context);
|
|
567
631
|
}
|
|
568
632
|
}
|
|
569
|
-
return summaryBuilder.getSummaryTree();
|
|
570
633
|
}
|
|
571
634
|
submitMessage(type, content, localOpMetadata) {
|
|
572
635
|
this.submit(type, content, localOpMetadata);
|
|
@@ -588,9 +651,10 @@ class FluidDataStoreRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
588
651
|
return this.deferredAttached.promise;
|
|
589
652
|
}
|
|
590
653
|
/**
|
|
591
|
-
*
|
|
654
|
+
* Assuming this DataStore is already attached, this will make the given channel locally visible
|
|
655
|
+
* by submitting its attach op.
|
|
592
656
|
*/
|
|
593
|
-
|
|
657
|
+
makeChannelLocallyVisible(channel) {
|
|
594
658
|
this.verifyNotClosed();
|
|
595
659
|
// If this handle is already attached no need to attach again.
|
|
596
660
|
if (channel.handle.isAttached) {
|
|
@@ -599,7 +663,10 @@ class FluidDataStoreRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
599
663
|
channel.handle.attachGraph();
|
|
600
664
|
(0, core_utils_1.assert)(this.isAttached, 0x182 /* "Data store should be attached to attach the channel." */);
|
|
601
665
|
(0, core_utils_1.assert)(this.visibilityState === runtime_definitions_1.VisibilityState.GloballyVisible, 0x2d0 /* "Data store should be globally visible to attach channels." */);
|
|
602
|
-
const summarizeResult = (0,
|
|
666
|
+
const summarizeResult = (0, channelContext_js_1.summarizeChannel)(channel, true /* fullTree */, false /* trackState */);
|
|
667
|
+
// We need to include the channel's GC Data so remote clients can learn of this channel's outbound routes
|
|
668
|
+
const gcData = channel.getGCData(/* fullGC: */ true);
|
|
669
|
+
(0, runtime_utils_1.addBlobToSummary)(summarizeResult, runtime_definitions_1.gcDataBlobKey, JSON.stringify(gcData));
|
|
603
670
|
// Attach message needs the summary in ITree format. Convert the ISummaryTree into an ITree.
|
|
604
671
|
const snapshot = (0, runtime_utils_1.convertSummaryTreeToITree)(summarizeResult.summary);
|
|
605
672
|
const message = {
|
|
@@ -709,33 +776,15 @@ class FluidDataStoreRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
709
776
|
}
|
|
710
777
|
attachListener() {
|
|
711
778
|
this.setMaxListeners(Number.MAX_SAFE_INTEGER);
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
* store can move to "attaching" state in 2 scenarios:
|
|
717
|
-
* 1) Before attachGraph() is called - When a data store is created and bound in an attached container.
|
|
718
|
-
* 2) After attachGraph() is called - When a detached container is attached.
|
|
719
|
-
*
|
|
720
|
-
* The basic idea is that all local object should become locally visible before they are globally visible.
|
|
721
|
-
*/
|
|
722
|
-
this.attachGraph();
|
|
723
|
-
this._attachState = container_definitions_1.AttachState.Attaching;
|
|
724
|
-
(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." */);
|
|
725
|
-
// Mark the data store globally visible and make its child channels visible as well.
|
|
726
|
-
this.visibilityState = runtime_definitions_1.VisibilityState.GloballyVisible;
|
|
727
|
-
this.localChannelContextQueue.forEach((channel) => {
|
|
728
|
-
channel.makeVisible();
|
|
729
|
-
});
|
|
730
|
-
this.localChannelContextQueue.clear();
|
|
731
|
-
// This promise resolution will be moved to attached event once we fix the scheduler.
|
|
732
|
-
this.deferredAttached.resolve();
|
|
733
|
-
this.emit("attaching");
|
|
779
|
+
// back-compat, to be removed in the future.
|
|
780
|
+
// Added in "2.0.0-rc.2.0.0" timeframe.
|
|
781
|
+
this.dataStoreContext.once?.("attaching", () => {
|
|
782
|
+
this.setAttachState(container_definitions_1.AttachState.Attaching);
|
|
734
783
|
});
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
this.
|
|
784
|
+
// back-compat, to be removed in the future.
|
|
785
|
+
// Added in "2.0.0-rc.2.0.0" timeframe.
|
|
786
|
+
this.dataStoreContext.once?.("attached", () => {
|
|
787
|
+
this.setAttachState(container_definitions_1.AttachState.Attached);
|
|
739
788
|
});
|
|
740
789
|
}
|
|
741
790
|
verifyNotClosed() {
|
|
@@ -767,6 +816,40 @@ class FluidDataStoreRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
767
816
|
});
|
|
768
817
|
this.localChangesTelemetryCount--;
|
|
769
818
|
}
|
|
819
|
+
setAttachState(attachState) {
|
|
820
|
+
switch (attachState) {
|
|
821
|
+
case container_definitions_1.AttachState.Attaching:
|
|
822
|
+
/**
|
|
823
|
+
* back-compat 0.59.1000 - Ideally, attachGraph() should have already been called making the data store
|
|
824
|
+
* locally visible. However, before visibility state was added, this may not have been the case and data
|
|
825
|
+
* store can move to "attaching" state in 2 scenarios:
|
|
826
|
+
* 1) Before attachGraph() is called - When a data store is created and bound in an attached container.
|
|
827
|
+
* 2) After attachGraph() is called - When a detached container is attached.
|
|
828
|
+
*
|
|
829
|
+
* The basic idea is that all local object should become locally visible before they are globally visible.
|
|
830
|
+
*/
|
|
831
|
+
this.attachGraph();
|
|
832
|
+
this._attachState = container_definitions_1.AttachState.Attaching;
|
|
833
|
+
(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." */);
|
|
834
|
+
// Mark the data store globally visible and make its child channels visible as well.
|
|
835
|
+
this.visibilityState = runtime_definitions_1.VisibilityState.GloballyVisible;
|
|
836
|
+
this.localChannelContextQueue.forEach((channel) => {
|
|
837
|
+
channel.makeVisible();
|
|
838
|
+
});
|
|
839
|
+
this.localChannelContextQueue.clear();
|
|
840
|
+
// This promise resolution will be moved to attached event once we fix the scheduler.
|
|
841
|
+
this.deferredAttached.resolve();
|
|
842
|
+
this.emit("attaching");
|
|
843
|
+
break;
|
|
844
|
+
case container_definitions_1.AttachState.Attached:
|
|
845
|
+
(0, core_utils_1.assert)(this.visibilityState === runtime_definitions_1.VisibilityState.GloballyVisible, 0x2d2 /* "Data store should be globally visible when its attached." */);
|
|
846
|
+
this._attachState = container_definitions_1.AttachState.Attached;
|
|
847
|
+
this.emit("attached");
|
|
848
|
+
break;
|
|
849
|
+
default:
|
|
850
|
+
(0, core_utils_1.unreachableCase)(attachState, "unreached");
|
|
851
|
+
}
|
|
852
|
+
}
|
|
770
853
|
}
|
|
771
854
|
exports.FluidDataStoreRuntime = FluidDataStoreRuntime;
|
|
772
855
|
/**
|