@fluidframework/container-runtime 0.59.4000 → 1.0.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.
Files changed (137) hide show
  1. package/.eslintrc.js +1 -1
  2. package/dist/blobManager.d.ts +2 -2
  3. package/dist/blobManager.d.ts.map +1 -1
  4. package/dist/blobManager.js +12 -11
  5. package/dist/blobManager.js.map +1 -1
  6. package/dist/connectionTelemetry.js +3 -3
  7. package/dist/connectionTelemetry.js.map +1 -1
  8. package/dist/containerRuntime.d.ts +125 -29
  9. package/dist/containerRuntime.d.ts.map +1 -1
  10. package/dist/containerRuntime.js +242 -110
  11. package/dist/containerRuntime.js.map +1 -1
  12. package/dist/dataStoreContext.d.ts +4 -2
  13. package/dist/dataStoreContext.d.ts.map +1 -1
  14. package/dist/dataStoreContext.js +16 -5
  15. package/dist/dataStoreContext.js.map +1 -1
  16. package/dist/dataStores.d.ts +4 -3
  17. package/dist/dataStores.d.ts.map +1 -1
  18. package/dist/dataStores.js +9 -3
  19. package/dist/dataStores.js.map +1 -1
  20. package/dist/garbageCollection.d.ts +14 -3
  21. package/dist/garbageCollection.d.ts.map +1 -1
  22. package/dist/garbageCollection.js +56 -26
  23. package/dist/garbageCollection.js.map +1 -1
  24. package/dist/index.d.ts +2 -2
  25. package/dist/index.d.ts.map +1 -1
  26. package/dist/index.js +2 -1
  27. package/dist/index.js.map +1 -1
  28. package/dist/orderedClientElection.js +0 -4
  29. package/dist/orderedClientElection.js.map +1 -1
  30. package/dist/packageVersion.d.ts +1 -1
  31. package/dist/packageVersion.d.ts.map +1 -1
  32. package/dist/packageVersion.js +1 -1
  33. package/dist/packageVersion.js.map +1 -1
  34. package/dist/pendingStateManager.d.ts +30 -29
  35. package/dist/pendingStateManager.d.ts.map +1 -1
  36. package/dist/pendingStateManager.js +72 -109
  37. package/dist/pendingStateManager.js.map +1 -1
  38. package/dist/runningSummarizer.d.ts +4 -3
  39. package/dist/runningSummarizer.d.ts.map +1 -1
  40. package/dist/runningSummarizer.js +11 -6
  41. package/dist/runningSummarizer.js.map +1 -1
  42. package/dist/serializedSnapshotStorage.d.ts +58 -0
  43. package/dist/serializedSnapshotStorage.d.ts.map +1 -0
  44. package/dist/serializedSnapshotStorage.js +108 -0
  45. package/dist/serializedSnapshotStorage.js.map +1 -0
  46. package/dist/summarizer.d.ts +11 -4
  47. package/dist/summarizer.d.ts.map +1 -1
  48. package/dist/summarizer.js +18 -9
  49. package/dist/summarizer.js.map +1 -1
  50. package/dist/summarizerHeuristics.d.ts +5 -3
  51. package/dist/summarizerHeuristics.d.ts.map +1 -1
  52. package/dist/summarizerHeuristics.js +10 -3
  53. package/dist/summarizerHeuristics.js.map +1 -1
  54. package/dist/summarizerTypes.d.ts +4 -2
  55. package/dist/summarizerTypes.d.ts.map +1 -1
  56. package/dist/summarizerTypes.js.map +1 -1
  57. package/dist/summaryManager.d.ts +3 -3
  58. package/dist/summaryManager.d.ts.map +1 -1
  59. package/dist/summaryManager.js +7 -7
  60. package/dist/summaryManager.js.map +1 -1
  61. package/garbageCollection.md +9 -1
  62. package/lib/blobManager.d.ts +2 -2
  63. package/lib/blobManager.d.ts.map +1 -1
  64. package/lib/blobManager.js +12 -11
  65. package/lib/blobManager.js.map +1 -1
  66. package/lib/connectionTelemetry.js +3 -3
  67. package/lib/connectionTelemetry.js.map +1 -1
  68. package/lib/containerRuntime.d.ts +125 -29
  69. package/lib/containerRuntime.d.ts.map +1 -1
  70. package/lib/containerRuntime.js +243 -111
  71. package/lib/containerRuntime.js.map +1 -1
  72. package/lib/dataStoreContext.d.ts +4 -2
  73. package/lib/dataStoreContext.d.ts.map +1 -1
  74. package/lib/dataStoreContext.js +16 -5
  75. package/lib/dataStoreContext.js.map +1 -1
  76. package/lib/dataStores.d.ts +4 -3
  77. package/lib/dataStores.d.ts.map +1 -1
  78. package/lib/dataStores.js +9 -3
  79. package/lib/dataStores.js.map +1 -1
  80. package/lib/garbageCollection.d.ts +14 -3
  81. package/lib/garbageCollection.d.ts.map +1 -1
  82. package/lib/garbageCollection.js +54 -6
  83. package/lib/garbageCollection.js.map +1 -1
  84. package/lib/index.d.ts +2 -2
  85. package/lib/index.d.ts.map +1 -1
  86. package/lib/index.js +1 -1
  87. package/lib/index.js.map +1 -1
  88. package/lib/orderedClientElection.js +0 -4
  89. package/lib/orderedClientElection.js.map +1 -1
  90. package/lib/packageVersion.d.ts +1 -1
  91. package/lib/packageVersion.d.ts.map +1 -1
  92. package/lib/packageVersion.js +1 -1
  93. package/lib/packageVersion.js.map +1 -1
  94. package/lib/pendingStateManager.d.ts +30 -29
  95. package/lib/pendingStateManager.d.ts.map +1 -1
  96. package/lib/pendingStateManager.js +72 -109
  97. package/lib/pendingStateManager.js.map +1 -1
  98. package/lib/runningSummarizer.d.ts +4 -3
  99. package/lib/runningSummarizer.d.ts.map +1 -1
  100. package/lib/runningSummarizer.js +11 -6
  101. package/lib/runningSummarizer.js.map +1 -1
  102. package/lib/serializedSnapshotStorage.d.ts +58 -0
  103. package/lib/serializedSnapshotStorage.d.ts.map +1 -0
  104. package/lib/serializedSnapshotStorage.js +104 -0
  105. package/lib/serializedSnapshotStorage.js.map +1 -0
  106. package/lib/summarizer.d.ts +11 -4
  107. package/lib/summarizer.d.ts.map +1 -1
  108. package/lib/summarizer.js +18 -9
  109. package/lib/summarizer.js.map +1 -1
  110. package/lib/summarizerHeuristics.d.ts +5 -3
  111. package/lib/summarizerHeuristics.d.ts.map +1 -1
  112. package/lib/summarizerHeuristics.js +10 -3
  113. package/lib/summarizerHeuristics.js.map +1 -1
  114. package/lib/summarizerTypes.d.ts +4 -2
  115. package/lib/summarizerTypes.d.ts.map +1 -1
  116. package/lib/summarizerTypes.js.map +1 -1
  117. package/lib/summaryManager.d.ts +3 -3
  118. package/lib/summaryManager.d.ts.map +1 -1
  119. package/lib/summaryManager.js +7 -7
  120. package/lib/summaryManager.js.map +1 -1
  121. package/package.json +45 -31
  122. package/src/blobManager.ts +29 -15
  123. package/src/connectionTelemetry.ts +3 -3
  124. package/src/containerRuntime.ts +388 -135
  125. package/src/dataStoreContext.ts +27 -5
  126. package/src/dataStores.ts +15 -3
  127. package/src/garbageCollection.ts +69 -12
  128. package/src/index.ts +7 -1
  129. package/src/orderedClientElection.ts +1 -1
  130. package/src/packageVersion.ts +1 -1
  131. package/src/pendingStateManager.ts +104 -123
  132. package/src/runningSummarizer.ts +20 -10
  133. package/src/serializedSnapshotStorage.ts +146 -0
  134. package/src/summarizer.ts +20 -16
  135. package/src/summarizerHeuristics.ts +21 -5
  136. package/src/summarizerTypes.ts +4 -2
  137. package/src/summaryManager.ts +5 -6
@@ -58,6 +58,7 @@ import {
58
58
  ISummarizeResult,
59
59
  ISummarizerNodeWithGC,
60
60
  SummarizeInternalFn,
61
+ ITelemetryContext,
61
62
  } from "@fluidframework/runtime-definitions";
62
63
  import { addBlobToSummary, convertSummaryTreeToITree } from "@fluidframework/runtime-utils";
63
64
  import {
@@ -289,7 +290,8 @@ export abstract class FluidDataStoreContext extends TypedEventEmitter<IFluidData
289
290
  };
290
291
 
291
292
  const thisSummarizeInternal =
292
- async (fullTree: boolean, trackState: boolean) => this.summarizeInternal(fullTree, trackState);
293
+ async (fullTree: boolean, trackState: boolean, telemetryContext?: ITelemetryContext) =>
294
+ this.summarizeInternal(fullTree, trackState, telemetryContext);
293
295
 
294
296
  this.summarizerNode = props.createSummarizerNodeFn(
295
297
  thisSummarizeInternal,
@@ -445,16 +447,25 @@ export abstract class FluidDataStoreContext extends TypedEventEmitter<IFluidData
445
447
  * Returns a summary at the current sequence number.
446
448
  * @param fullTree - true to bypass optimizations and force a full summary tree
447
449
  * @param trackState - This tells whether we should track state from this summary.
450
+ * @param telemetryContext - summary data passed through the layers for telemetry purposes
448
451
  */
449
- public async summarize(fullTree: boolean = false, trackState: boolean = true): Promise<ISummarizeResult> {
450
- return this.summarizerNode.summarize(fullTree, trackState);
452
+ public async summarize(
453
+ fullTree: boolean = false,
454
+ trackState: boolean = true,
455
+ telemetryContext?: ITelemetryContext,
456
+ ): Promise<ISummarizeResult> {
457
+ return this.summarizerNode.summarize(fullTree, trackState, telemetryContext);
451
458
  }
452
459
 
453
- private async summarizeInternal(fullTree: boolean, trackState: boolean): Promise<ISummarizeInternalResult> {
460
+ private async summarizeInternal(
461
+ fullTree: boolean,
462
+ trackState: boolean,
463
+ telemetryContext?: ITelemetryContext,
464
+ ): Promise<ISummarizeInternalResult> {
454
465
  await this.realize();
455
466
 
456
467
  // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
457
- const summarizeResult = await this.channel!.summarize(fullTree, trackState);
468
+ const summarizeResult = await this.channel!.summarize(fullTree, trackState, telemetryContext);
458
469
  let pathPartsForChildren: string[] | undefined;
459
470
 
460
471
  if (!this.disableIsolatedChannels) {
@@ -717,6 +728,17 @@ export abstract class FluidDataStoreContext extends TypedEventEmitter<IFluidData
717
728
  this.channel.reSubmit(innerContents.type, innerContents.content, localOpMetadata);
718
729
  }
719
730
 
731
+ public rollback(contents: any, localOpMetadata: unknown) {
732
+ if (!this.channel) {
733
+ throw new Error("Channel must exist when rolling back ops");
734
+ }
735
+ if (!this.channel.rollback) {
736
+ throw new Error("Channel doesn't support rollback");
737
+ }
738
+ const innerContents = contents as FluidDataStoreMessage;
739
+ this.channel.rollback(innerContents.type, innerContents.content, localOpMetadata);
740
+ }
741
+
720
742
  public async applyStashedOp(contents: any): Promise<unknown> {
721
743
  if (!this.channel) {
722
744
  await this.realize();
package/src/dataStores.ts CHANGED
@@ -25,6 +25,7 @@ import {
25
25
  InboundAttachMessage,
26
26
  ISummarizeResult,
27
27
  ISummaryTreeWithStats,
28
+ ITelemetryContext,
28
29
  } from "@fluidframework/runtime-definitions";
29
30
  import {
30
31
  convertSnapshotTreeToSummaryTree,
@@ -380,6 +381,13 @@ export class DataStores implements IDisposable {
380
381
  context.reSubmit(envelope.contents, localOpMetadata);
381
382
  }
382
383
 
384
+ public rollbackDataStoreOp(content: any, localOpMetadata: unknown) {
385
+ const envelope = content as IEnvelope;
386
+ const context = this.contexts.get(envelope.address);
387
+ assert(!!context, 0x2e8 /* "There should be a store context for the op" */);
388
+ context.rollback(envelope.contents, localOpMetadata);
389
+ }
390
+
383
391
  public async applyStashedOp(content: any): Promise<unknown> {
384
392
  const envelope = content as IEnvelope;
385
393
  const context = this.contexts.get(envelope.address);
@@ -473,7 +481,11 @@ export class DataStores implements IDisposable {
473
481
  return this.contexts.size;
474
482
  }
475
483
 
476
- public async summarize(fullTree: boolean, trackState: boolean): Promise<ISummaryTreeWithStats> {
484
+ public async summarize(
485
+ fullTree: boolean,
486
+ trackState: boolean,
487
+ telemetryContext?: ITelemetryContext,
488
+ ): Promise<ISummaryTreeWithStats> {
477
489
  const summaryBuilder = new SummaryTreeBuilder();
478
490
 
479
491
  // Iterate over each store and ask it to snapshot
@@ -484,14 +496,14 @@ export class DataStores implements IDisposable {
484
496
  0x165 /* "Summarizer cannot work if client has local changes" */);
485
497
  return context.attachState === AttachState.Attached;
486
498
  }).map(async ([contextId, context]) => {
487
- const contextSummary = await context.summarize(fullTree, trackState);
499
+ const contextSummary = await context.summarize(fullTree, trackState, telemetryContext);
488
500
  summaryBuilder.addWithStats(contextId, contextSummary);
489
501
  }));
490
502
 
491
503
  return summaryBuilder.getSummaryTree();
492
504
  }
493
505
 
494
- public createSummary(): ISummaryTreeWithStats {
506
+ public createSummary(telemetryContext?: ITelemetryContext): ISummaryTreeWithStats {
495
507
  const builder = new SummaryTreeBuilder();
496
508
  // Attaching graph of some stores can cause other stores to get bound too.
497
509
  // So keep taking summary until no new stores get bound.
@@ -22,8 +22,9 @@ import {
22
22
  IGarbageCollectionData,
23
23
  IGarbageCollectionState,
24
24
  IGarbageCollectionDetailsBase,
25
- IGarbageCollectionNodeData,
26
25
  ISummarizeResult,
26
+ ITelemetryContext,
27
+ IGarbageCollectionNodeData,
27
28
  } from "@fluidframework/runtime-definitions";
28
29
  import {
29
30
  mergeStats,
@@ -39,7 +40,6 @@ import {
39
40
  TelemetryDataTag,
40
41
  } from "@fluidframework/telemetry-utils";
41
42
 
42
- import * as semver from "semver";
43
43
  import { IGCRuntimeOptions, RuntimeHeaders } from "./containerRuntime";
44
44
  import { getSummaryForDatastores } from "./dataStores";
45
45
  import { pkgVersion } from "./packageVersion";
@@ -163,7 +163,11 @@ export interface IGarbageCollector {
163
163
  options: { logger?: ITelemetryLogger; runGC?: boolean; runSweep?: boolean; fullGC?: boolean; },
164
164
  ): Promise<IGCStats>;
165
165
  /** Summarizes the GC data and returns it as a summary tree. */
166
- summarize(fullTree: boolean, trackState: boolean): ISummarizeResult | undefined;
166
+ summarize(
167
+ fullTree: boolean,
168
+ trackState: boolean,
169
+ telemetryContext?: ITelemetryContext,
170
+ ): ISummarizeResult | undefined;
167
171
  /** Returns the garbage collector specific metadata to be written into the summary. */
168
172
  getMetadata(): IGCMetadata;
169
173
  /** Returns a map of each node id to its base GC details in the base summary. */
@@ -331,7 +335,7 @@ export class GarbageCollector implements IGarbageCollector {
331
335
  private _writeDataAtRoot: boolean = false;
332
336
  public get writeDataAtRoot(): boolean {
333
337
  return this._writeDataAtRoot;
334
- }
338
+ }
335
339
 
336
340
  /**
337
341
  * Tells whether the initial GC state needs to be reset. This can happen under 2 conditions:
@@ -421,12 +425,14 @@ export class GarbageCollector implements IGarbageCollector {
421
425
  } else {
422
426
  // Sweep should not be enabled without enabling GC mark phase. We could silently disable sweep in this
423
427
  // scenario but explicitly failing makes it clearer and promotes correct usage.
424
- if (gcOptions.sweepAllowed && !gcOptions.gcAllowed) {
428
+ if (gcOptions.sweepAllowed && gcOptions.gcAllowed === false) {
425
429
  throw new UsageError("GC sweep phase cannot be enabled without enabling GC mark phase");
426
430
  }
427
431
 
428
- // For new documents, GC has to be explicitly enabled via the flags in GC options.
429
- this.gcEnabled = gcOptions.gcAllowed === true;
432
+ // For new documents, GC is enabled by default. It can be explicitly disabled by setting the gcAllowed
433
+ // flag in GC options to false.
434
+ this.gcEnabled = gcOptions.gcAllowed !== false;
435
+ // The sweep phase has to be explicitly enabled by setting the sweepAllowed flag in GC options to true.
430
436
  this.sweepEnabled = gcOptions.sweepAllowed === true;
431
437
 
432
438
  // Set the Session Expiry only if the flag is enabled or the test option is set.
@@ -589,7 +595,7 @@ export class GarbageCollector implements IGarbageCollector {
589
595
  return;
590
596
  }
591
597
 
592
- const gcNodes: { [ id: string ]: string[]; } = {};
598
+ const gcNodes: { [id: string]: string[]; } = {};
593
599
  for (const [nodeId, nodeData] of Object.entries(baseState.gcNodes)) {
594
600
  if (nodeData.unreferencedTimestampMs !== undefined) {
595
601
  this.unreferencedNodesState.set(
@@ -614,7 +620,7 @@ export class GarbageCollector implements IGarbageCollector {
614
620
  return new Map();
615
621
  }
616
622
 
617
- const gcNodes: { [ id: string ]: string[]; } = {};
623
+ const gcNodes: { [id: string]: string[]; } = {};
618
624
  for (const [nodeId, nodeData] of Object.entries(baseState.gcNodes)) {
619
625
  gcNodes[nodeId] = Array.from(nodeData.outboundRoutes);
620
626
  }
@@ -738,8 +744,7 @@ export class GarbageCollector implements IGarbageCollector {
738
744
  this.completedRuns++;
739
745
 
740
746
  return gcStats;
741
- },
742
- { end: true, cancel: "error" });
747
+ }, { end: true, cancel: "error" });
743
748
  }
744
749
 
745
750
  /**
@@ -750,6 +755,7 @@ export class GarbageCollector implements IGarbageCollector {
750
755
  public summarize(
751
756
  fullTree: boolean,
752
757
  trackState: boolean,
758
+ telemetryContext?: ITelemetryContext,
753
759
  ): ISummarizeResult | undefined {
754
760
  if (!this.shouldRunGC || this.previousGCDataFromLastRun === undefined) {
755
761
  return;
@@ -1324,5 +1330,56 @@ function setLongTimeout(
1324
1330
  * @param minimumVersion - the function to execute when the timer ends
1325
1331
  */
1326
1332
  function meetsMinimumVersionRequirement(currentVersion: string, minimumVersion: string | undefined) {
1327
- return minimumVersion === undefined || semver.compare(currentVersion, minimumVersion) >= 0;
1333
+ return minimumVersion === undefined || semverCompare(currentVersion, minimumVersion) >= 0;
1334
+ }
1335
+
1336
+ /**
1337
+ * Compare semver versions.
1338
+ * @param currentVersion - assumed to be any valid semver version
1339
+ * @param minimumVersion - must be [major].[minor].[patch], where major, minor, and patch are all numbers
1340
+ * as it complicates the algorithm if we allow comparisons against minimum pre-release versions.
1341
+ * @returns
1342
+ * 0 if the currentVersion equals the minimumVersion
1343
+ * 1 if the currentVersion is greater than the minimumVersion
1344
+ * -1 if the minimumVersion is greater than the currentVersion
1345
+ */
1346
+ export function semverCompare(currentVersion: string, minimumVersion: string): number {
1347
+ const minimumValues = minimumVersion.split(".").map((value): number => {
1348
+ assert(isNaN(+value) === false, 0x2f8 /* Expected real numbers in minimum version! */);
1349
+ return Number.parseInt(value, 10);
1350
+ });
1351
+ assert(minimumValues.length === 3, 0x2f9 /* Expected minimumVersion to be [major].[minor].[patch] */);
1352
+ const [minMajor, minMinor, minPatch] = minimumValues;
1353
+
1354
+ const currentValuesString = currentVersion.split(/\W/);
1355
+ assert(currentValuesString.length >= 3, 0x2fa /* Expected version to match semver rules! */);
1356
+ const currentValues = currentValuesString.slice(0, 3).map((value) => {
1357
+ assert(isNaN(+value) === false, 0x2fb /* Expected real numbers in minimum version! */);
1358
+ return Number.parseInt(value, 10);
1359
+ });
1360
+ const [cMajor, cMinor, cPatch] = currentValues;
1361
+
1362
+ if (cMajor > minMajor) {
1363
+ return 1;
1364
+ } else if (minMajor > cMajor) {
1365
+ return -1;
1366
+ }
1367
+
1368
+ if (cMinor > minMinor) {
1369
+ return 1;
1370
+ } else if (minMinor > cMinor) {
1371
+ return -1;
1372
+ }
1373
+
1374
+ if (cPatch > minPatch) {
1375
+ return 1;
1376
+ } else if (minPatch > cPatch) {
1377
+ return -1;
1378
+ }
1379
+
1380
+ if (currentValuesString.length === 3) {
1381
+ return 0;
1382
+ }
1383
+
1384
+ return -1;
1328
1385
  }
package/src/index.ts CHANGED
@@ -9,7 +9,12 @@ export {
9
9
  ContainerRuntimeMessage,
10
10
  IGCRuntimeOptions,
11
11
  ISummaryRuntimeOptions,
12
+ ISummaryBaseConfiguration,
13
+ ISummaryConfigurationHeuristics,
14
+ ISummaryConfigurationDisableSummarizer,
15
+ ISummaryConfigurationDisableHeuristics,
12
16
  IContainerRuntimeOptions,
17
+ IPendingRuntimeState,
13
18
  IRootSummaryTreeWithStats,
14
19
  isRuntimeMessage,
15
20
  RuntimeMessage,
@@ -18,6 +23,8 @@ export {
18
23
  agentSchedulerId,
19
24
  ContainerRuntime,
20
25
  RuntimeHeaders,
26
+ ISummaryConfiguration,
27
+ DefaultSummaryConfiguration,
21
28
  } from "./containerRuntime";
22
29
  export { DeltaScheduler } from "./deltaScheduler";
23
30
  export { FluidDataStoreRegistry } from "./dataStoreRegistry";
@@ -55,7 +62,6 @@ export {
55
62
  ISummarizer,
56
63
  ISummarizerEvents,
57
64
  ISummarizerInternalsProvider,
58
- ISummarizerOptions,
59
65
  ISummarizerRuntime,
60
66
  ISummarizingWarning,
61
67
  ISummaryCancellationToken,
@@ -2,7 +2,7 @@
2
2
  * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
3
  * Licensed under the MIT License.
4
4
  */
5
-
5
+ /* eslint-disable @rushstack/no-new-null */
6
6
  import { IEvent, IEventProvider, ITelemetryLogger } from "@fluidframework/common-definitions";
7
7
  import { assert, TypedEventEmitter } from "@fluidframework/common-utils";
8
8
  import { IDeltaManager } from "@fluidframework/container-definitions";
@@ -6,4 +6,4 @@
6
6
  */
7
7
 
8
8
  export const pkgName = "@fluidframework/container-runtime";
9
- export const pkgVersion = "0.59.4000";
9
+ export const pkgVersion = "1.0.1";