@fluidframework/datastore 2.0.0-internal.3.0.2 → 2.0.0-internal.3.2.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.
Files changed (67) hide show
  1. package/.eslintrc.js +5 -7
  2. package/.mocharc.js +2 -2
  3. package/README.md +3 -0
  4. package/api-extractor.json +2 -2
  5. package/dist/channelContext.d.ts.map +1 -1
  6. package/dist/channelContext.js.map +1 -1
  7. package/dist/channelDeltaConnection.d.ts.map +1 -1
  8. package/dist/channelDeltaConnection.js.map +1 -1
  9. package/dist/channelStorageService.d.ts.map +1 -1
  10. package/dist/channelStorageService.js +1 -3
  11. package/dist/channelStorageService.js.map +1 -1
  12. package/dist/dataStoreRuntime.d.ts +10 -18
  13. package/dist/dataStoreRuntime.d.ts.map +1 -1
  14. package/dist/dataStoreRuntime.js +65 -83
  15. package/dist/dataStoreRuntime.js.map +1 -1
  16. package/dist/fluidHandle.d.ts.map +1 -1
  17. package/dist/fluidHandle.js.map +1 -1
  18. package/dist/localChannelContext.d.ts.map +1 -1
  19. package/dist/localChannelContext.js +9 -5
  20. package/dist/localChannelContext.js.map +1 -1
  21. package/dist/localChannelStorageService.d.ts.map +1 -1
  22. package/dist/localChannelStorageService.js.map +1 -1
  23. package/dist/packageVersion.d.ts +1 -1
  24. package/dist/packageVersion.js +1 -1
  25. package/dist/packageVersion.js.map +1 -1
  26. package/dist/remoteChannelContext.d.ts +2 -2
  27. package/dist/remoteChannelContext.d.ts.map +1 -1
  28. package/dist/remoteChannelContext.js +4 -4
  29. package/dist/remoteChannelContext.js.map +1 -1
  30. package/lib/channelContext.d.ts.map +1 -1
  31. package/lib/channelContext.js.map +1 -1
  32. package/lib/channelDeltaConnection.d.ts.map +1 -1
  33. package/lib/channelDeltaConnection.js.map +1 -1
  34. package/lib/channelStorageService.d.ts.map +1 -1
  35. package/lib/channelStorageService.js +1 -3
  36. package/lib/channelStorageService.js.map +1 -1
  37. package/lib/dataStoreRuntime.d.ts +10 -18
  38. package/lib/dataStoreRuntime.d.ts.map +1 -1
  39. package/lib/dataStoreRuntime.js +68 -86
  40. package/lib/dataStoreRuntime.js.map +1 -1
  41. package/lib/fluidHandle.d.ts.map +1 -1
  42. package/lib/fluidHandle.js.map +1 -1
  43. package/lib/localChannelContext.d.ts.map +1 -1
  44. package/lib/localChannelContext.js +9 -5
  45. package/lib/localChannelContext.js.map +1 -1
  46. package/lib/localChannelStorageService.d.ts.map +1 -1
  47. package/lib/localChannelStorageService.js.map +1 -1
  48. package/lib/packageVersion.d.ts +1 -1
  49. package/lib/packageVersion.js +1 -1
  50. package/lib/packageVersion.js.map +1 -1
  51. package/lib/remoteChannelContext.d.ts +2 -2
  52. package/lib/remoteChannelContext.d.ts.map +1 -1
  53. package/lib/remoteChannelContext.js +4 -4
  54. package/lib/remoteChannelContext.js.map +1 -1
  55. package/package.json +50 -49
  56. package/prettier.config.cjs +1 -1
  57. package/src/channelContext.ts +66 -65
  58. package/src/channelDeltaConnection.ts +50 -44
  59. package/src/channelStorageService.ts +58 -54
  60. package/src/dataStoreRuntime.ts +1131 -1087
  61. package/src/fluidHandle.ts +87 -91
  62. package/src/localChannelContext.ts +302 -255
  63. package/src/localChannelStorageService.ts +47 -45
  64. package/src/packageVersion.ts +1 -1
  65. package/src/remoteChannelContext.ts +297 -291
  66. package/tsconfig.esnext.json +6 -6
  67. package/tsconfig.json +9 -13
@@ -8,12 +8,12 @@ import { assert, Deferred, LazyPromise, TypedEventEmitter, unreachableCase, } fr
8
8
  import { ChildLogger, generateStack, LoggingError, loggerToMonitoringContext, raiseConnectedEvent, TelemetryDataTag, } from "@fluidframework/telemetry-utils";
9
9
  import { buildSnapshotTree } from "@fluidframework/driver-utils";
10
10
  import { SummaryType, } from "@fluidframework/protocol-definitions";
11
- import { BindState, CreateSummarizerNodeSource, VisibilityState, } from "@fluidframework/runtime-definitions";
11
+ import { CreateSummarizerNodeSource, VisibilityState, } from "@fluidframework/runtime-definitions";
12
12
  import { convertSnapshotTreeToSummaryTree, convertSummaryTreeToITree, generateHandleContextPath, RequestParser, SummaryTreeBuilder, create404Response, createResponseError, exceptionToResponse, requestFluidObject, packagePathToTelemetryProperty, } from "@fluidframework/runtime-utils";
13
- import { GCDataBuilder, removeRouteFromAllNodes, unpackChildNodesGCDetails, unpackChildNodesUsedRoutes, } from "@fluidframework/garbage-collector";
13
+ import { GCDataBuilder, unpackChildNodesUsedRoutes } from "@fluidframework/garbage-collector";
14
14
  import { v4 as uuid } from "uuid";
15
15
  import { summarizeChannel } from "./channelContext";
16
- import { LocalChannelContext, LocalChannelContextBase, RehydratedLocalChannelContext } from "./localChannelContext";
16
+ import { LocalChannelContext, LocalChannelContextBase, RehydratedLocalChannelContext, } from "./localChannelContext";
17
17
  import { RemoteChannelContext } from "./remoteChannelContext";
18
18
  import { FluidObjectHandle } from "./fluidHandle";
19
19
  export var DataStoreMessageType;
@@ -27,16 +27,16 @@ export var DataStoreMessageType;
27
27
  */
28
28
  export class FluidDataStoreRuntime extends TypedEventEmitter {
29
29
  /**
30
- * Create an instance of a DataStore runtime.
31
- *
32
- * @param dataStoreContext - Context object for the runtime.
33
- * @param sharedObjectRegistry - The registry of shared objects that this data store will be able to instantiate.
34
- * @param existing - Pass 'true' if loading this datastore from an existing file; pass 'false' otherwise.
35
- * @param initializeEntryPoint - Function to initialize the entryPoint object for the data store runtime. The
36
- * handle to this data store runtime will point to the object returned by this function. If this function is not
37
- * provided, the handle will be left undefined. This is here so we can start making handles a first-class citizen
38
- * and the primary way of interacting with some Fluid objects, and should be used if possible.
39
- */
30
+ * Create an instance of a DataStore runtime.
31
+ *
32
+ * @param dataStoreContext - Context object for the runtime.
33
+ * @param sharedObjectRegistry - The registry of shared objects that this data store will be able to instantiate.
34
+ * @param existing - Pass 'true' if loading this datastore from an existing file; pass 'false' otherwise.
35
+ * @param initializeEntryPoint - Function to initialize the entryPoint object for the data store runtime. The
36
+ * handle to this data store runtime will point to the object returned by this function. If this function is not
37
+ * provided, the handle will be left undefined. This is here so we can start making handles a first-class citizen
38
+ * and the primary way of interacting with some Fluid objects, and should be used if possible.
39
+ */
40
40
  constructor(dataStoreContext, sharedObjectRegistry, existing, initializeEntryPoint) {
41
41
  var _a;
42
42
  super();
@@ -62,10 +62,6 @@ export class FluidDataStoreRuntime extends TypedEventEmitter {
62
62
  this.quorum = dataStoreContext.getQuorum();
63
63
  this.audience = dataStoreContext.getAudience();
64
64
  const tree = dataStoreContext.baseSnapshot;
65
- this.channelsBaseGCDetails = new LazyPromise(async () => {
66
- const baseGCDetails = await this.dataStoreContext.getBaseGCDetails();
67
- return unpackChildNodesGCDetails(baseGCDetails);
68
- });
69
65
  // Must always receive the data store type inside of the attributes
70
66
  if ((tree === null || tree === void 0 ? void 0 : tree.trees) !== undefined) {
71
67
  Object.keys(tree.trees).forEach((path) => {
@@ -91,7 +87,9 @@ export class FluidDataStoreRuntime extends TypedEventEmitter {
91
87
  }
92
88
  }
93
89
  else {
94
- channelContext = new 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, { type: CreateSummarizerNodeSource.FromSummary }), async () => this.getChannelBaseGCDetails(path));
90
+ channelContext = new 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, {
91
+ type: CreateSummarizerNodeSource.FromSummary,
92
+ }));
95
93
  }
96
94
  const deferred = new Deferred();
97
95
  deferred.resolve(channelContext);
@@ -104,8 +102,6 @@ export class FluidDataStoreRuntime extends TypedEventEmitter {
104
102
  this.entryPoint = new FluidObjectHandle(promise, "", this.objectsRoutingContext);
105
103
  }
106
104
  this.attachListener();
107
- // If exists on storage or loaded from a snapshot, it should already be bound.
108
- this.bindState = existing ? BindState.Bound : BindState.NotBound;
109
105
  this._attachState = dataStoreContext.attachState;
110
106
  /**
111
107
  * If existing flag is false, this is a new data store and is not visible. The existing flag can be true in two
@@ -118,8 +114,10 @@ export class FluidDataStoreRuntime extends TypedEventEmitter {
118
114
  * when an attach op comes in. In both these cases, the data store is already globally visible.
119
115
  */
120
116
  if (existing) {
121
- this.visibilityState = dataStoreContext.attachState === AttachState.Detached
122
- ? VisibilityState.LocallyVisible : VisibilityState.GloballyVisible;
117
+ this.visibilityState =
118
+ dataStoreContext.attachState === AttachState.Detached
119
+ ? VisibilityState.LocallyVisible
120
+ : VisibilityState.GloballyVisible;
123
121
  }
124
122
  else {
125
123
  this.visibilityState = VisibilityState.NotVisible;
@@ -143,7 +141,9 @@ export class FluidDataStoreRuntime extends TypedEventEmitter {
143
141
  static load(context, sharedObjectRegistry, existing) {
144
142
  return new FluidDataStoreRuntime(context, sharedObjectRegistry, existing, async (dataStoreRuntime) => requestFluidObject(dataStoreRuntime, "/"));
145
143
  }
146
- get IFluidRouter() { return this; }
144
+ get IFluidRouter() {
145
+ return this;
146
+ }
147
147
  get connected() {
148
148
  return this.dataStoreContext.connected;
149
149
  }
@@ -165,11 +165,21 @@ export class FluidDataStoreRuntime extends TypedEventEmitter {
165
165
  get routeContext() {
166
166
  return this.dataStoreContext.IFluidHandleContext;
167
167
  }
168
- get IFluidHandleContext() { return this; }
169
- get rootRoutingContext() { return this; }
170
- get channelsRoutingContext() { return this; }
171
- get objectsRoutingContext() { return this; }
172
- get disposed() { return this._disposed; }
168
+ get IFluidHandleContext() {
169
+ return this;
170
+ }
171
+ get rootRoutingContext() {
172
+ return this;
173
+ }
174
+ get channelsRoutingContext() {
175
+ return this;
176
+ }
177
+ get objectsRoutingContext() {
178
+ return this;
179
+ }
180
+ get disposed() {
181
+ return this._disposed;
182
+ }
173
183
  get logger() {
174
184
  return this.mc.logger;
175
185
  }
@@ -183,9 +193,9 @@ export class FluidDataStoreRuntime extends TypedEventEmitter {
183
193
  */
184
194
  ensureNoDataModelChanges(callback) {
185
195
  // back-compat ADO:2309
186
- return this.dataStoreContext.ensureNoDataModelChanges === undefined ?
187
- callback() :
188
- this.dataStoreContext.ensureNoDataModelChanges(callback);
196
+ return this.dataStoreContext.ensureNoDataModelChanges === undefined
197
+ ? callback()
198
+ : this.dataStoreContext.ensureNoDataModelChanges(callback);
189
199
  }
190
200
  dispose() {
191
201
  if (this._disposed) {
@@ -307,7 +317,7 @@ export class FluidDataStoreRuntime extends TypedEventEmitter {
307
317
  handle.attachGraph();
308
318
  });
309
319
  this.pendingHandlesToMakeVisible.clear();
310
- this.bindToContext();
320
+ this.dataStoreContext.makeLocallyVisible();
311
321
  }
312
322
  /**
313
323
  * This function is called when a handle to this data store is added to a visible DDS.
@@ -323,12 +333,7 @@ export class FluidDataStoreRuntime extends TypedEventEmitter {
323
333
  * 2. Attaching the graph if the data store becomes attached.
324
334
  */
325
335
  bindToContext() {
326
- if (this.bindState !== BindState.NotBound) {
327
- return;
328
- }
329
- this.bindState = BindState.Binding;
330
- this.dataStoreContext.bindToContext();
331
- this.bindState = BindState.Bound;
336
+ this.makeVisibleAndAttachGraph();
332
337
  }
333
338
  bind(handle) {
334
339
  // If visible, attach the incoming handle's graph. Else, this will be done when we become visible.
@@ -370,14 +375,14 @@ export class FluidDataStoreRuntime extends TypedEventEmitter {
370
375
  this.pendingAttach.delete(id);
371
376
  }
372
377
  else {
373
- assert(!this.contexts.has(id), 0x17d);
378
+ assert(!this.contexts.has(id), 0x17d /* "Unexpected attach channel OP" */);
374
379
  const flatBlobs = new Map();
375
380
  const snapshotTree = buildSnapshotTree(attachMessage.snapshot.entries, flatBlobs);
376
381
  const remoteChannelContext = new RemoteChannelContext(this, this.dataStoreContext, this.dataStoreContext.storage, (content, localContentMetadata) => this.submitChannelOp(id, content, localContentMetadata), (address) => this.setChannelDirty(address), (srcHandle, outboundHandle) => this.addedGCOutboundReference(srcHandle, outboundHandle), id, snapshotTree, this.sharedObjectRegistry, flatBlobs, this.dataStoreContext.getCreateChildSummarizerNodeFn(id, {
377
382
  type: CreateSummarizerNodeSource.FromAttach,
378
383
  sequenceNumber: message.sequenceNumber,
379
384
  snapshot: attachMessage.snapshot,
380
- }), async () => this.getChannelBaseGCDetails(id), attachMessage.type);
385
+ }), attachMessage.type);
381
386
  this.contexts.set(id, remoteChannelContext);
382
387
  if (this.contextsDeferred.has(id)) {
383
388
  // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
@@ -409,13 +414,13 @@ export class FluidDataStoreRuntime extends TypedEventEmitter {
409
414
  return (
410
415
  // Added in createChannel
411
416
  // Removed when bindChannel is called
412
- !this.notBoundedChannelContextSet.has(id)
417
+ !this.notBoundedChannelContextSet.has(id) &&
413
418
  // Added in bindChannel only if this is not attached yet
414
419
  // Removed when this is attached by calling attachGraph
415
- && !this.localChannelContextQueue.has(id)
420
+ !this.localChannelContextQueue.has(id) &&
416
421
  // Added in attachChannel called by bindChannel
417
422
  // Removed when attach op is broadcast
418
- && !this.pendingAttach.has(id));
423
+ !this.pendingAttach.has(id));
419
424
  }
420
425
  /**
421
426
  * Returns the outbound routes of this channel. Currently, all contexts in this channel are considered
@@ -465,7 +470,8 @@ export class FluidDataStoreRuntime extends TypedEventEmitter {
465
470
  // Get GC data only for attached contexts. Detached contexts are not connected in the GC reference
466
471
  // graph so any references they might have won't be connected as well.
467
472
  return this.isChannelAttached(contextId);
468
- }).map(async ([contextId, context]) => {
473
+ })
474
+ .map(async ([contextId, context]) => {
469
475
  const contextGCData = await context.getGCData(fullGC);
470
476
  // Prefix the child's id to the ids of its GC nodes so they can be identified as belonging to the child.
471
477
  // This also gradually builds the id of each node to be a path from the root.
@@ -502,29 +508,6 @@ export class FluidDataStoreRuntime extends TypedEventEmitter {
502
508
  var _a, _b;
503
509
  (_b = (_a = this.dataStoreContext).addedGCOutboundReference) === null || _b === void 0 ? void 0 : _b.call(_a, srcHandle, outboundHandle);
504
510
  }
505
- /**
506
- * Returns the base GC details for the channel with the given id. This is used to initialize its GC state.
507
- * @param channelId - The id of the channel context that is asked for the initial GC details.
508
- * @returns the requested channel's base GC details.
509
- */
510
- async getChannelBaseGCDetails(channelId) {
511
- var _a;
512
- let channelBaseGCDetails = (await this.channelsBaseGCDetails).get(channelId);
513
- if (channelBaseGCDetails === undefined) {
514
- channelBaseGCDetails = {};
515
- }
516
- else if (((_a = channelBaseGCDetails.gcData) === null || _a === void 0 ? void 0 : _a.gcNodes) !== undefined) {
517
- // Note: if the child channel has an explicit handle route to its parent, it will be removed here and
518
- // expected to be added back by the parent when getGCData is called.
519
- removeRouteFromAllNodes(channelBaseGCDetails.gcData.gcNodes, this.absolutePath);
520
- }
521
- // Currently, channel context's are always considered used. So, it there are no used routes for it, we still
522
- // need to mark it as used. Add self-route (empty string) to the channel context's used routes.
523
- if (channelBaseGCDetails.usedRoutes === undefined || channelBaseGCDetails.usedRoutes.length === 0) {
524
- channelBaseGCDetails.usedRoutes = [""];
525
- }
526
- return channelBaseGCDetails;
527
- }
528
511
  /**
529
512
  * Returns a summary at the current sequence number.
530
513
  * @param fullTree - true to bypass optimizations and force a full summary tree
@@ -542,7 +525,8 @@ export class FluidDataStoreRuntime extends TypedEventEmitter {
542
525
  // If the object is registered - and we have received the sequenced op creating the object
543
526
  // (i.e. it has a base mapping) - then we go ahead and summarize
544
527
  return isAttached;
545
- }).map(async ([contextId, context]) => {
528
+ })
529
+ .map(async ([contextId, context]) => {
546
530
  const contextSummary = await context.summarize(fullTree, trackState, telemetryContext);
547
531
  summaryBuilder.addWithStats(contextId, contextSummary);
548
532
  }));
@@ -647,15 +631,14 @@ export class FluidDataStoreRuntime extends TypedEventEmitter {
647
631
  reSubmit(type, content, localOpMetadata) {
648
632
  this.verifyNotClosed();
649
633
  switch (type) {
650
- case DataStoreMessageType.ChannelOp:
651
- {
652
- // For Operations, find the right channel and trigger resubmission on it.
653
- const envelope = content;
654
- const channelContext = this.contexts.get(envelope.address);
655
- assert(!!channelContext, 0x183 /* "There should be a channel context for the op" */);
656
- channelContext.reSubmit(envelope.contents, localOpMetadata);
657
- break;
658
- }
634
+ case DataStoreMessageType.ChannelOp: {
635
+ // For Operations, find the right channel and trigger resubmission on it.
636
+ const envelope = content;
637
+ const channelContext = this.contexts.get(envelope.address);
638
+ assert(!!channelContext, 0x183 /* "There should be a channel context for the op" */);
639
+ channelContext.reSubmit(envelope.contents, localOpMetadata);
640
+ break;
641
+ }
659
642
  case DataStoreMessageType.Attach:
660
643
  // For Attach messages, just submit them again.
661
644
  this.submit(type, content, localOpMetadata);
@@ -672,15 +655,14 @@ export class FluidDataStoreRuntime extends TypedEventEmitter {
672
655
  rollback(type, content, localOpMetadata) {
673
656
  this.verifyNotClosed();
674
657
  switch (type) {
675
- case DataStoreMessageType.ChannelOp:
676
- {
677
- // For Operations, find the right channel and trigger resubmission on it.
678
- const envelope = content;
679
- const channelContext = this.contexts.get(envelope.address);
680
- assert(!!channelContext, 0x2ed /* "There should be a channel context for the op" */);
681
- channelContext.rollback(envelope.contents, localOpMetadata);
682
- break;
683
- }
658
+ case DataStoreMessageType.ChannelOp: {
659
+ // For Operations, find the right channel and trigger resubmission on it.
660
+ const envelope = content;
661
+ const channelContext = this.contexts.get(envelope.address);
662
+ assert(!!channelContext, 0x2ed /* "There should be a channel context for the op" */);
663
+ channelContext.rollback(envelope.contents, localOpMetadata);
664
+ break;
665
+ }
684
666
  default:
685
667
  throw new LoggingError(`Can't rollback ${type} message`);
686
668
  }