@fluidframework/container-runtime 2.11.0 → 2.13.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 (119) hide show
  1. package/CHANGELOG.md +41 -0
  2. package/api-report/container-runtime.legacy.alpha.api.md +17 -15
  3. package/container-runtime.test-files.tar +0 -0
  4. package/dist/blobManager/blobManagerSnapSum.js.map +1 -1
  5. package/dist/channelCollection.js.map +1 -1
  6. package/dist/containerRuntime.d.ts +38 -5
  7. package/dist/containerRuntime.d.ts.map +1 -1
  8. package/dist/containerRuntime.js +28 -7
  9. package/dist/containerRuntime.js.map +1 -1
  10. package/dist/gc/garbageCollection.d.ts.map +1 -1
  11. package/dist/gc/garbageCollection.js.map +1 -1
  12. package/dist/gc/gcConfigs.js +1 -1
  13. package/dist/gc/gcConfigs.js.map +1 -1
  14. package/dist/gc/gcHelpers.js.map +1 -1
  15. package/dist/gc/gcReferenceGraphAlgorithm.js.map +1 -1
  16. package/dist/index.d.ts +1 -1
  17. package/dist/index.d.ts.map +1 -1
  18. package/dist/index.js.map +1 -1
  19. package/dist/opLifecycle/opDecompressor.js +0 -1
  20. package/dist/opLifecycle/opDecompressor.js.map +1 -1
  21. package/dist/opLifecycle/opSplitter.js +0 -1
  22. package/dist/opLifecycle/opSplitter.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/pendingStateManager.d.ts +4 -0
  27. package/dist/pendingStateManager.d.ts.map +1 -1
  28. package/dist/pendingStateManager.js +31 -1
  29. package/dist/pendingStateManager.js.map +1 -1
  30. package/dist/scheduleManager.js +0 -2
  31. package/dist/scheduleManager.js.map +1 -1
  32. package/dist/summary/runWhileConnectedCoordinator.d.ts +2 -1
  33. package/dist/summary/runWhileConnectedCoordinator.d.ts.map +1 -1
  34. package/dist/summary/runWhileConnectedCoordinator.js.map +1 -1
  35. package/dist/summary/runningSummarizer.d.ts +8 -1
  36. package/dist/summary/runningSummarizer.d.ts.map +1 -1
  37. package/dist/summary/runningSummarizer.js +70 -8
  38. package/dist/summary/runningSummarizer.js.map +1 -1
  39. package/dist/summary/summarizer.d.ts +5 -2
  40. package/dist/summary/summarizer.d.ts.map +1 -1
  41. package/dist/summary/summarizer.js +39 -6
  42. package/dist/summary/summarizer.js.map +1 -1
  43. package/dist/summary/summarizerTypes.d.ts +8 -4
  44. package/dist/summary/summarizerTypes.d.ts.map +1 -1
  45. package/dist/summary/summarizerTypes.js.map +1 -1
  46. package/dist/summary/summaryCollection.js +0 -2
  47. package/dist/summary/summaryCollection.js.map +1 -1
  48. package/dist/summary/summaryManager.d.ts +5 -2
  49. package/dist/summary/summaryManager.d.ts.map +1 -1
  50. package/dist/summary/summaryManager.js +23 -6
  51. package/dist/summary/summaryManager.js.map +1 -1
  52. package/lib/blobManager/blobManagerSnapSum.js.map +1 -1
  53. package/lib/channelCollection.js.map +1 -1
  54. package/lib/containerRuntime.d.ts +38 -5
  55. package/lib/containerRuntime.d.ts.map +1 -1
  56. package/lib/containerRuntime.js +28 -7
  57. package/lib/containerRuntime.js.map +1 -1
  58. package/lib/gc/garbageCollection.d.ts.map +1 -1
  59. package/lib/gc/garbageCollection.js.map +1 -1
  60. package/lib/gc/gcConfigs.js +1 -1
  61. package/lib/gc/gcConfigs.js.map +1 -1
  62. package/lib/gc/gcHelpers.js.map +1 -1
  63. package/lib/gc/gcReferenceGraphAlgorithm.js.map +1 -1
  64. package/lib/index.d.ts +1 -1
  65. package/lib/index.d.ts.map +1 -1
  66. package/lib/index.js.map +1 -1
  67. package/lib/opLifecycle/opDecompressor.js +0 -1
  68. package/lib/opLifecycle/opDecompressor.js.map +1 -1
  69. package/lib/opLifecycle/opSplitter.js +0 -1
  70. package/lib/opLifecycle/opSplitter.js.map +1 -1
  71. package/lib/packageVersion.d.ts +1 -1
  72. package/lib/packageVersion.js +1 -1
  73. package/lib/packageVersion.js.map +1 -1
  74. package/lib/pendingStateManager.d.ts +4 -0
  75. package/lib/pendingStateManager.d.ts.map +1 -1
  76. package/lib/pendingStateManager.js +29 -0
  77. package/lib/pendingStateManager.js.map +1 -1
  78. package/lib/scheduleManager.js +0 -2
  79. package/lib/scheduleManager.js.map +1 -1
  80. package/lib/summary/runWhileConnectedCoordinator.d.ts +2 -1
  81. package/lib/summary/runWhileConnectedCoordinator.d.ts.map +1 -1
  82. package/lib/summary/runWhileConnectedCoordinator.js.map +1 -1
  83. package/lib/summary/runningSummarizer.d.ts +8 -1
  84. package/lib/summary/runningSummarizer.d.ts.map +1 -1
  85. package/lib/summary/runningSummarizer.js +70 -8
  86. package/lib/summary/runningSummarizer.js.map +1 -1
  87. package/lib/summary/summarizer.d.ts +5 -2
  88. package/lib/summary/summarizer.d.ts.map +1 -1
  89. package/lib/summary/summarizer.js +39 -6
  90. package/lib/summary/summarizer.js.map +1 -1
  91. package/lib/summary/summarizerTypes.d.ts +8 -4
  92. package/lib/summary/summarizerTypes.d.ts.map +1 -1
  93. package/lib/summary/summarizerTypes.js.map +1 -1
  94. package/lib/summary/summaryCollection.js +0 -2
  95. package/lib/summary/summaryCollection.js.map +1 -1
  96. package/lib/summary/summaryManager.d.ts +5 -2
  97. package/lib/summary/summaryManager.d.ts.map +1 -1
  98. package/lib/summary/summaryManager.js +23 -6
  99. package/lib/summary/summaryManager.js.map +1 -1
  100. package/package.json +20 -20
  101. package/src/blobManager/blobManagerSnapSum.ts +1 -1
  102. package/src/channelCollection.ts +1 -1
  103. package/src/containerRuntime.ts +84 -24
  104. package/src/gc/garbageCollection.ts +2 -1
  105. package/src/gc/gcConfigs.ts +1 -1
  106. package/src/gc/gcHelpers.ts +2 -2
  107. package/src/gc/gcReferenceGraphAlgorithm.ts +1 -1
  108. package/src/index.ts +1 -0
  109. package/src/opLifecycle/opDecompressor.ts +1 -1
  110. package/src/opLifecycle/opSplitter.ts +1 -1
  111. package/src/packageVersion.ts +1 -1
  112. package/src/pendingStateManager.ts +38 -0
  113. package/src/scheduleManager.ts +2 -2
  114. package/src/summary/runWhileConnectedCoordinator.ts +2 -5
  115. package/src/summary/runningSummarizer.ts +82 -11
  116. package/src/summary/summarizer.ts +49 -10
  117. package/src/summary/summarizerTypes.ts +11 -4
  118. package/src/summary/summaryCollection.ts +2 -2
  119. package/src/summary/summaryManager.ts +30 -10
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fluidframework/container-runtime",
3
- "version": "2.11.0",
3
+ "version": "2.13.0",
4
4
  "description": "Fluid container runtime",
5
5
  "homepage": "https://fluidframework.com",
6
6
  "repository": {
@@ -129,39 +129,39 @@
129
129
  "temp-directory": "nyc/.nyc_output"
130
130
  },
131
131
  "dependencies": {
132
- "@fluid-internal/client-utils": "~2.11.0",
133
- "@fluidframework/container-definitions": "~2.11.0",
134
- "@fluidframework/container-runtime-definitions": "~2.11.0",
135
- "@fluidframework/core-interfaces": "~2.11.0",
136
- "@fluidframework/core-utils": "~2.11.0",
137
- "@fluidframework/datastore": "~2.11.0",
138
- "@fluidframework/driver-definitions": "~2.11.0",
139
- "@fluidframework/driver-utils": "~2.11.0",
140
- "@fluidframework/id-compressor": "~2.11.0",
141
- "@fluidframework/runtime-definitions": "~2.11.0",
142
- "@fluidframework/runtime-utils": "~2.11.0",
143
- "@fluidframework/telemetry-utils": "~2.11.0",
132
+ "@fluid-internal/client-utils": "~2.13.0",
133
+ "@fluidframework/container-definitions": "~2.13.0",
134
+ "@fluidframework/container-runtime-definitions": "~2.13.0",
135
+ "@fluidframework/core-interfaces": "~2.13.0",
136
+ "@fluidframework/core-utils": "~2.13.0",
137
+ "@fluidframework/datastore": "~2.13.0",
138
+ "@fluidframework/driver-definitions": "~2.13.0",
139
+ "@fluidframework/driver-utils": "~2.13.0",
140
+ "@fluidframework/id-compressor": "~2.13.0",
141
+ "@fluidframework/runtime-definitions": "~2.13.0",
142
+ "@fluidframework/runtime-utils": "~2.13.0",
143
+ "@fluidframework/telemetry-utils": "~2.13.0",
144
144
  "@tylerbu/sorted-btree-es6": "^1.8.0",
145
145
  "double-ended-queue": "^2.1.0-0",
146
146
  "lz4js": "^0.2.0",
147
147
  "uuid": "^9.0.0"
148
148
  },
149
149
  "devDependencies": {
150
- "@arethetypeswrong/cli": "^0.16.4",
150
+ "@arethetypeswrong/cli": "^0.17.1",
151
151
  "@biomejs/biome": "~1.9.3",
152
- "@fluid-internal/mocha-test-setup": "~2.11.0",
153
- "@fluid-private/stochastic-test-utils": "~2.11.0",
154
- "@fluid-private/test-pairwise-generator": "~2.11.0",
152
+ "@fluid-internal/mocha-test-setup": "~2.13.0",
153
+ "@fluid-private/stochastic-test-utils": "~2.13.0",
154
+ "@fluid-private/test-pairwise-generator": "~2.13.0",
155
155
  "@fluid-tools/benchmark": "^0.50.0",
156
156
  "@fluid-tools/build-cli": "^0.51.0",
157
157
  "@fluidframework/build-common": "^2.0.3",
158
158
  "@fluidframework/build-tools": "^0.51.0",
159
- "@fluidframework/container-runtime-previous": "npm:@fluidframework/container-runtime@2.10.0",
159
+ "@fluidframework/container-runtime-previous": "npm:@fluidframework/container-runtime@2.12.0",
160
160
  "@fluidframework/eslint-config-fluid": "^5.6.0",
161
- "@fluidframework/test-runtime-utils": "~2.11.0",
161
+ "@fluidframework/test-runtime-utils": "~2.13.0",
162
162
  "@microsoft/api-extractor": "7.47.8",
163
163
  "@types/double-ended-queue": "^2.1.0",
164
- "@types/mocha": "^9.1.1",
164
+ "@types/mocha": "^10.0.10",
165
165
  "@types/node": "^18.19.0",
166
166
  "@types/sinon": "^17.0.3",
167
167
  "@types/uuid": "^9.0.2",
@@ -47,7 +47,7 @@ const loadV1 = async (
47
47
  return {};
48
48
  }
49
49
  let redirectTableEntries: [string, string][] = [];
50
- const tableId = blobsTree.blobs[redirectTableBlobName];
50
+ const tableId: string | undefined = blobsTree.blobs[redirectTableBlobName];
51
51
  if (tableId) {
52
52
  redirectTableEntries = await readAndParse(context.storage, tableId);
53
53
  }
@@ -1551,7 +1551,7 @@ export function getSummaryForDatastores(
1551
1551
  }
1552
1552
 
1553
1553
  if (rootHasIsolatedChannels(metadata)) {
1554
- const datastoresSnapshot = snapshot.trees[channelsTreeName];
1554
+ const datastoresSnapshot: ISnapshotTree | undefined = snapshot.trees[channelsTreeName];
1555
1555
  assert(!!datastoresSnapshot, 0x168 /* Expected tree in snapshot not found */);
1556
1556
  return datastoresSnapshot;
1557
1557
  } else {
@@ -64,6 +64,7 @@ import {
64
64
  ISequencedDocumentMessage,
65
65
  ISignalMessage,
66
66
  type ISummaryContext,
67
+ type SummaryObject,
67
68
  } from "@fluidframework/driver-definitions/internal";
68
69
  import { readAndParse } from "@fluidframework/driver-utils/internal";
69
70
  import type { IIdCompressor } from "@fluidframework/id-compressor";
@@ -218,7 +219,6 @@ import {
218
219
  ISubmitSummaryOptions,
219
220
  ISummarizeResults,
220
221
  ISummarizer,
221
- ISummarizerEvents,
222
222
  ISummarizerInternalsProvider,
223
223
  ISummarizerRuntime,
224
224
  ISummaryMetadataMessage,
@@ -475,6 +475,8 @@ export interface IContainerRuntimeOptions {
475
475
  * send all operations to the driver layer, while in TurnBased the operations will be buffered
476
476
  * and then sent them as a single batch at the end of the turn.
477
477
  * By default, flush mode is TurnBased.
478
+ *
479
+ * @deprecated Only the default value TurnBased is supported. This option will be removed in the future.
478
480
  */
479
481
  readonly flushMode?: FlushMode;
480
482
  /**
@@ -516,9 +518,10 @@ export interface IContainerRuntimeOptions {
516
518
  /**
517
519
  * If enabled, the runtime will group messages within a batch into a single
518
520
  * message to be sent to the service.
519
- * The grouping an ungrouping of such messages is handled by the "OpGroupingManager".
521
+ * The grouping and ungrouping of such messages is handled by the "OpGroupingManager".
520
522
  *
521
523
  * By default, the feature is enabled.
524
+ * @deprecated The ability to disable Grouped Batching is deprecated and will be removed in v2.20.0. This feature is required for the proper functioning of the Fluid Framework.
522
525
  */
523
526
  readonly enableGroupedBatching?: boolean;
524
527
 
@@ -532,6 +535,31 @@ export interface IContainerRuntimeOptions {
532
535
  readonly explicitSchemaControl?: boolean;
533
536
  }
534
537
 
538
+ /**
539
+ * Internal extension of @see IContainerRuntimeOptions
540
+ *
541
+ * These options are not available to consumers when creating a new container runtime,
542
+ * but we do need to expose them for internal use, e.g. when configuring the container runtime
543
+ * to ensure compability with older versions.
544
+ *
545
+ * @internal
546
+ */
547
+ export interface IContainerRuntimeOptionsInternal extends IContainerRuntimeOptions {
548
+ /**
549
+ * Sets the flush mode for the runtime. In Immediate flush mode the runtime will immediately
550
+ * send all operations to the driver layer, while in TurnBased the operations will be buffered
551
+ * and then sent them as a single batch at the end of the turn.
552
+ * By default, flush mode is TurnBased.
553
+ */
554
+ readonly flushMode?: FlushMode;
555
+
556
+ /**
557
+ * Allows Grouped Batching to be disabled by setting to false (default is true).
558
+ * In that case, batched messages will be sent individually (but still all at the same time).
559
+ */
560
+ readonly enableGroupedBatching?: boolean;
561
+ }
562
+
535
563
  /**
536
564
  * Error responses when requesting a deleted object will have this header set to true
537
565
  * @legacy
@@ -836,11 +864,15 @@ export async function loadContainerRuntime(
836
864
  /**
837
865
  * Represents the runtime of the container. Contains helper functions/state of the container.
838
866
  * It will define the store level mappings.
867
+ *
868
+ * @deprecated To be removed from the Legacy-Alpha API in version 2.20.0.
869
+ * Use the loadContainerRuntime function and interfaces IContainerRuntime / IRuntime instead.
870
+ *
839
871
  * @legacy
840
872
  * @alpha
841
873
  */
842
874
  export class ContainerRuntime
843
- extends TypedEventEmitter<IContainerRuntimeEvents & ISummarizerEvents>
875
+ extends TypedEventEmitter<IContainerRuntimeEvents>
844
876
  implements
845
877
  IContainerRuntime,
846
878
  IRuntime,
@@ -867,7 +899,7 @@ export class ContainerRuntime
867
899
  context: IContainerContext;
868
900
  registryEntries: NamedFluidDataStoreRegistryEntries;
869
901
  existing: boolean;
870
- runtimeOptions?: IContainerRuntimeOptions;
902
+ runtimeOptions?: IContainerRuntimeOptions; // May also include options from IContainerRuntimeOptionsInternal
871
903
  containerScope?: FluidObject;
872
904
  containerRuntimeCtor?: typeof ContainerRuntime;
873
905
  /** @deprecated Will be removed once Loader LTS version is "2.0.0-internal.7.0.0". Migrate all usage of IFluidRouter to the "entryPoint" pattern. Refer to Removing-IFluidRouter.md */
@@ -914,7 +946,7 @@ export class ContainerRuntime
914
946
  chunkSizeInBytes = defaultChunkSizeInBytes,
915
947
  enableGroupedBatching = true,
916
948
  explicitSchemaControl = false,
917
- } = runtimeOptions;
949
+ }: IContainerRuntimeOptionsInternal = runtimeOptions;
918
950
 
919
951
  const registry = new FluidDataStoreRegistry(registryEntries);
920
952
 
@@ -1093,6 +1125,21 @@ export class ContainerRuntime
1093
1125
 
1094
1126
  const featureGatesForTelemetry: Record<string, boolean | number | undefined> = {};
1095
1127
 
1128
+ // Make sure we've got all the options including internal ones
1129
+ const internalRuntimeOptions: Readonly<Required<IContainerRuntimeOptionsInternal>> = {
1130
+ summaryOptions,
1131
+ gcOptions,
1132
+ loadSequenceNumberVerification,
1133
+ flushMode,
1134
+ compressionOptions,
1135
+ maxBatchSizeInBytes,
1136
+ chunkSizeInBytes,
1137
+ // Requires<> drops undefined from IdCompressorType
1138
+ enableRuntimeIdCompressor: enableRuntimeIdCompressor as "on" | "delayed",
1139
+ enableGroupedBatching,
1140
+ explicitSchemaControl,
1141
+ };
1142
+
1096
1143
  const runtime = new containerRuntimeCtor(
1097
1144
  context,
1098
1145
  registry,
@@ -1100,19 +1147,7 @@ export class ContainerRuntime
1100
1147
  electedSummarizerData,
1101
1148
  chunks ?? [],
1102
1149
  aliases ?? [],
1103
- {
1104
- summaryOptions,
1105
- gcOptions,
1106
- loadSequenceNumberVerification,
1107
- flushMode,
1108
- compressionOptions,
1109
- maxBatchSizeInBytes,
1110
- chunkSizeInBytes,
1111
- // Requires<> drops undefined from IdCompressorType
1112
- enableRuntimeIdCompressor: enableRuntimeIdCompressor as "on" | "delayed",
1113
- enableGroupedBatching,
1114
- explicitSchemaControl,
1115
- },
1150
+ internalRuntimeOptions,
1116
1151
  containerScope,
1117
1152
  logger,
1118
1153
  existing,
@@ -1474,6 +1509,11 @@ export class ContainerRuntime
1474
1509
  expiry: { policy: "absolute", durationMs: 60000 },
1475
1510
  });
1476
1511
 
1512
+ /**
1513
+ * The options to apply to this ContainerRuntime instance (including internal options hidden from the public API)
1514
+ */
1515
+ private readonly runtimeOptions: Readonly<Required<IContainerRuntimeOptionsInternal>>;
1516
+
1477
1517
  /***/
1478
1518
  protected constructor(
1479
1519
  context: IContainerContext,
@@ -1482,7 +1522,10 @@ export class ContainerRuntime
1482
1522
  electedSummarizerData: ISerializedElection | undefined,
1483
1523
  chunks: [string, string[]][],
1484
1524
  dataStoreAliasMap: [string, string][],
1485
- private readonly runtimeOptions: Readonly<Required<IContainerRuntimeOptions>>,
1525
+ runtimeOptions: Readonly<
1526
+ Required<Omit<IContainerRuntimeOptions, "flushMode" | "enableGroupedBatching">> &
1527
+ IContainerRuntimeOptions // Let flushMode and enabledGroupedBatching be optional now since they're soon to be removed
1528
+ >,
1486
1529
  private readonly containerScope: FluidObject,
1487
1530
  // Create a custom ITelemetryBaseLogger to output telemetry events.
1488
1531
  public readonly baseLogger: ITelemetryBaseLogger,
@@ -1527,6 +1570,12 @@ export class ContainerRuntime
1527
1570
  snapshotWithContents,
1528
1571
  } = context;
1529
1572
 
1573
+ // Backfill in defaults for the internal runtimeOptions, since they may not be present on the provided runtimeOptions object
1574
+ this.runtimeOptions = {
1575
+ flushMode: defaultFlushMode,
1576
+ enableGroupedBatching: true,
1577
+ ...runtimeOptions,
1578
+ };
1530
1579
  this.logger = createChildLogger({ logger: this.baseLogger });
1531
1580
  this.mc = createChildMonitoringContext({
1532
1581
  logger: this.logger,
@@ -1697,14 +1746,15 @@ export class ContainerRuntime
1697
1746
  this.defaultMaxConsecutiveReconnects;
1698
1747
 
1699
1748
  if (
1700
- runtimeOptions.flushMode === (FlushModeExperimental.Async as unknown as FlushMode) &&
1749
+ this.runtimeOptions.flushMode ===
1750
+ (FlushModeExperimental.Async as unknown as FlushMode) &&
1701
1751
  supportedFeatures?.get("referenceSequenceNumbers") !== true
1702
1752
  ) {
1703
1753
  // The loader does not support reference sequence numbers, falling back on FlushMode.TurnBased
1704
1754
  this.mc.logger.sendErrorEvent({ eventName: "FlushModeFallback" });
1705
1755
  this._flushMode = FlushMode.TurnBased;
1706
1756
  } else {
1707
- this._flushMode = runtimeOptions.flushMode;
1757
+ this._flushMode = this.runtimeOptions.flushMode;
1708
1758
  }
1709
1759
  this.offlineEnabled =
1710
1760
  this.mc.config.getBoolean("Fluid.Container.enableOfflineLoad") ?? false;
@@ -2015,9 +2065,19 @@ export class ContainerRuntime
2015
2065
  initialDelayMs: this.initialSummarizerDelayMs,
2016
2066
  },
2017
2067
  );
2018
- this.summaryManager.on("summarize", (eventProps) => {
2019
- this.emit("summarize", eventProps);
2068
+ // Forward events from SummaryManager
2069
+ [
2070
+ "summarize",
2071
+ "summarizeAllAttemptsFailed",
2072
+ "summarizerStop",
2073
+ "summarizerStart",
2074
+ "summarizerStartupFailed",
2075
+ ].forEach((eventName) => {
2076
+ this.summaryManager?.on(eventName, (...args: any[]) => {
2077
+ this.emit(eventName, ...args);
2078
+ });
2020
2079
  });
2080
+
2021
2081
  this.summaryManager.start();
2022
2082
  }
2023
2083
  }
@@ -4111,7 +4171,7 @@ export class ContainerRuntime
4111
4171
  // Counting dataStores and handles
4112
4172
  // Because handles are unchanged dataStores in the current logic,
4113
4173
  // summarized dataStore count is total dataStore count minus handle count
4114
- const dataStoreTree = summaryTree.tree[channelsTreeName];
4174
+ const dataStoreTree: SummaryObject | undefined = summaryTree.tree[channelsTreeName];
4115
4175
 
4116
4176
  assert(dataStoreTree.type === SummaryType.Tree, 0x1fc /* "summary is not a tree" */);
4117
4177
  const handleCount = Object.values(dataStoreTree.tree).filter(
@@ -5,6 +5,7 @@
5
5
 
6
6
  import { IRequest } from "@fluidframework/core-interfaces";
7
7
  import { assert, LazyPromise, Timer } from "@fluidframework/core-utils/internal";
8
+ import type { ISnapshotTree } from "@fluidframework/driver-definitions/internal";
8
9
  import {
9
10
  IGarbageCollectionDetailsBase,
10
11
  ISummarizeResult,
@@ -226,7 +227,7 @@ export class GarbageCollector implements IGarbageCollector {
226
227
 
227
228
  try {
228
229
  // For newer documents, GC data should be present in the GC tree in the root of the snapshot.
229
- const gcSnapshotTree = baseSnapshot.trees[gcTreeKey];
230
+ const gcSnapshotTree: ISnapshotTree | undefined = baseSnapshot.trees[gcTreeKey];
230
231
  if (gcSnapshotTree === undefined) {
231
232
  // back-compat - Older documents get their gc data reset for simplicity as there are few of them
232
233
  // incremental gc summary will not work with older gc data as well
@@ -87,7 +87,7 @@ export function generateGCConfigs(
87
87
  tombstoneTimeoutMs =
88
88
  testOverrideTombstoneTimeoutMs ?? computeTombstoneTimeout(sessionExpiryTimeoutMs);
89
89
 
90
- const gcGeneration = createParams.gcOptions[gcGenerationOptionName];
90
+ const gcGeneration = createParams.gcOptions?.[gcGenerationOptionName];
91
91
  if (gcGeneration !== undefined) {
92
92
  persistedGcFeatureMatrix = { gcGeneration };
93
93
  }
@@ -109,7 +109,7 @@ export function concatGarbageCollectionStates(
109
109
  }
110
110
 
111
111
  for (const [nodeId, nodeData] of Object.entries(gcState2.gcNodes)) {
112
- let combineNodeData = combinedGCNodes[nodeId];
112
+ let combineNodeData: IGarbageCollectionNodeData | undefined = combinedGCNodes[nodeId];
113
113
  if (combineNodeData === undefined) {
114
114
  combineNodeData = {
115
115
  outboundRoutes: Array.from(nodeData.outboundRoutes),
@@ -202,7 +202,7 @@ export async function getGCDataFromSnapshot(
202
202
  continue;
203
203
  }
204
204
 
205
- const blobId = gcSnapshotTree.blobs[key];
205
+ const blobId: string | undefined = gcSnapshotTree.blobs[key];
206
206
  if (blobId === undefined) {
207
207
  continue;
208
208
  }
@@ -31,7 +31,7 @@ export function runGarbageCollection(
31
31
 
32
32
  // Get the node for the referenced id and add its outbound routes to referencedIds since they are
33
33
  // also referenced.
34
- const routes = referenceGraph[id];
34
+ const routes: string[] | undefined = referenceGraph[id];
35
35
  if (routes !== undefined) {
36
36
  referencedIds.push(...routes);
37
37
  }
package/src/index.ts CHANGED
@@ -10,6 +10,7 @@ export {
10
10
  ISummaryConfigurationDisableSummarizer,
11
11
  ISummaryConfigurationDisableHeuristics,
12
12
  IContainerRuntimeOptions,
13
+ IContainerRuntimeOptionsInternal,
13
14
  loadContainerRuntime,
14
15
  LoadContainerRuntimeParams,
15
16
  agentSchedulerId,
@@ -168,7 +168,7 @@ const newMessage = (
168
168
  contents,
169
169
  compression: undefined,
170
170
  // TODO: It should already be the case that we're not modifying any metadata, not clear if/why this shallow clone should be required.
171
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
171
+
172
172
  metadata:
173
173
  originalMessage.metadata === undefined
174
174
  ? undefined
@@ -190,7 +190,7 @@ export class OpSplitter {
190
190
  const contents: IChunkedContents = message.contents;
191
191
 
192
192
  // TODO: Verify whether this should be able to handle server-generated ops (with null clientId)
193
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
193
+
194
194
  const clientId = message.clientId as string;
195
195
  const chunkedContent = contents.contents;
196
196
  this.addChunk(clientId, chunkedContent, message);
@@ -6,4 +6,4 @@
6
6
  */
7
7
 
8
8
  export const pkgName = "@fluidframework/container-runtime";
9
- export const pkgVersion = "2.11.0";
9
+ export const pkgVersion = "2.13.0";
@@ -131,6 +131,28 @@ function scrubAndStringify(
131
131
  return JSON.stringify(scrubbed);
132
132
  }
133
133
 
134
+ /**
135
+ * @returns The index where the strings diverge, and the character at that index in each string (or undefined if not applicable)
136
+ */
137
+ export function findFirstCharacterMismatched(
138
+ a: string,
139
+ b: string,
140
+ ): [index: number, charA?: string, charB?: string] {
141
+ const minLength = Math.min(a.length, b.length);
142
+ for (let i = 0; i < minLength; i++) {
143
+ if (a[i] !== b[i]) {
144
+ return [i, a[i], b[i]];
145
+ }
146
+ }
147
+
148
+ // Since we didn't return in the loop, the shorter string must be a prefix of the other.
149
+ // If they're the same length, return -1 to indicate they're identical.
150
+ // Otherwise, the next character of the longer one is where they differ. No need to return that next character.
151
+ return a.length === b.length
152
+ ? [-1, undefined, undefined]
153
+ : [minLength, a[minLength], b[minLength]];
154
+ }
155
+
134
156
  function withoutLocalOpMetadata(message: IPendingMessage): IPendingMessage {
135
157
  return {
136
158
  ...message,
@@ -459,7 +481,17 @@ export class PendingStateManager implements IDisposable {
459
481
  const messageContent = buildPendingMessageContent(message);
460
482
 
461
483
  // Stringified content should match
484
+ // If it doesn't, collect as much info about the difference as possible (privacy-wise) and log it
462
485
  if (pendingMessage.content !== messageContent) {
486
+ const [pendingLength, incomingLength] = [
487
+ pendingMessage.content.length,
488
+ messageContent.length,
489
+ ];
490
+ const [mismatchStartIndex, pendingChar, incomingChar] = findFirstCharacterMismatched(
491
+ pendingMessage.content,
492
+ messageContent,
493
+ );
494
+
463
495
  const pendingContentObj = JSON.parse(
464
496
  pendingMessage.content,
465
497
  ) as LocalContainerRuntimeMessage;
@@ -467,6 +499,7 @@ export class PendingStateManager implements IDisposable {
467
499
  messageContent,
468
500
  ) as InboundContainerRuntimeMessage;
469
501
 
502
+ // Compare inner contents object, since that both should be { type, contents }
470
503
  const contentsMatch =
471
504
  pendingContentObj.contents === incomingContentObj.contents ||
472
505
  (pendingContentObj.contents !== undefined &&
@@ -480,6 +513,11 @@ export class PendingStateManager implements IDisposable {
480
513
  pendingContentScrubbed: scrubAndStringify(pendingContentObj),
481
514
  incomingContentScrubbed: scrubAndStringify(incomingContentObj),
482
515
  contentsMatch,
516
+ pendingLength,
517
+ incomingLength,
518
+ mismatchStartIndex,
519
+ pendingChar,
520
+ incomingChar,
483
521
  },
484
522
  });
485
523
 
@@ -103,7 +103,7 @@ class ScheduleManagerCore {
103
103
  // Set the batch flag to false on the last message to indicate the end of the send batch
104
104
  const lastMessage = messages[messages.length - 1];
105
105
  // TODO: It's not clear if this shallow clone is required, as opposed to just setting "batch" to false.
106
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
106
+
107
107
  lastMessage.metadata = { ...(lastMessage.metadata as any), batch: false };
108
108
  });
109
109
 
@@ -303,7 +303,7 @@ class ScheduleManagerCore {
303
303
  );
304
304
  this.pauseSequenceNumber = message.sequenceNumber;
305
305
  // TODO: Verify whether this should be able to handle server-generated ops (with null clientId)
306
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
306
+
307
307
  this.currentBatchClientId = message.clientId as string;
308
308
  // Start of the batch
309
309
  // Only pause processing if queue has no other ops!
@@ -3,13 +3,10 @@
3
3
  * Licensed under the MIT License.
4
4
  */
5
5
 
6
+ import type { SummarizerStopReason } from "@fluidframework/container-runtime-definitions/internal";
6
7
  import { assert, Deferred } from "@fluidframework/core-utils/internal";
7
8
 
8
- import {
9
- IConnectableRuntime,
10
- ISummaryCancellationToken,
11
- SummarizerStopReason,
12
- } from "./summarizerTypes.js";
9
+ import { IConnectableRuntime, ISummaryCancellationToken } from "./summarizerTypes.js";
13
10
 
14
11
  /**
15
12
  * Similar to AbortController, but using promise instead of events