@fluidframework/datastore 2.0.0-dev.5.3.2.178189 → 2.0.0-dev.6.4.0.191258

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 (49) hide show
  1. package/CHANGELOG.md +89 -0
  2. package/README.md +4 -3
  3. package/dist/channelContext.d.ts.map +1 -1
  4. package/dist/channelContext.js +15 -33
  5. package/dist/channelContext.js.map +1 -1
  6. package/dist/channelDeltaConnection.js +5 -5
  7. package/dist/channelDeltaConnection.js.map +1 -1
  8. package/dist/channelStorageService.js +1 -2
  9. package/dist/channelStorageService.js.map +1 -1
  10. package/dist/dataStoreRuntime.d.ts +9 -3
  11. package/dist/dataStoreRuntime.d.ts.map +1 -1
  12. package/dist/dataStoreRuntime.js +91 -93
  13. package/dist/dataStoreRuntime.js.map +1 -1
  14. package/dist/localChannelContext.d.ts +1 -1
  15. package/dist/localChannelContext.d.ts.map +1 -1
  16. package/dist/localChannelContext.js +12 -13
  17. package/dist/localChannelContext.js.map +1 -1
  18. package/dist/localChannelStorageService.js +2 -2
  19. package/dist/localChannelStorageService.js.map +1 -1
  20. package/dist/remoteChannelContext.d.ts.map +1 -1
  21. package/dist/remoteChannelContext.js +12 -10
  22. package/dist/remoteChannelContext.js.map +1 -1
  23. package/lib/channelContext.d.ts.map +1 -1
  24. package/lib/channelContext.js +16 -34
  25. package/lib/channelContext.js.map +1 -1
  26. package/lib/channelDeltaConnection.js +2 -2
  27. package/lib/channelDeltaConnection.js.map +1 -1
  28. package/lib/channelStorageService.js +1 -2
  29. package/lib/channelStorageService.js.map +1 -1
  30. package/lib/dataStoreRuntime.d.ts +9 -3
  31. package/lib/dataStoreRuntime.d.ts.map +1 -1
  32. package/lib/dataStoreRuntime.js +74 -76
  33. package/lib/dataStoreRuntime.js.map +1 -1
  34. package/lib/localChannelContext.d.ts +1 -1
  35. package/lib/localChannelContext.d.ts.map +1 -1
  36. package/lib/localChannelContext.js +2 -3
  37. package/lib/localChannelContext.js.map +1 -1
  38. package/lib/localChannelStorageService.js +1 -1
  39. package/lib/localChannelStorageService.js.map +1 -1
  40. package/lib/remoteChannelContext.d.ts.map +1 -1
  41. package/lib/remoteChannelContext.js +7 -5
  42. package/lib/remoteChannelContext.js.map +1 -1
  43. package/package.json +28 -31
  44. package/src/channelContext.ts +28 -36
  45. package/src/channelDeltaConnection.ts +2 -2
  46. package/src/dataStoreRuntime.ts +105 -94
  47. package/src/localChannelContext.ts +2 -4
  48. package/src/localChannelStorageService.ts +1 -1
  49. package/src/remoteChannelContext.ts +6 -4
@@ -3,15 +3,17 @@
3
3
  * Licensed under the MIT License.
4
4
  */
5
5
 
6
+ import { TypedEventEmitter } from "@fluid-internal/client-utils";
6
7
  import {
8
+ DataProcessingError,
7
9
  ITelemetryLoggerExt,
8
- ChildLogger,
9
10
  generateStack,
10
11
  LoggingError,
11
- loggerToMonitoringContext,
12
12
  MonitoringContext,
13
13
  raiseConnectedEvent,
14
- TelemetryDataTag,
14
+ createChildMonitoringContext,
15
+ tagCodeArtifacts,
16
+ UsageError,
15
17
  } from "@fluidframework/telemetry-utils";
16
18
  import {
17
19
  FluidObject,
@@ -20,15 +22,13 @@ import {
20
22
  IRequest,
21
23
  IResponse,
22
24
  } from "@fluidframework/core-interfaces";
23
- import { LazyPromise } from "@fluidframework/core-utils";
25
+ import { assert, Deferred, LazyPromise, unreachableCase } from "@fluidframework/core-utils";
24
26
  import {
25
27
  IAudience,
26
28
  IDeltaManager,
27
29
  AttachState,
28
30
  ILoaderOptions,
29
31
  } from "@fluidframework/container-definitions";
30
- import { DataProcessingError, UsageError } from "@fluidframework/container-utils";
31
- import { assert, Deferred, TypedEventEmitter, unreachableCase } from "@fluidframework/common-utils";
32
32
  import { buildSnapshotTree } from "@fluidframework/driver-utils";
33
33
  import {
34
34
  IClientDetails,
@@ -40,6 +40,7 @@ import {
40
40
  IQuorumClients,
41
41
  } from "@fluidframework/protocol-definitions";
42
42
  import {
43
+ CreateChildSummarizerNodeParam,
43
44
  CreateSummarizerNodeSource,
44
45
  IAttachMessage,
45
46
  IEnvelope,
@@ -63,7 +64,6 @@ import {
63
64
  exceptionToResponse,
64
65
  GCDataBuilder,
65
66
  requestFluidObject,
66
- packagePathToTelemetryProperty,
67
67
  unpackChildNodesUsedRoutes,
68
68
  } from "@fluidframework/runtime-utils";
69
69
  import {
@@ -127,6 +127,9 @@ export class FluidDataStoreRuntime
127
127
  */
128
128
  public readonly entryPoint?: IFluidHandle<FluidObject>;
129
129
 
130
+ /**
131
+ * @deprecated - Will be removed in future major release. Migrate all usage of IFluidRouter to the "entryPoint" pattern. Refer to Removing-IFluidRouter.md
132
+ */
130
133
  public get IFluidRouter() {
131
134
  return this;
132
135
  }
@@ -183,8 +186,7 @@ export class FluidDataStoreRuntime
183
186
  }
184
187
 
185
188
  private readonly contexts = new Map<string, IChannelContext>();
186
- private readonly contextsDeferred = new Map<string, Deferred<IChannelContext>>();
187
- private readonly pendingAttach = new Map<string, IAttachMessage>();
189
+ private readonly pendingAttach = new Set<string>();
188
190
 
189
191
  private readonly deferredAttached = new Deferred<void>();
190
192
  private readonly localChannelContextQueue = new Map<string, LocalChannelContextBase>();
@@ -251,11 +253,13 @@ export class FluidDataStoreRuntime
251
253
  0x30e /* Id cannot contain slashes. DataStoreContext should have validated this. */,
252
254
  );
253
255
 
254
- this.mc = loggerToMonitoringContext(
255
- ChildLogger.create(dataStoreContext.logger, "FluidDataStoreRuntime", {
256
+ this.mc = createChildMonitoringContext({
257
+ logger: dataStoreContext.logger,
258
+ namespace: "FluidDataStoreRuntime",
259
+ properties: {
256
260
  all: { dataStoreId: uuid() },
257
- }),
258
- );
261
+ },
262
+ });
259
263
 
260
264
  this.id = dataStoreContext.id;
261
265
  this.options = dataStoreContext.options;
@@ -320,11 +324,8 @@ export class FluidDataStoreRuntime
320
324
  }),
321
325
  );
322
326
  }
323
- const deferred = new Deferred<IChannelContext>();
324
- deferred.resolve(channelContext);
325
327
 
326
328
  this.contexts.set(path, channelContext);
327
- this.contextsDeferred.set(path, deferred);
328
329
  });
329
330
  }
330
331
 
@@ -383,6 +384,9 @@ export class FluidDataStoreRuntime
383
384
  return this.request(request);
384
385
  }
385
386
 
387
+ /**
388
+ * @deprecated - Will be removed in future major release. Migrate all usage of IFluidRouter to the "entryPoint" pattern. Refer to Removing-IFluidRouter.md
389
+ */
386
390
  public async request(request: IRequest): Promise<IResponse> {
387
391
  try {
388
392
  const parser = RequestParser.create(request);
@@ -393,11 +397,10 @@ export class FluidDataStoreRuntime
393
397
  }
394
398
 
395
399
  // Check for a data type reference first
396
- if (this.contextsDeferred.has(id) && parser.isLeaf(1)) {
400
+ const context = this.contexts.get(id);
401
+ if (context !== undefined && parser.isLeaf(1)) {
397
402
  try {
398
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
399
- const value = await this.contextsDeferred.get(id)!.promise;
400
- const channel = await value.getChannel();
403
+ const channel = await context.getChannel();
401
404
 
402
405
  return { mimeType: "fluid/object", status: 200, value: channel };
403
406
  } catch (error) {
@@ -420,18 +423,12 @@ export class FluidDataStoreRuntime
420
423
  public async getChannel(id: string): Promise<IChannel> {
421
424
  this.verifyNotClosed();
422
425
 
423
- // TODO we don't assume any channels (even root) in the runtime. If you request a channel that doesn't exist
424
- // we will never resolve the promise. May want a flag to getChannel that doesn't wait for the promise if
425
- // it doesn't exist
426
- if (!this.contextsDeferred.has(id)) {
427
- this.contextsDeferred.set(id, new Deferred<IChannelContext>());
426
+ const context = this.contexts.get(id);
427
+ if (context === undefined) {
428
+ throw new LoggingError("Channel does not exist");
428
429
  }
429
430
 
430
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
431
- const context = await this.contextsDeferred.get(id)!.promise;
432
- const channel = await context.getChannel();
433
-
434
- return channel;
431
+ return context.getChannel();
435
432
  }
436
433
 
437
434
  public createChannel(id: string = uuid(), type: string): IChannel {
@@ -458,15 +455,6 @@ export class FluidDataStoreRuntime
458
455
  );
459
456
  this.contexts.set(id, context);
460
457
 
461
- if (this.contextsDeferred.has(id)) {
462
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
463
- this.contextsDeferred.get(id)!.resolve(context);
464
- } else {
465
- const deferred = new Deferred<IChannelContext>();
466
- deferred.resolve(context);
467
- this.contextsDeferred.set(id, deferred);
468
- }
469
-
470
458
  // Channels (DDS) should not be created in summarizer client.
471
459
  this.identifyLocalChangeInSummarizer("DDSCreatedInSummarizer", id, type);
472
460
 
@@ -578,10 +566,41 @@ export class FluidDataStoreRuntime
578
566
  return this.audience;
579
567
  }
580
568
 
581
- public async uploadBlob(blob: ArrayBufferLike): Promise<IFluidHandle<ArrayBufferLike>> {
569
+ public async uploadBlob(
570
+ blob: ArrayBufferLike,
571
+ signal?: AbortSignal,
572
+ ): Promise<IFluidHandle<ArrayBufferLike>> {
582
573
  this.verifyNotClosed();
583
574
 
584
- return this.dataStoreContext.uploadBlob(blob);
575
+ return this.dataStoreContext.uploadBlob(blob, signal);
576
+ }
577
+
578
+ private createRemoteChannelContext(
579
+ attachMessage: IAttachMessage,
580
+ summarizerNodeParams: CreateChildSummarizerNodeParam,
581
+ ) {
582
+ const flatBlobs = new Map<string, ArrayBufferLike>();
583
+ const snapshotTree = buildSnapshotTree(attachMessage.snapshot.entries, flatBlobs);
584
+
585
+ return new RemoteChannelContext(
586
+ this,
587
+ this.dataStoreContext,
588
+ this.dataStoreContext.storage,
589
+ (content, localContentMetadata) =>
590
+ this.submitChannelOp(attachMessage.id, content, localContentMetadata),
591
+ (address: string) => this.setChannelDirty(address),
592
+ (srcHandle: IFluidHandle, outboundHandle: IFluidHandle) =>
593
+ this.addedGCOutboundReference(srcHandle, outboundHandle),
594
+ attachMessage.id,
595
+ snapshotTree,
596
+ this.sharedObjectRegistry,
597
+ flatBlobs,
598
+ this.dataStoreContext.getCreateChildSummarizerNodeFn(
599
+ attachMessage.id,
600
+ summarizerNodeParams,
601
+ ),
602
+ attachMessage.type,
603
+ );
585
604
  }
586
605
 
587
606
  public process(message: ISequencedDocumentMessage, local: boolean, localOpMetadata: unknown) {
@@ -598,49 +617,23 @@ export class FluidDataStoreRuntime
598
617
  // Otherwise mark it as officially attached.
599
618
  if (local) {
600
619
  assert(
601
- this.pendingAttach.has(id),
620
+ this.pendingAttach.delete(id),
602
621
  0x17c /* "Unexpected attach (local) channel OP" */,
603
622
  );
604
- this.pendingAttach.delete(id);
605
623
  } else {
606
624
  assert(!this.contexts.has(id), 0x17d /* "Unexpected attach channel OP" */);
607
625
 
608
- const flatBlobs = new Map<string, ArrayBufferLike>();
609
- const snapshotTree = buildSnapshotTree(
610
- attachMessage.snapshot.entries,
611
- flatBlobs,
612
- );
626
+ const summarizerNodeParams = {
627
+ type: CreateSummarizerNodeSource.FromAttach,
628
+ sequenceNumber: message.sequenceNumber,
629
+ snapshot: attachMessage.snapshot,
630
+ };
613
631
 
614
- const remoteChannelContext = new RemoteChannelContext(
615
- this,
616
- this.dataStoreContext,
617
- this.dataStoreContext.storage,
618
- (content, localContentMetadata) =>
619
- this.submitChannelOp(id, content, localContentMetadata),
620
- (address: string) => this.setChannelDirty(address),
621
- (srcHandle: IFluidHandle, outboundHandle: IFluidHandle) =>
622
- this.addedGCOutboundReference(srcHandle, outboundHandle),
623
- id,
624
- snapshotTree,
625
- this.sharedObjectRegistry,
626
- flatBlobs,
627
- this.dataStoreContext.getCreateChildSummarizerNodeFn(id, {
628
- type: CreateSummarizerNodeSource.FromAttach,
629
- sequenceNumber: message.sequenceNumber,
630
- snapshot: attachMessage.snapshot,
631
- }),
632
- attachMessage.type,
632
+ const remoteChannelContext = this.createRemoteChannelContext(
633
+ attachMessage,
634
+ summarizerNodeParams,
633
635
  );
634
-
635
636
  this.contexts.set(id, remoteChannelContext);
636
- if (this.contextsDeferred.has(id)) {
637
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
638
- this.contextsDeferred.get(id)!.resolve(remoteChannelContext);
639
- } else {
640
- const deferred = new Deferred<IChannelContext>();
641
- deferred.resolve(remoteChannelContext);
642
- this.contextsDeferred.set(id, deferred);
643
- }
644
637
  }
645
638
  break;
646
639
  }
@@ -920,7 +913,7 @@ export class FluidDataStoreRuntime
920
913
  snapshot,
921
914
  type: channel.attributes.type,
922
915
  };
923
- this.pendingAttach.set(channel.id, message);
916
+ this.pendingAttach.add(channel.id);
924
917
  this.submit(DataStoreMessageType.Attach, message);
925
918
 
926
919
  const context = this.contexts.get(channel.id) as LocalChannelContextBase;
@@ -998,11 +991,35 @@ export class FluidDataStoreRuntime
998
991
  }
999
992
 
1000
993
  public async applyStashedOp(content: any): Promise<unknown> {
1001
- const envelope = content as IEnvelope;
1002
- const channelContext = this.contexts.get(envelope.address);
1003
- assert(!!channelContext, 0x184 /* "There should be a channel context for the op" */);
1004
- await channelContext.getChannel();
1005
- return channelContext.applyStashedOp(envelope.contents);
994
+ const type = content?.type as DataStoreMessageType;
995
+ switch (type) {
996
+ case DataStoreMessageType.Attach: {
997
+ const attachMessage = content.content as IAttachMessage;
998
+ // local means this node will throw if summarized; this is fine because only interactive clients will have stashed ops
999
+ const summarizerNodeParams: CreateChildSummarizerNodeParam = {
1000
+ type: CreateSummarizerNodeSource.Local,
1001
+ };
1002
+ const context = this.createRemoteChannelContext(
1003
+ attachMessage,
1004
+ summarizerNodeParams,
1005
+ );
1006
+ this.pendingAttach.add(attachMessage.id);
1007
+ this.contexts.set(attachMessage.id, context);
1008
+ return;
1009
+ }
1010
+ case DataStoreMessageType.ChannelOp: {
1011
+ const envelope = content.content as IEnvelope;
1012
+ const channelContext = this.contexts.get(envelope.address);
1013
+ assert(
1014
+ !!channelContext,
1015
+ 0x184 /* "There should be a channel context for the op" */,
1016
+ );
1017
+ await channelContext.getChannel();
1018
+ return channelContext.applyStashedOp(envelope.contents);
1019
+ }
1020
+ default:
1021
+ unreachableCase(type);
1022
+ }
1006
1023
  }
1007
1024
 
1008
1025
  private setChannelDirty(address: string): void {
@@ -1098,18 +1115,12 @@ export class FluidDataStoreRuntime
1098
1115
  // in the summarizer and the data will help us plan this.
1099
1116
  this.mc.logger.sendTelemetryEvent({
1100
1117
  eventName,
1101
- channelType,
1102
- channelId: {
1103
- value: channelId,
1104
- tag: TelemetryDataTag.CodeArtifact,
1105
- },
1106
- fluidDataStoreId: {
1107
- value: this.id,
1108
- tag: TelemetryDataTag.CodeArtifact,
1109
- },
1110
- fluidDataStorePackagePath: packagePathToTelemetryProperty(
1111
- this.dataStoreContext.packagePath,
1112
- ),
1118
+ ...tagCodeArtifacts({
1119
+ channelType,
1120
+ channelId,
1121
+ fluidDataStoreId: this.id,
1122
+ fluidDataStorePackagePath: this.dataStoreContext.packagePath.join("/"),
1123
+ }),
1113
1124
  stack: generateStack(),
1114
1125
  });
1115
1126
  this.localChangesTelemetryCount--;
@@ -5,7 +5,7 @@
5
5
 
6
6
  // eslint-disable-next-line import/no-internal-modules
7
7
  import cloneDeep from "lodash/cloneDeep";
8
- import { ITelemetryLoggerExt } from "@fluidframework/telemetry-utils";
8
+ import { DataProcessingError, ITelemetryLoggerExt } from "@fluidframework/telemetry-utils";
9
9
  import { IDocumentStorageService } from "@fluidframework/driver-definitions";
10
10
  import { ISequencedDocumentMessage, ISnapshotTree } from "@fluidframework/protocol-definitions";
11
11
  import { IChannel, IFluidDataStoreRuntime } from "@fluidframework/datastore-definitions";
@@ -15,10 +15,8 @@ import {
15
15
  ISummarizeResult,
16
16
  ITelemetryContext,
17
17
  } from "@fluidframework/runtime-definitions";
18
- import { DataProcessingError } from "@fluidframework/container-utils";
19
- import { assert } from "@fluidframework/common-utils";
18
+ import { assert, Lazy, LazyPromise } from "@fluidframework/core-utils";
20
19
  import { IFluidHandle } from "@fluidframework/core-interfaces";
21
- import { Lazy, LazyPromise } from "@fluidframework/core-utils";
22
20
  import {
23
21
  ChannelServiceEndpoints,
24
22
  createChannelServiceEndpoints,
@@ -4,7 +4,7 @@
4
4
  */
5
5
 
6
6
  import { IChannelStorageService } from "@fluidframework/datastore-definitions";
7
- import { stringToBuffer } from "@fluidframework/common-utils";
7
+ import { stringToBuffer } from "@fluid-internal/client-utils";
8
8
  import { IBlob, ITree, TreeEntry } from "@fluidframework/protocol-definitions";
9
9
  import { listBlobsAtTreePath } from "@fluidframework/runtime-utils";
10
10
 
@@ -3,9 +3,8 @@
3
3
  * Licensed under the MIT License.
4
4
  */
5
5
 
6
- import { assert } from "@fluidframework/common-utils";
6
+ import { assert, LazyPromise } from "@fluidframework/core-utils";
7
7
  import { IFluidHandle } from "@fluidframework/core-interfaces";
8
- import { LazyPromise } from "@fluidframework/core-utils";
9
8
  import { IChannel, IFluidDataStoreRuntime } from "@fluidframework/datastore-definitions";
10
9
  import { IDocumentStorageService } from "@fluidframework/driver-definitions";
11
10
  import { ISequencedDocumentMessage, ISnapshotTree } from "@fluidframework/protocol-definitions";
@@ -20,7 +19,7 @@ import {
20
19
  ITelemetryContext,
21
20
  } from "@fluidframework/runtime-definitions";
22
21
  import {
23
- ChildLogger,
22
+ createChildLogger,
24
23
  ITelemetryLoggerExt,
25
24
  ThresholdCounter,
26
25
  } from "@fluidframework/telemetry-utils";
@@ -61,7 +60,10 @@ export class RemoteChannelContext implements IChannelContext {
61
60
  ) {
62
61
  assert(!this.id.includes("/"), 0x310 /* Channel context ID cannot contain slashes */);
63
62
 
64
- this.subLogger = ChildLogger.create(runtime.logger, "RemoteChannelContext");
63
+ this.subLogger = createChildLogger({
64
+ logger: runtime.logger,
65
+ namespace: "RemoteChannelContext",
66
+ });
65
67
 
66
68
  this.services = createChannelServiceEndpoints(
67
69
  dataStoreContext.connected,