@fluidframework/datastore 2.0.0-internal.3.1.0 → 2.0.0-internal.3.2.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/package.json CHANGED
@@ -1,113 +1,113 @@
1
1
  {
2
- "name": "@fluidframework/datastore",
3
- "version": "2.0.0-internal.3.1.0",
4
- "description": "Fluid data store implementation",
5
- "homepage": "https://fluidframework.com",
6
- "repository": {
7
- "type": "git",
8
- "url": "https://github.com/microsoft/FluidFramework.git",
9
- "directory": "packages/runtime/datastore"
10
- },
11
- "license": "MIT",
12
- "author": "Microsoft and contributors",
13
- "sideEffects": false,
14
- "main": "dist/index.js",
15
- "module": "lib/index.js",
16
- "types": "dist/index.d.ts",
17
- "scripts": {
18
- "build": "npm run build:genver && concurrently npm:build:compile npm:lint && npm run build:docs",
19
- "build:commonjs": "npm run tsc && npm run typetests:gen && npm run build:test",
20
- "build:compile": "concurrently npm:build:commonjs npm:build:esnext",
21
- "build:docs": "api-extractor run --local --typescript-compiler-folder ../../../node_modules/typescript && copyfiles -u 1 ./_api-extractor-temp/doc-models/* ../../../_api-extractor-temp/",
22
- "build:esnext": "tsc --project ./tsconfig.esnext.json",
23
- "build:full": "npm run build",
24
- "build:full:compile": "npm run build:compile",
25
- "build:genver": "gen-version",
26
- "build:test": "tsc --project ./src/test/tsconfig.json",
27
- "ci:build:docs": "api-extractor run --typescript-compiler-folder ../../../node_modules/typescript && copyfiles -u 1 ./_api-extractor-temp/* ../../../_api-extractor-temp/",
28
- "clean": "rimraf dist lib *.tsbuildinfo *.build.log",
29
- "eslint": "eslint --format stylish src",
30
- "eslint:fix": "eslint --format stylish src --fix --fix-type problem,suggestion,layout",
31
- "format": "npm run prettier:fix",
32
- "lint": "npm run prettier && npm run eslint",
33
- "lint:fix": "npm run prettier:fix && npm run eslint:fix",
34
- "prettier": "prettier --check . --ignore-path ../../../.prettierignore",
35
- "prettier:fix": "prettier --write . --ignore-path ../../../.prettierignore",
36
- "test": "npm run test:mocha",
37
- "test:coverage": "nyc npm test -- --reporter xunit --reporter-option output=nyc/junit-report.xml",
38
- "test:mocha": "mocha --ignore 'dist/test/types/*' --recursive dist/test --exit -r node_modules/@fluidframework/mocha-test-setup --unhandled-rejections=strict",
39
- "test:mocha:verbose": "cross-env FLUID_TEST_VERBOSE=1 npm run test:mocha",
40
- "tsc": "tsc",
41
- "tsc:watch": "tsc --watch",
42
- "typetests:gen": "flub generate typetests --generate --dir .",
43
- "typetests:prepare": "flub generate typetests --prepare --dir . --pin"
44
- },
45
- "nyc": {
46
- "all": true,
47
- "cache-dir": "nyc/.cache",
48
- "exclude": [
49
- "src/test/**/*.ts",
50
- "dist/test/**/*.js"
51
- ],
52
- "exclude-after-remap": false,
53
- "include": [
54
- "src/**/*.ts",
55
- "dist/**/*.js"
56
- ],
57
- "report-dir": "nyc/report",
58
- "reporter": [
59
- "cobertura",
60
- "html",
61
- "text"
62
- ],
63
- "temp-directory": "nyc/.nyc_output"
64
- },
65
- "dependencies": {
66
- "@fluidframework/common-definitions": "^0.20.1",
67
- "@fluidframework/common-utils": "^1.0.0",
68
- "@fluidframework/container-definitions": ">=2.0.0-internal.3.1.0 <2.0.0-internal.4.0.0",
69
- "@fluidframework/container-utils": ">=2.0.0-internal.3.1.0 <2.0.0-internal.4.0.0",
70
- "@fluidframework/core-interfaces": ">=2.0.0-internal.3.1.0 <2.0.0-internal.4.0.0",
71
- "@fluidframework/datastore-definitions": ">=2.0.0-internal.3.1.0 <2.0.0-internal.4.0.0",
72
- "@fluidframework/driver-definitions": ">=2.0.0-internal.3.1.0 <2.0.0-internal.4.0.0",
73
- "@fluidframework/driver-utils": ">=2.0.0-internal.3.1.0 <2.0.0-internal.4.0.0",
74
- "@fluidframework/garbage-collector": ">=2.0.0-internal.3.1.0 <2.0.0-internal.4.0.0",
75
- "@fluidframework/protocol-base": "^0.1038.2000",
76
- "@fluidframework/protocol-definitions": "^1.1.0",
77
- "@fluidframework/runtime-definitions": ">=2.0.0-internal.3.1.0 <2.0.0-internal.4.0.0",
78
- "@fluidframework/runtime-utils": ">=2.0.0-internal.3.1.0 <2.0.0-internal.4.0.0",
79
- "@fluidframework/telemetry-utils": ">=2.0.0-internal.3.1.0 <2.0.0-internal.4.0.0",
80
- "lodash": "^4.17.21",
81
- "uuid": "^8.3.1"
82
- },
83
- "devDependencies": {
84
- "@fluid-tools/build-cli": "^0.9.0",
85
- "@fluidframework/build-common": "^1.1.0",
86
- "@fluidframework/build-tools": "^0.9.0",
87
- "@fluidframework/datastore-previous": "npm:@fluidframework/datastore@2.0.0-internal.3.0.0",
88
- "@fluidframework/eslint-config-fluid": "^2.0.0",
89
- "@fluidframework/mocha-test-setup": ">=2.0.0-internal.3.1.0 <2.0.0-internal.4.0.0",
90
- "@fluidframework/test-runtime-utils": ">=2.0.0-internal.3.1.0 <2.0.0-internal.4.0.0",
91
- "@microsoft/api-extractor": "^7.22.2",
92
- "@rushstack/eslint-config": "^2.5.1",
93
- "@types/mocha": "^9.1.1",
94
- "@types/node": "^14.18.36",
95
- "@types/uuid": "^8.3.0",
96
- "concurrently": "^6.2.0",
97
- "copyfiles": "^2.4.1",
98
- "cross-env": "^7.0.2",
99
- "eslint": "~8.6.0",
100
- "mocha": "^10.0.0",
101
- "nyc": "^15.0.0",
102
- "prettier": "~2.6.2",
103
- "rimraf": "^2.6.2",
104
- "typescript": "~4.5.5"
105
- },
106
- "typeValidation": {
107
- "version": "2.0.0-internal.3.1.0",
108
- "previousVersionStyle": "~previousMinor",
109
- "baselineRange": ">=2.0.0-internal.3.0.0 <2.0.0-internal.3.1.0",
110
- "baselineVersion": "2.0.0-internal.3.0.0",
111
- "broken": {}
112
- }
113
- }
2
+ "name": "@fluidframework/datastore",
3
+ "version": "2.0.0-internal.3.2.1",
4
+ "description": "Fluid data store implementation",
5
+ "homepage": "https://fluidframework.com",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "https://github.com/microsoft/FluidFramework.git",
9
+ "directory": "packages/runtime/datastore"
10
+ },
11
+ "license": "MIT",
12
+ "author": "Microsoft and contributors",
13
+ "sideEffects": false,
14
+ "main": "dist/index.js",
15
+ "module": "lib/index.js",
16
+ "types": "dist/index.d.ts",
17
+ "nyc": {
18
+ "all": true,
19
+ "cache-dir": "nyc/.cache",
20
+ "exclude": [
21
+ "src/test/**/*.ts",
22
+ "dist/test/**/*.js"
23
+ ],
24
+ "exclude-after-remap": false,
25
+ "include": [
26
+ "src/**/*.ts",
27
+ "dist/**/*.js"
28
+ ],
29
+ "report-dir": "nyc/report",
30
+ "reporter": [
31
+ "cobertura",
32
+ "html",
33
+ "text"
34
+ ],
35
+ "temp-directory": "nyc/.nyc_output"
36
+ },
37
+ "dependencies": {
38
+ "@fluidframework/common-definitions": "^0.20.1",
39
+ "@fluidframework/common-utils": "^1.1.1",
40
+ "@fluidframework/container-definitions": ">=2.0.0-internal.3.2.1 <2.0.0-internal.4.0.0",
41
+ "@fluidframework/container-utils": ">=2.0.0-internal.3.2.1 <2.0.0-internal.4.0.0",
42
+ "@fluidframework/core-interfaces": ">=2.0.0-internal.3.2.1 <2.0.0-internal.4.0.0",
43
+ "@fluidframework/datastore-definitions": ">=2.0.0-internal.3.2.1 <2.0.0-internal.4.0.0",
44
+ "@fluidframework/driver-definitions": ">=2.0.0-internal.3.2.1 <2.0.0-internal.4.0.0",
45
+ "@fluidframework/driver-utils": ">=2.0.0-internal.3.2.1 <2.0.0-internal.4.0.0",
46
+ "@fluidframework/garbage-collector": ">=2.0.0-internal.3.2.1 <2.0.0-internal.4.0.0",
47
+ "@fluidframework/protocol-base": "^0.1038.2000",
48
+ "@fluidframework/protocol-definitions": "^1.1.0",
49
+ "@fluidframework/runtime-definitions": ">=2.0.0-internal.3.2.1 <2.0.0-internal.4.0.0",
50
+ "@fluidframework/runtime-utils": ">=2.0.0-internal.3.2.1 <2.0.0-internal.4.0.0",
51
+ "@fluidframework/telemetry-utils": ">=2.0.0-internal.3.2.1 <2.0.0-internal.4.0.0",
52
+ "lodash": "^4.17.21",
53
+ "uuid": "^8.3.1"
54
+ },
55
+ "devDependencies": {
56
+ "@fluid-tools/build-cli": "^0.10.0",
57
+ "@fluidframework/build-common": "^1.1.0",
58
+ "@fluidframework/build-tools": "^0.10.0",
59
+ "@fluidframework/datastore-previous": "npm:@fluidframework/datastore@2.0.0-internal.3.1.0",
60
+ "@fluidframework/eslint-config-fluid": "^2.0.0",
61
+ "@fluidframework/mocha-test-setup": ">=2.0.0-internal.3.2.1 <2.0.0-internal.4.0.0",
62
+ "@fluidframework/test-runtime-utils": ">=2.0.0-internal.3.2.1 <2.0.0-internal.4.0.0",
63
+ "@microsoft/api-extractor": "^7.22.2",
64
+ "@rushstack/eslint-config": "^2.5.1",
65
+ "@types/mocha": "^9.1.1",
66
+ "@types/node": "^14.18.36",
67
+ "@types/uuid": "^8.3.0",
68
+ "concurrently": "^6.2.0",
69
+ "copyfiles": "^2.4.1",
70
+ "cross-env": "^7.0.2",
71
+ "eslint": "~8.6.0",
72
+ "mocha": "^10.0.0",
73
+ "nyc": "^15.0.0",
74
+ "prettier": "~2.6.2",
75
+ "rimraf": "^2.6.2",
76
+ "typescript": "~4.5.5"
77
+ },
78
+ "typeValidation": {
79
+ "version": "2.0.0-internal.3.2.0",
80
+ "previousVersionStyle": "~previousMinor",
81
+ "baselineRange": ">=2.0.0-internal.3.1.0 <2.0.0-internal.3.2.0",
82
+ "baselineVersion": "2.0.0-internal.3.1.0",
83
+ "broken": {}
84
+ },
85
+ "scripts": {
86
+ "build": "npm run build:genver && concurrently npm:build:compile npm:lint && npm run build:docs",
87
+ "build:commonjs": "npm run tsc && npm run typetests:gen && npm run build:test",
88
+ "build:compile": "concurrently npm:build:commonjs npm:build:esnext",
89
+ "build:docs": "api-extractor run --local --typescript-compiler-folder ../../../node_modules/typescript && copyfiles -u 1 ./_api-extractor-temp/doc-models/* ../../../_api-extractor-temp/",
90
+ "build:esnext": "tsc --project ./tsconfig.esnext.json",
91
+ "build:full": "npm run build",
92
+ "build:full:compile": "npm run build:compile",
93
+ "build:genver": "gen-version",
94
+ "build:test": "tsc --project ./src/test/tsconfig.json",
95
+ "ci:build:docs": "api-extractor run --typescript-compiler-folder ../../../node_modules/typescript && copyfiles -u 1 ./_api-extractor-temp/* ../../../_api-extractor-temp/",
96
+ "clean": "rimraf dist lib *.tsbuildinfo *.build.log",
97
+ "eslint": "eslint --format stylish src",
98
+ "eslint:fix": "eslint --format stylish src --fix --fix-type problem,suggestion,layout",
99
+ "format": "npm run prettier:fix",
100
+ "lint": "npm run prettier && npm run eslint",
101
+ "lint:fix": "npm run prettier:fix && npm run eslint:fix",
102
+ "prettier": "prettier --check . --ignore-path ../../../.prettierignore",
103
+ "prettier:fix": "prettier --write . --ignore-path ../../../.prettierignore",
104
+ "test": "npm run test:mocha",
105
+ "test:coverage": "nyc npm test -- --reporter xunit --reporter-option output=nyc/junit-report.xml",
106
+ "test:mocha": "mocha --ignore 'dist/test/types/*' --recursive dist/test --exit -r node_modules/@fluidframework/mocha-test-setup --unhandled-rejections=strict",
107
+ "test:mocha:verbose": "cross-env FLUID_TEST_VERBOSE=1 npm run test:mocha",
108
+ "tsc": "tsc",
109
+ "tsc:watch": "tsc --watch",
110
+ "typetests:gen": "flub generate typetests --generate --dir .",
111
+ "typetests:prepare": "flub generate typetests --prepare --dir . --pin"
112
+ }
113
+ }
@@ -25,7 +25,15 @@ import {
25
25
  TypedEventEmitter,
26
26
  unreachableCase,
27
27
  } from "@fluidframework/common-utils";
28
- import { ChildLogger, LoggingError, raiseConnectedEvent } from "@fluidframework/telemetry-utils";
28
+ import {
29
+ ChildLogger,
30
+ generateStack,
31
+ LoggingError,
32
+ loggerToMonitoringContext,
33
+ MonitoringContext,
34
+ raiseConnectedEvent,
35
+ TelemetryDataTag,
36
+ } from "@fluidframework/telemetry-utils";
29
37
  import { buildSnapshotTree } from "@fluidframework/driver-utils";
30
38
  import {
31
39
  IClientDetails,
@@ -37,14 +45,12 @@ import {
37
45
  IQuorumClients,
38
46
  } from "@fluidframework/protocol-definitions";
39
47
  import {
40
- BindState,
41
48
  CreateSummarizerNodeSource,
42
49
  IAttachMessage,
43
50
  IEnvelope,
44
51
  IFluidDataStoreContext,
45
52
  IFluidDataStoreChannel,
46
53
  IGarbageCollectionData,
47
- IGarbageCollectionDetailsBase,
48
54
  IInboundSignalMessage,
49
55
  ISummaryTreeWithStats,
50
56
  VisibilityState,
@@ -60,6 +66,7 @@ import {
60
66
  createResponseError,
61
67
  exceptionToResponse,
62
68
  requestFluidObject,
69
+ packagePathToTelemetryProperty,
63
70
  } from "@fluidframework/runtime-utils";
64
71
  import {
65
72
  IChannel,
@@ -67,12 +74,7 @@ import {
67
74
  IFluidDataStoreRuntimeEvents,
68
75
  IChannelFactory,
69
76
  } from "@fluidframework/datastore-definitions";
70
- import {
71
- GCDataBuilder,
72
- removeRouteFromAllNodes,
73
- unpackChildNodesGCDetails,
74
- unpackChildNodesUsedRoutes,
75
- } from "@fluidframework/garbage-collector";
77
+ import { GCDataBuilder, unpackChildNodesUsedRoutes } from "@fluidframework/garbage-collector";
76
78
  import { v4 as uuid } from "uuid";
77
79
  import { IChannelContext, summarizeChannel } from "./channelContext";
78
80
  import {
@@ -183,7 +185,6 @@ export class FluidDataStoreRuntime
183
185
  private readonly contextsDeferred = new Map<string, Deferred<IChannelContext>>();
184
186
  private readonly pendingAttach = new Map<string, IAttachMessage>();
185
187
 
186
- private bindState: BindState;
187
188
  private readonly deferredAttached = new Deferred<void>();
188
189
  private readonly localChannelContextQueue = new Map<string, LocalChannelContextBase>();
189
190
  private readonly notBoundedChannelContextSet = new Set<string>();
@@ -198,11 +199,17 @@ export class FluidDataStoreRuntime
198
199
  public readonly deltaManager: IDeltaManager<ISequencedDocumentMessage, IDocumentMessage>;
199
200
  private readonly quorum: IQuorumClients;
200
201
  private readonly audience: IAudience;
201
- public readonly logger: ITelemetryLogger;
202
+ private readonly mc: MonitoringContext;
203
+ public get logger(): ITelemetryLogger {
204
+ return this.mc.logger;
205
+ }
202
206
 
203
- // A map of child channel context ids to the their base GC details. This is used to initialize the GC state of the
204
- // channel contexts.
205
- private readonly channelsBaseGCDetails: LazyPromise<Map<string, IGarbageCollectionDetailsBase>>;
207
+ /**
208
+ * If the summarizer makes local changes, a telemetry event is logged. This has the potential to be very noisy.
209
+ * So, adding a count of how many telemetry events are logged per data store context. This can be
210
+ * controlled via feature flags.
211
+ */
212
+ private localChangesTelemetryCount: number;
206
213
 
207
214
  /**
208
215
  * Invokes the given callback and expects that no ops are submitted
@@ -243,9 +250,11 @@ export class FluidDataStoreRuntime
243
250
  0x30e /* Id cannot contain slashes. DataStoreContext should have validated this. */,
244
251
  );
245
252
 
246
- this.logger = ChildLogger.create(dataStoreContext.logger, "FluidDataStoreRuntime", {
247
- all: { dataStoreId: uuid() },
248
- });
253
+ this.mc = loggerToMonitoringContext(
254
+ ChildLogger.create(dataStoreContext.logger, "FluidDataStoreRuntime", {
255
+ all: { dataStoreId: uuid() },
256
+ }),
257
+ );
249
258
 
250
259
  this.id = dataStoreContext.id;
251
260
  this.options = dataStoreContext.options;
@@ -255,11 +264,6 @@ export class FluidDataStoreRuntime
255
264
 
256
265
  const tree = dataStoreContext.baseSnapshot;
257
266
 
258
- this.channelsBaseGCDetails = new LazyPromise(async () => {
259
- const baseGCDetails = await this.dataStoreContext.getBaseGCDetails();
260
- return unpackChildNodesGCDetails(baseGCDetails);
261
- });
262
-
263
267
  // Must always receive the data store type inside of the attributes
264
268
  if (tree?.trees !== undefined) {
265
269
  Object.keys(tree.trees).forEach((path) => {
@@ -316,7 +320,6 @@ export class FluidDataStoreRuntime
316
320
  this.dataStoreContext.getCreateChildSummarizerNodeFn(path, {
317
321
  type: CreateSummarizerNodeSource.FromSummary,
318
322
  }),
319
- async () => this.getChannelBaseGCDetails(path),
320
323
  );
321
324
  }
322
325
  const deferred = new Deferred<IChannelContext>();
@@ -337,8 +340,6 @@ export class FluidDataStoreRuntime
337
340
  }
338
341
 
339
342
  this.attachListener();
340
- // If exists on storage or loaded from a snapshot, it should already be bound.
341
- this.bindState = existing ? BindState.Bound : BindState.NotBound;
342
343
  this._attachState = dataStoreContext.attachState;
343
344
 
344
345
  /**
@@ -364,6 +365,10 @@ export class FluidDataStoreRuntime
364
365
  if (existing) {
365
366
  this.deferredAttached.resolve();
366
367
  }
368
+
369
+ // By default, a data store can log maximum 10 local changes telemetry in summarizer.
370
+ this.localChangesTelemetryCount =
371
+ this.mc.config.getNumber("Fluid.Telemetry.LocalChangesTelemetryCount") ?? 10;
367
372
  }
368
373
 
369
374
  public dispose(): void {
@@ -398,7 +403,10 @@ export class FluidDataStoreRuntime
398
403
 
399
404
  return { mimeType: "fluid/object", status: 200, value: channel };
400
405
  } catch (error) {
401
- this.logger.sendErrorEvent({ eventName: "GetChannelFailedInRequest" }, error);
406
+ this.mc.logger.sendErrorEvent(
407
+ { eventName: "GetChannelFailedInRequest" },
408
+ error,
409
+ );
402
410
 
403
411
  return createResponseError(500, `Failed to get Channel: ${error}`, request);
404
412
  }
@@ -461,6 +469,9 @@ export class FluidDataStoreRuntime
461
469
  this.contextsDeferred.set(id, deferred);
462
470
  }
463
471
 
472
+ // Channels (DDS) should not be created in summarizer client.
473
+ this.identifyLocalChangeInSummarizer("DDSCreatedInSummarizer", id, type);
474
+
464
475
  assert(!!context.channel, 0x17a /* "Channel should be loaded when created!!" */);
465
476
  return context.channel;
466
477
  }
@@ -522,7 +533,7 @@ export class FluidDataStoreRuntime
522
533
  handle.attachGraph();
523
534
  });
524
535
  this.pendingHandlesToMakeVisible.clear();
525
- this.bindToContext();
536
+ this.dataStoreContext.makeLocallyVisible();
526
537
  }
527
538
 
528
539
  /**
@@ -540,12 +551,7 @@ export class FluidDataStoreRuntime
540
551
  * 2. Attaching the graph if the data store becomes attached.
541
552
  */
542
553
  public bindToContext() {
543
- if (this.bindState !== BindState.NotBound) {
544
- return;
545
- }
546
- this.bindState = BindState.Binding;
547
- this.dataStoreContext.bindToContext();
548
- this.bindState = BindState.Bound;
554
+ this.makeVisibleAndAttachGraph();
549
555
  }
550
556
 
551
557
  public bind(handle: IFluidHandle): void {
@@ -600,12 +606,7 @@ export class FluidDataStoreRuntime
600
606
  );
601
607
  this.pendingAttach.delete(id);
602
608
  } else {
603
- assert(
604
- !this.contexts.has(id),
605
- 0x17d /* `Unexpected attach channel OP,
606
- is in pendingAttach set: ${this.pendingAttach.has(id)},
607
- is local channel contexts: ${this.contexts.get(id) instanceof LocalChannelContextBase}` */,
608
- );
609
+ assert(!this.contexts.has(id), 0x17d /* "Unexpected attach channel OP" */);
609
610
 
610
611
  const flatBlobs = new Map<string, ArrayBufferLike>();
611
612
  const snapshotTree = buildSnapshotTree(
@@ -631,7 +632,6 @@ export class FluidDataStoreRuntime
631
632
  sequenceNumber: message.sequenceNumber,
632
633
  snapshot: attachMessage.snapshot,
633
634
  }),
634
- async () => this.getChannelBaseGCDetails(id),
635
635
  attachMessage.type,
636
636
  );
637
637
 
@@ -780,34 +780,6 @@ export class FluidDataStoreRuntime
780
780
  this.dataStoreContext.addedGCOutboundReference?.(srcHandle, outboundHandle);
781
781
  }
782
782
 
783
- /**
784
- * Returns the base GC details for the channel with the given id. This is used to initialize its GC state.
785
- * @param channelId - The id of the channel context that is asked for the initial GC details.
786
- * @returns the requested channel's base GC details.
787
- */
788
- private async getChannelBaseGCDetails(
789
- channelId: string,
790
- ): Promise<IGarbageCollectionDetailsBase> {
791
- let channelBaseGCDetails = (await this.channelsBaseGCDetails).get(channelId);
792
- if (channelBaseGCDetails === undefined) {
793
- channelBaseGCDetails = {};
794
- } else if (channelBaseGCDetails.gcData?.gcNodes !== undefined) {
795
- // Note: if the child channel has an explicit handle route to its parent, it will be removed here and
796
- // expected to be added back by the parent when getGCData is called.
797
- removeRouteFromAllNodes(channelBaseGCDetails.gcData.gcNodes, this.absolutePath);
798
- }
799
-
800
- // Currently, channel context's are always considered used. So, it there are no used routes for it, we still
801
- // need to mark it as used. Add self-route (empty string) to the channel context's used routes.
802
- if (
803
- channelBaseGCDetails.usedRoutes === undefined ||
804
- channelBaseGCDetails.usedRoutes.length === 0
805
- ) {
806
- channelBaseGCDetails.usedRoutes = [""];
807
- }
808
- return channelBaseGCDetails;
809
- }
810
-
811
783
  /**
812
784
  * Returns a summary at the current sequence number.
813
785
  * @param fullTree - true to bypass optimizations and force a full summary tree
@@ -1109,6 +1081,42 @@ export class FluidDataStoreRuntime
1109
1081
  throw new LoggingError("Runtime is closed");
1110
1082
  }
1111
1083
  }
1084
+
1085
+ /**
1086
+ * Summarizer client should not have local changes. These changes can become part of the summary and can break
1087
+ * eventual consistency. For example, the next summary (say at ref seq# 100) may contain these changes whereas
1088
+ * other clients that are up-to-date till seq# 100 may not have them yet.
1089
+ */
1090
+ private identifyLocalChangeInSummarizer(
1091
+ eventName: string,
1092
+ channelId: string,
1093
+ channelType: string,
1094
+ ) {
1095
+ if (this.clientDetails.type !== "summarizer" || this.localChangesTelemetryCount <= 0) {
1096
+ return;
1097
+ }
1098
+
1099
+ // Log a telemetry if there are local changes in the summarizer. This will give us data on how often
1100
+ // this is happening and which data stores do this. The eventual goal is to disallow local changes
1101
+ // in the summarizer and the data will help us plan this.
1102
+ this.mc.logger.sendTelemetryEvent({
1103
+ eventName,
1104
+ channelType,
1105
+ channelId: {
1106
+ value: channelId,
1107
+ tag: TelemetryDataTag.CodeArtifact,
1108
+ },
1109
+ fluidDataStoreId: {
1110
+ value: this.id,
1111
+ tag: TelemetryDataTag.CodeArtifact,
1112
+ },
1113
+ fluidDataStorePackagePath: packagePathToTelemetryProperty(
1114
+ this.dataStoreContext.packagePath,
1115
+ ),
1116
+ stack: generateStack(),
1117
+ });
1118
+ this.localChangesTelemetryCount--;
1119
+ }
1112
1120
  }
1113
1121
 
1114
1122
  /**
@@ -6,4 +6,4 @@
6
6
  */
7
7
 
8
8
  export const pkgName = "@fluidframework/datastore";
9
- export const pkgVersion = "2.0.0-internal.3.1.0";
9
+ export const pkgVersion = "2.0.0-internal.3.2.1";
@@ -20,7 +20,6 @@ import {
20
20
  CreateChildSummarizerNodeFn,
21
21
  IFluidDataStoreContext,
22
22
  IGarbageCollectionData,
23
- IGarbageCollectionDetailsBase,
24
23
  ISummarizeInternalResult,
25
24
  ISummarizeResult,
26
25
  ISummarizerNodeWithGC,
@@ -63,7 +62,6 @@ export class RemoteChannelContext implements IChannelContext {
63
62
  private readonly registry: ISharedObjectRegistry,
64
63
  extraBlobs: Map<string, ArrayBufferLike> | undefined,
65
64
  createSummarizerNode: CreateChildSummarizerNodeFn,
66
- getBaseGCDetails: () => Promise<IGarbageCollectionDetailsBase>,
67
65
  private readonly attachMessageType?: string,
68
66
  ) {
69
67
  assert(!this.id.includes("/"), 0x310 /* Channel context ID cannot contain slashes */);
@@ -91,7 +89,6 @@ export class RemoteChannelContext implements IChannelContext {
91
89
  this.summarizerNode = createSummarizerNode(
92
90
  thisSummarizeInternal,
93
91
  async (fullGC?: boolean) => this.getGCDataInternal(fullGC),
94
- async () => getBaseGCDetails(),
95
92
  );
96
93
 
97
94
  this.thresholdOpsCounter = new ThresholdCounter(