@fluidframework/datastore 2.0.0-dev.5.2.0.169897 → 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 +101 -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 +93 -94
  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 +16 -16
  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 +14 -11
  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 -75
  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 -2
  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 -4
  42. package/lib/remoteChannelContext.js.map +1 -1
  43. package/package.json +29 -31
  44. package/src/channelContext.ts +28 -36
  45. package/src/channelDeltaConnection.ts +2 -2
  46. package/src/dataStoreRuntime.ts +105 -99
  47. package/src/localChannelContext.ts +2 -3
  48. package/src/localChannelStorageService.ts +1 -1
  49. package/src/remoteChannelContext.ts +6 -3
@@ -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,20 +22,13 @@ import {
20
22
  IRequest,
21
23
  IResponse,
22
24
  } from "@fluidframework/core-interfaces";
25
+ import { assert, Deferred, LazyPromise, unreachableCase } from "@fluidframework/core-utils";
23
26
  import {
24
27
  IAudience,
25
28
  IDeltaManager,
26
29
  AttachState,
27
30
  ILoaderOptions,
28
31
  } from "@fluidframework/container-definitions";
29
- import { DataProcessingError, UsageError } from "@fluidframework/container-utils";
30
- import {
31
- assert,
32
- Deferred,
33
- LazyPromise,
34
- TypedEventEmitter,
35
- unreachableCase,
36
- } from "@fluidframework/common-utils";
37
32
  import { buildSnapshotTree } from "@fluidframework/driver-utils";
38
33
  import {
39
34
  IClientDetails,
@@ -45,6 +40,7 @@ import {
45
40
  IQuorumClients,
46
41
  } from "@fluidframework/protocol-definitions";
47
42
  import {
43
+ CreateChildSummarizerNodeParam,
48
44
  CreateSummarizerNodeSource,
49
45
  IAttachMessage,
50
46
  IEnvelope,
@@ -68,7 +64,6 @@ import {
68
64
  exceptionToResponse,
69
65
  GCDataBuilder,
70
66
  requestFluidObject,
71
- packagePathToTelemetryProperty,
72
67
  unpackChildNodesUsedRoutes,
73
68
  } from "@fluidframework/runtime-utils";
74
69
  import {
@@ -132,6 +127,9 @@ export class FluidDataStoreRuntime
132
127
  */
133
128
  public readonly entryPoint?: IFluidHandle<FluidObject>;
134
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
+ */
135
133
  public get IFluidRouter() {
136
134
  return this;
137
135
  }
@@ -188,8 +186,7 @@ export class FluidDataStoreRuntime
188
186
  }
189
187
 
190
188
  private readonly contexts = new Map<string, IChannelContext>();
191
- private readonly contextsDeferred = new Map<string, Deferred<IChannelContext>>();
192
- private readonly pendingAttach = new Map<string, IAttachMessage>();
189
+ private readonly pendingAttach = new Set<string>();
193
190
 
194
191
  private readonly deferredAttached = new Deferred<void>();
195
192
  private readonly localChannelContextQueue = new Map<string, LocalChannelContextBase>();
@@ -256,11 +253,13 @@ export class FluidDataStoreRuntime
256
253
  0x30e /* Id cannot contain slashes. DataStoreContext should have validated this. */,
257
254
  );
258
255
 
259
- this.mc = loggerToMonitoringContext(
260
- ChildLogger.create(dataStoreContext.logger, "FluidDataStoreRuntime", {
256
+ this.mc = createChildMonitoringContext({
257
+ logger: dataStoreContext.logger,
258
+ namespace: "FluidDataStoreRuntime",
259
+ properties: {
261
260
  all: { dataStoreId: uuid() },
262
- }),
263
- );
261
+ },
262
+ });
264
263
 
265
264
  this.id = dataStoreContext.id;
266
265
  this.options = dataStoreContext.options;
@@ -325,11 +324,8 @@ export class FluidDataStoreRuntime
325
324
  }),
326
325
  );
327
326
  }
328
- const deferred = new Deferred<IChannelContext>();
329
- deferred.resolve(channelContext);
330
327
 
331
328
  this.contexts.set(path, channelContext);
332
- this.contextsDeferred.set(path, deferred);
333
329
  });
334
330
  }
335
331
 
@@ -388,6 +384,9 @@ export class FluidDataStoreRuntime
388
384
  return this.request(request);
389
385
  }
390
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
+ */
391
390
  public async request(request: IRequest): Promise<IResponse> {
392
391
  try {
393
392
  const parser = RequestParser.create(request);
@@ -398,11 +397,10 @@ export class FluidDataStoreRuntime
398
397
  }
399
398
 
400
399
  // Check for a data type reference first
401
- if (this.contextsDeferred.has(id) && parser.isLeaf(1)) {
400
+ const context = this.contexts.get(id);
401
+ if (context !== undefined && parser.isLeaf(1)) {
402
402
  try {
403
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
404
- const value = await this.contextsDeferred.get(id)!.promise;
405
- const channel = await value.getChannel();
403
+ const channel = await context.getChannel();
406
404
 
407
405
  return { mimeType: "fluid/object", status: 200, value: channel };
408
406
  } catch (error) {
@@ -425,18 +423,12 @@ export class FluidDataStoreRuntime
425
423
  public async getChannel(id: string): Promise<IChannel> {
426
424
  this.verifyNotClosed();
427
425
 
428
- // TODO we don't assume any channels (even root) in the runtime. If you request a channel that doesn't exist
429
- // we will never resolve the promise. May want a flag to getChannel that doesn't wait for the promise if
430
- // it doesn't exist
431
- if (!this.contextsDeferred.has(id)) {
432
- 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");
433
429
  }
434
430
 
435
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
436
- const context = await this.contextsDeferred.get(id)!.promise;
437
- const channel = await context.getChannel();
438
-
439
- return channel;
431
+ return context.getChannel();
440
432
  }
441
433
 
442
434
  public createChannel(id: string = uuid(), type: string): IChannel {
@@ -463,15 +455,6 @@ export class FluidDataStoreRuntime
463
455
  );
464
456
  this.contexts.set(id, context);
465
457
 
466
- if (this.contextsDeferred.has(id)) {
467
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
468
- this.contextsDeferred.get(id)!.resolve(context);
469
- } else {
470
- const deferred = new Deferred<IChannelContext>();
471
- deferred.resolve(context);
472
- this.contextsDeferred.set(id, deferred);
473
- }
474
-
475
458
  // Channels (DDS) should not be created in summarizer client.
476
459
  this.identifyLocalChangeInSummarizer("DDSCreatedInSummarizer", id, type);
477
460
 
@@ -583,10 +566,41 @@ export class FluidDataStoreRuntime
583
566
  return this.audience;
584
567
  }
585
568
 
586
- public async uploadBlob(blob: ArrayBufferLike): Promise<IFluidHandle<ArrayBufferLike>> {
569
+ public async uploadBlob(
570
+ blob: ArrayBufferLike,
571
+ signal?: AbortSignal,
572
+ ): Promise<IFluidHandle<ArrayBufferLike>> {
587
573
  this.verifyNotClosed();
588
574
 
589
- 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
+ );
590
604
  }
591
605
 
592
606
  public process(message: ISequencedDocumentMessage, local: boolean, localOpMetadata: unknown) {
@@ -603,49 +617,23 @@ export class FluidDataStoreRuntime
603
617
  // Otherwise mark it as officially attached.
604
618
  if (local) {
605
619
  assert(
606
- this.pendingAttach.has(id),
620
+ this.pendingAttach.delete(id),
607
621
  0x17c /* "Unexpected attach (local) channel OP" */,
608
622
  );
609
- this.pendingAttach.delete(id);
610
623
  } else {
611
624
  assert(!this.contexts.has(id), 0x17d /* "Unexpected attach channel OP" */);
612
625
 
613
- const flatBlobs = new Map<string, ArrayBufferLike>();
614
- const snapshotTree = buildSnapshotTree(
615
- attachMessage.snapshot.entries,
616
- flatBlobs,
617
- );
626
+ const summarizerNodeParams = {
627
+ type: CreateSummarizerNodeSource.FromAttach,
628
+ sequenceNumber: message.sequenceNumber,
629
+ snapshot: attachMessage.snapshot,
630
+ };
618
631
 
619
- const remoteChannelContext = new RemoteChannelContext(
620
- this,
621
- this.dataStoreContext,
622
- this.dataStoreContext.storage,
623
- (content, localContentMetadata) =>
624
- this.submitChannelOp(id, content, localContentMetadata),
625
- (address: string) => this.setChannelDirty(address),
626
- (srcHandle: IFluidHandle, outboundHandle: IFluidHandle) =>
627
- this.addedGCOutboundReference(srcHandle, outboundHandle),
628
- id,
629
- snapshotTree,
630
- this.sharedObjectRegistry,
631
- flatBlobs,
632
- this.dataStoreContext.getCreateChildSummarizerNodeFn(id, {
633
- type: CreateSummarizerNodeSource.FromAttach,
634
- sequenceNumber: message.sequenceNumber,
635
- snapshot: attachMessage.snapshot,
636
- }),
637
- attachMessage.type,
632
+ const remoteChannelContext = this.createRemoteChannelContext(
633
+ attachMessage,
634
+ summarizerNodeParams,
638
635
  );
639
-
640
636
  this.contexts.set(id, remoteChannelContext);
641
- if (this.contextsDeferred.has(id)) {
642
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
643
- this.contextsDeferred.get(id)!.resolve(remoteChannelContext);
644
- } else {
645
- const deferred = new Deferred<IChannelContext>();
646
- deferred.resolve(remoteChannelContext);
647
- this.contextsDeferred.set(id, deferred);
648
- }
649
637
  }
650
638
  break;
651
639
  }
@@ -925,7 +913,7 @@ export class FluidDataStoreRuntime
925
913
  snapshot,
926
914
  type: channel.attributes.type,
927
915
  };
928
- this.pendingAttach.set(channel.id, message);
916
+ this.pendingAttach.add(channel.id);
929
917
  this.submit(DataStoreMessageType.Attach, message);
930
918
 
931
919
  const context = this.contexts.get(channel.id) as LocalChannelContextBase;
@@ -1003,11 +991,35 @@ export class FluidDataStoreRuntime
1003
991
  }
1004
992
 
1005
993
  public async applyStashedOp(content: any): Promise<unknown> {
1006
- const envelope = content as IEnvelope;
1007
- const channelContext = this.contexts.get(envelope.address);
1008
- assert(!!channelContext, 0x184 /* "There should be a channel context for the op" */);
1009
- await channelContext.getChannel();
1010
- 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
+ }
1011
1023
  }
1012
1024
 
1013
1025
  private setChannelDirty(address: string): void {
@@ -1103,18 +1115,12 @@ export class FluidDataStoreRuntime
1103
1115
  // in the summarizer and the data will help us plan this.
1104
1116
  this.mc.logger.sendTelemetryEvent({
1105
1117
  eventName,
1106
- channelType,
1107
- channelId: {
1108
- value: channelId,
1109
- tag: TelemetryDataTag.CodeArtifact,
1110
- },
1111
- fluidDataStoreId: {
1112
- value: this.id,
1113
- tag: TelemetryDataTag.CodeArtifact,
1114
- },
1115
- fluidDataStorePackagePath: packagePathToTelemetryProperty(
1116
- this.dataStoreContext.packagePath,
1117
- ),
1118
+ ...tagCodeArtifacts({
1119
+ channelType,
1120
+ channelId,
1121
+ fluidDataStoreId: this.id,
1122
+ fluidDataStorePackagePath: this.dataStoreContext.packagePath.join("/"),
1123
+ }),
1118
1124
  stack: generateStack(),
1119
1125
  });
1120
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,8 +15,7 @@ import {
15
15
  ISummarizeResult,
16
16
  ITelemetryContext,
17
17
  } from "@fluidframework/runtime-definitions";
18
- import { DataProcessingError } from "@fluidframework/container-utils";
19
- import { assert, Lazy, LazyPromise } from "@fluidframework/common-utils";
18
+ import { assert, Lazy, LazyPromise } from "@fluidframework/core-utils";
20
19
  import { IFluidHandle } from "@fluidframework/core-interfaces";
21
20
  import {
22
21
  ChannelServiceEndpoints,
@@ -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,7 +3,7 @@
3
3
  * Licensed under the MIT License.
4
4
  */
5
5
 
6
- import { LazyPromise, assert } from "@fluidframework/common-utils";
6
+ import { assert, LazyPromise } from "@fluidframework/core-utils";
7
7
  import { IFluidHandle } from "@fluidframework/core-interfaces";
8
8
  import { IChannel, IFluidDataStoreRuntime } from "@fluidframework/datastore-definitions";
9
9
  import { IDocumentStorageService } from "@fluidframework/driver-definitions";
@@ -19,7 +19,7 @@ import {
19
19
  ITelemetryContext,
20
20
  } from "@fluidframework/runtime-definitions";
21
21
  import {
22
- ChildLogger,
22
+ createChildLogger,
23
23
  ITelemetryLoggerExt,
24
24
  ThresholdCounter,
25
25
  } from "@fluidframework/telemetry-utils";
@@ -60,7 +60,10 @@ export class RemoteChannelContext implements IChannelContext {
60
60
  ) {
61
61
  assert(!this.id.includes("/"), 0x310 /* Channel context ID cannot contain slashes */);
62
62
 
63
- this.subLogger = ChildLogger.create(runtime.logger, "RemoteChannelContext");
63
+ this.subLogger = createChildLogger({
64
+ logger: runtime.logger,
65
+ namespace: "RemoteChannelContext",
66
+ });
64
67
 
65
68
  this.services = createChannelServiceEndpoints(
66
69
  dataStoreContext.connected,