@fluidframework/container-runtime 0.49.2 → 0.50.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 (61) hide show
  1. package/dist/containerRuntime.d.ts +2 -2
  2. package/dist/containerRuntime.d.ts.map +1 -1
  3. package/dist/containerRuntime.js +73 -71
  4. package/dist/containerRuntime.js.map +1 -1
  5. package/dist/dataStoreContext.d.ts.map +1 -1
  6. package/dist/dataStoreContext.js +2 -1
  7. package/dist/dataStoreContext.js.map +1 -1
  8. package/dist/dataStores.d.ts.map +1 -1
  9. package/dist/dataStores.js.map +1 -1
  10. package/dist/index.d.ts +1 -1
  11. package/dist/index.d.ts.map +1 -1
  12. package/dist/index.js.map +1 -1
  13. package/dist/packageVersion.d.ts +1 -1
  14. package/dist/packageVersion.js +1 -1
  15. package/dist/packageVersion.js.map +1 -1
  16. package/dist/summarizer.d.ts +4 -1
  17. package/dist/summarizer.d.ts.map +1 -1
  18. package/dist/summarizer.js +3 -3
  19. package/dist/summarizer.js.map +1 -1
  20. package/dist/summarizerClientElection.d.ts +1 -1
  21. package/dist/summarizerClientElection.js +1 -1
  22. package/dist/summarizerClientElection.js.map +1 -1
  23. package/dist/summaryManager.d.ts +10 -3
  24. package/dist/summaryManager.d.ts.map +1 -1
  25. package/dist/summaryManager.js +9 -6
  26. package/dist/summaryManager.js.map +1 -1
  27. package/lib/containerRuntime.d.ts +2 -2
  28. package/lib/containerRuntime.d.ts.map +1 -1
  29. package/lib/containerRuntime.js +73 -71
  30. package/lib/containerRuntime.js.map +1 -1
  31. package/lib/dataStoreContext.d.ts.map +1 -1
  32. package/lib/dataStoreContext.js +2 -1
  33. package/lib/dataStoreContext.js.map +1 -1
  34. package/lib/dataStores.d.ts.map +1 -1
  35. package/lib/dataStores.js.map +1 -1
  36. package/lib/index.d.ts +1 -1
  37. package/lib/index.d.ts.map +1 -1
  38. package/lib/index.js.map +1 -1
  39. package/lib/packageVersion.d.ts +1 -1
  40. package/lib/packageVersion.js +1 -1
  41. package/lib/packageVersion.js.map +1 -1
  42. package/lib/summarizer.d.ts +4 -1
  43. package/lib/summarizer.d.ts.map +1 -1
  44. package/lib/summarizer.js +3 -3
  45. package/lib/summarizer.js.map +1 -1
  46. package/lib/summarizerClientElection.d.ts +1 -1
  47. package/lib/summarizerClientElection.js +1 -1
  48. package/lib/summarizerClientElection.js.map +1 -1
  49. package/lib/summaryManager.d.ts +10 -3
  50. package/lib/summaryManager.d.ts.map +1 -1
  51. package/lib/summaryManager.js +9 -6
  52. package/lib/summaryManager.js.map +1 -1
  53. package/package.json +16 -16
  54. package/src/containerRuntime.ts +106 -96
  55. package/src/dataStoreContext.ts +2 -1
  56. package/src/dataStores.ts +1 -1
  57. package/src/index.ts +1 -1
  58. package/src/packageVersion.ts +1 -1
  59. package/src/summarizer.ts +5 -2
  60. package/src/summarizerClientElection.ts +1 -1
  61. package/src/summaryManager.ts +17 -7
@@ -102,7 +102,7 @@ import { v4 as uuid } from "uuid";
102
102
  import { ContainerFluidHandleContext } from "./containerHandleContext";
103
103
  import { FluidDataStoreRegistry } from "./dataStoreRegistry";
104
104
  import { Summarizer } from "./summarizer";
105
- import { formRequestSummarizerFn, SummaryManager } from "./summaryManager";
105
+ import { formRequestSummarizerFn, ISummarizerRequestOptions, SummaryManager } from "./summaryManager";
106
106
  import { DeltaScheduler } from "./deltaScheduler";
107
107
  import { ReportOpPerfTelemetry } from "./connectionTelemetry";
108
108
  import { IPendingLocalState, PendingStateManager } from "./pendingStateManager";
@@ -127,6 +127,7 @@ import { ISerializedElection, OrderedClientCollection, OrderedClientElection } f
127
127
  import { SummarizerClientElection, summarizerClientType } from "./summarizerClientElection";
128
128
  import {
129
129
  SubmitSummaryResult,
130
+ IConnectableRuntime,
130
131
  IGeneratedSummaryStats,
131
132
  ISubmitSummaryOptions,
132
133
  ISummarizer,
@@ -135,6 +136,7 @@ import {
135
136
  ISummarizerRuntime,
136
137
  } from "./summarizerTypes";
137
138
  import { formExponentialFn, Throttler } from "./throttler";
139
+ import { RunWhileConnectedCoordinator } from "./runWhileConnectedCoordinator";
138
140
 
139
141
  export enum ContainerMessageType {
140
142
  // An op to be delivered to store
@@ -721,13 +723,13 @@ export class ContainerRuntime extends TypedEventEmitter<IContainerRuntimeEvents>
721
723
 
722
724
  // internal logger for ContainerRuntime. Use this.logger for stores, summaries, etc.
723
725
  private readonly _logger: ITelemetryLogger;
724
- private readonly summarizerClientElection: SummarizerClientElection;
726
+ private readonly summarizerClientElection?: SummarizerClientElection;
725
727
  /**
726
728
  * summaryManager will only be created if this client is permitted to spawn a summarizing client
727
729
  * It is created only by interactive client, i.e. summarizer client, as well as non-interactive bots
728
730
  * do not create it (see SummarizerClientElection.clientDetailsPermitElection() for details)
729
731
  */
730
- private readonly summaryManager: SummaryManager | undefined;
732
+ private readonly summaryManager?: SummaryManager;
731
733
  private readonly summaryCollection: SummaryCollection;
732
734
 
733
735
  private readonly summarizerNode: IRootSummarizerNodeWithGC;
@@ -747,7 +749,7 @@ export class ContainerRuntime extends TypedEventEmitter<IContainerRuntimeEvents>
747
749
 
748
750
  /** clientId of parent (non-summarizing) container that owns summarizer container */
749
751
  public get summarizerClientId(): string | undefined {
750
- return this.summarizerClientElection.electedClientId;
752
+ return this.summarizerClientElection?.electedClientId;
751
753
  }
752
754
 
753
755
  private get summaryConfiguration() {
@@ -949,49 +951,51 @@ export class ContainerRuntime extends TypedEventEmitter<IContainerRuntimeEvents>
949
951
  });
950
952
 
951
953
  this.summaryCollection = new SummaryCollection(this.deltaManager, this.logger);
952
- const maxOpsSinceLastSummary = this.runtimeOptions.summaryOptions.maxOpsSinceLastSummary ?? 7000;
953
- const defaultAction = () => {
954
- if (this.summaryCollection.opsSinceLastAck > maxOpsSinceLastSummary) {
955
- this.logger.sendErrorEvent({eventName: "SummaryStatus:Behind"});
956
- // unregister default to no log on every op after falling behind
957
- // and register summary ack handler to re-register this handler
958
- // after successful summary
959
- this.summaryCollection.once(MessageType.SummaryAck, () => {
960
- this.logger.sendTelemetryEvent({eventName: "SummaryStatus:CaughtUp"});
961
- // we've caught up, so re-register the default action to monitor for
962
- // falling behind, and unregister ourself
963
- this.summaryCollection.on("default", defaultAction);
964
- });
965
- this.summaryCollection.off("default", defaultAction);
966
- }
967
- };
968
- this.summaryCollection.on("default", defaultAction);
969
954
 
970
- const orderedClientLogger = ChildLogger.create(this.logger, "OrderedClientElection");
971
- const orderedClientCollection = new OrderedClientCollection(
972
- orderedClientLogger,
973
- this.context.deltaManager,
974
- this.context.quorum,
975
- );
976
- const orderedClientElectionForSummarizer = new OrderedClientElection(
977
- orderedClientLogger,
978
- orderedClientCollection,
979
- electedSummarizerData ?? this.context.deltaManager.lastSequenceNumber,
980
- SummarizerClientElection.isClientEligible,
981
- );
982
- const summarizerClientElectionEnabled = getLocalStorageFeatureGate("summarizerClientElection") ??
983
- this.runtimeOptions.summaryOptions?.summarizerClientElection === true;
984
- this.summarizerClientElection = new SummarizerClientElection(
985
- orderedClientLogger,
986
- this.summaryCollection,
987
- orderedClientElectionForSummarizer,
988
- maxOpsSinceLastSummary,
989
- summarizerClientElectionEnabled,
990
- );
991
955
  // Only create a SummaryManager if summaries are enabled and we are not the summarizer client
992
956
  if (this.runtimeOptions.summaryOptions.generateSummaries === false) {
993
957
  this._logger.sendTelemetryEvent({ eventName: "SummariesDisabled" });
994
958
  } else {
959
+ const maxOpsSinceLastSummary = this.runtimeOptions.summaryOptions.maxOpsSinceLastSummary ?? 7000;
960
+ const defaultAction = () => {
961
+ if (this.summaryCollection.opsSinceLastAck > maxOpsSinceLastSummary) {
962
+ this.logger.sendErrorEvent({eventName: "SummaryStatus:Behind"});
963
+ // unregister default to no log on every op after falling behind
964
+ // and register summary ack handler to re-register this handler
965
+ // after successful summary
966
+ this.summaryCollection.once(MessageType.SummaryAck, () => {
967
+ this.logger.sendTelemetryEvent({eventName: "SummaryStatus:CaughtUp"});
968
+ // we've caught up, so re-register the default action to monitor for
969
+ // falling behind, and unregister ourself
970
+ this.summaryCollection.on("default", defaultAction);
971
+ });
972
+ this.summaryCollection.off("default", defaultAction);
973
+ }
974
+ };
975
+
976
+ this.summaryCollection.on("default", defaultAction);
977
+ const orderedClientLogger = ChildLogger.create(this.logger, "OrderedClientElection");
978
+ const orderedClientCollection = new OrderedClientCollection(
979
+ orderedClientLogger,
980
+ this.context.deltaManager,
981
+ this.context.quorum,
982
+ );
983
+ const orderedClientElectionForSummarizer = new OrderedClientElection(
984
+ orderedClientLogger,
985
+ orderedClientCollection,
986
+ electedSummarizerData ?? this.context.deltaManager.lastSequenceNumber,
987
+ SummarizerClientElection.isClientEligible,
988
+ );
989
+ const summarizerClientElectionEnabled = getLocalStorageFeatureGate("summarizerClientElection") ??
990
+ this.runtimeOptions.summaryOptions?.summarizerClientElection === true;
991
+ this.summarizerClientElection = new SummarizerClientElection(
992
+ orderedClientLogger,
993
+ this.summaryCollection,
994
+ orderedClientElectionForSummarizer,
995
+ maxOpsSinceLastSummary,
996
+ summarizerClientElectionEnabled,
997
+ );
998
+
995
999
  if (this.context.clientDetails.type === summarizerClientType) {
996
1000
  this._summarizer = new Summarizer(
997
1001
  "/_summarizer",
@@ -999,15 +1003,26 @@ export class ContainerRuntime extends TypedEventEmitter<IContainerRuntimeEvents>
999
1003
  () => this.summaryConfiguration,
1000
1004
  this /* ISummarizerInternalsProvider */,
1001
1005
  this.IFluidHandleContext,
1002
- this.summaryCollection);
1006
+ this.summaryCollection,
1007
+ async (runtime: IConnectableRuntime) => RunWhileConnectedCoordinator.create(runtime),
1008
+ );
1003
1009
  } else if (SummarizerClientElection.clientDetailsPermitElection(this.context.clientDetails)) {
1004
1010
  // Create the SummaryManager and mark the initial state
1011
+ const requestOptions: ISummarizerRequestOptions =
1012
+ {
1013
+ cache: false,
1014
+ reconnect: false,
1015
+ summarizingClient: true,
1016
+ };
1005
1017
  this.summaryManager = new SummaryManager(
1006
1018
  this.summarizerClientElection,
1007
1019
  this, // IConnectedState
1008
1020
  this.summaryCollection,
1009
1021
  this.logger,
1010
- formRequestSummarizerFn(this.context.loader, this.context.deltaManager),
1022
+ formRequestSummarizerFn(
1023
+ this.context.loader,
1024
+ this.context.deltaManager.lastSequenceNumber,
1025
+ requestOptions),
1011
1026
  new Throttler(
1012
1027
  60 * 1000, // 60 sec delay window
1013
1028
  30 * 1000, // 30 sec max delay
@@ -1250,9 +1265,11 @@ export class ContainerRuntime extends TypedEventEmitter<IContainerRuntimeEvents>
1250
1265
  const content = JSON.stringify([...this.chunkMap]);
1251
1266
  addBlobToSummary(summaryTree, chunksBlobName, content);
1252
1267
  }
1253
- const electedSummarizerContent = JSON.stringify(this.summarizerClientElection.serialize());
1254
- addBlobToSummary(summaryTree, electedSummarizerBlobName, electedSummarizerContent);
1255
1268
 
1269
+ if (this.summarizerClientElection) {
1270
+ const electedSummarizerContent = JSON.stringify(this.summarizerClientElection?.serialize());
1271
+ addBlobToSummary(summaryTree, electedSummarizerBlobName, electedSummarizerContent);
1272
+ }
1256
1273
  const snapshot = this.blobManager.snapshot();
1257
1274
 
1258
1275
  // Some storage (like git) doesn't allow empty tree, so we can omit it.
@@ -1521,7 +1538,7 @@ export class ContainerRuntime extends TypedEventEmitter<IContainerRuntimeEvents>
1521
1538
 
1522
1539
  public async createRootDataStore(pkg: string | string[], rootDataStoreId: string): Promise<IFluidRouter> {
1523
1540
  const fluidDataStore = await this._createDataStore(pkg, true /* isRoot */, rootDataStoreId);
1524
- fluidDataStore.bindToContext();
1541
+ fluidDataStore.attachGraph();
1525
1542
  return fluidDataStore;
1526
1543
  }
1527
1544
 
@@ -1542,8 +1559,12 @@ export class ContainerRuntime extends TypedEventEmitter<IContainerRuntimeEvents>
1542
1559
  id = uuid(),
1543
1560
  isRoot = false,
1544
1561
  ): Promise<IFluidDataStoreChannel> {
1545
- return this.dataStores._createFluidDataStoreContext(
1562
+ const fluidDataStore = await this.dataStores._createFluidDataStoreContext(
1546
1563
  Array.isArray(pkg) ? pkg : [pkg], id, isRoot, props).realize();
1564
+ if (isRoot) {
1565
+ fluidDataStore.attachGraph();
1566
+ }
1567
+ return fluidDataStore;
1547
1568
  }
1548
1569
 
1549
1570
  private async _createDataStore(
@@ -1567,6 +1588,7 @@ export class ContainerRuntime extends TypedEventEmitter<IContainerRuntimeEvents>
1567
1588
  return this.context.audience!;
1568
1589
  }
1569
1590
 
1591
+ // @deprecated Needs to become private
1570
1592
  public readonly raiseContainerWarning = (warning: ContainerWarning) => {
1571
1593
  this.context.raiseContainerWarning(warning);
1572
1594
  };
@@ -1667,47 +1689,43 @@ export class ContainerRuntime extends TypedEventEmitter<IContainerRuntimeEvents>
1667
1689
  deletedDataStores?: number,
1668
1690
  totalDataStores?: number,
1669
1691
  } = {};
1670
- try {
1671
- // Get the container's GC data and run GC on the reference graph in it.
1672
- const gcData = await this.dataStores.getGCData(fullGC);
1673
- const { referencedNodeIds, deletedNodeIds } = runGarbageCollection(
1674
- gcData.gcNodes, [ "/" ],
1675
- this.logger,
1676
- );
1692
+ // Get the container's GC data and run GC on the reference graph in it.
1693
+ const gcData = await this.dataStores.getGCData(fullGC);
1694
+ const { referencedNodeIds, deletedNodeIds } = runGarbageCollection(
1695
+ gcData.gcNodes, [ "/" ],
1696
+ this.logger,
1697
+ );
1677
1698
 
1678
- // Update our summarizer node's used routes. Updating used routes in summarizer node before
1679
- // summarizing is required and asserted by the the summarizer node. We are the root and are
1680
- // always referenced, so the used routes is only self-route (empty string).
1681
- this.summarizerNode.updateUsedRoutes([""]);
1682
-
1683
- // Remove this node's route ("/") and notify data stores of routes that are used in it.
1684
- const usedRoutes = referencedNodeIds.filter((id: string) => { return id !== "/"; });
1685
- const { dataStoreCount, unusedDataStoreCount } = this.dataStores.updateUsedRoutes(
1686
- usedRoutes,
1687
- // For now, we use the timestamp of the last op for gcTimestamp. However, there can be cases where
1688
- // we don't have an op (on demand summaries for instance). In those cases, we will use the timestamp
1689
- // of this client's connection - https://github.com/microsoft/FluidFramework/issues/7152.
1690
- this.deltaManager.lastMessage?.timestamp,
1691
- );
1699
+ // Update our summarizer node's used routes. Updating used routes in summarizer node before
1700
+ // summarizing is required and asserted by the the summarizer node. We are the root and are
1701
+ // always referenced, so the used routes is only self-route (empty string).
1702
+ this.summarizerNode.updateUsedRoutes([""]);
1703
+
1704
+ // Remove this node's route ("/") and notify data stores of routes that are used in it.
1705
+ const usedRoutes = referencedNodeIds.filter((id: string) => { return id !== "/"; });
1706
+ const { dataStoreCount, unusedDataStoreCount } = this.dataStores.updateUsedRoutes(
1707
+ usedRoutes,
1708
+ // For now, we use the timestamp of the last op for gcTimestamp. However, there can be cases where
1709
+ // we don't have an op (on demand summaries for instance). In those cases, we will use the timestamp
1710
+ // of this client's connection - https://github.com/microsoft/FluidFramework/issues/7152.
1711
+ this.deltaManager.lastMessage?.timestamp,
1712
+ );
1692
1713
 
1693
- // Update stats to be reported in the peformance event.
1694
- gcStats.deletedNodes = deletedNodeIds.length;
1695
- gcStats.totalNodes = referencedNodeIds.length + deletedNodeIds.length;
1696
- gcStats.deletedDataStores = unusedDataStoreCount;
1697
- gcStats.totalDataStores = dataStoreCount;
1714
+ // Update stats to be reported in the peformance event.
1715
+ gcStats.deletedNodes = deletedNodeIds.length;
1716
+ gcStats.totalNodes = referencedNodeIds.length + deletedNodeIds.length;
1717
+ gcStats.deletedDataStores = unusedDataStoreCount;
1718
+ gcStats.totalDataStores = dataStoreCount;
1698
1719
 
1699
- // If we are running in GC test mode, delete objects for unused routes. This enables testing scenarios
1700
- // involving access to deleted data.
1701
- if (this.gcTestMode) {
1702
- this.dataStores.deleteUnusedRoutes(deletedNodeIds);
1703
- }
1704
- } catch (error) {
1705
- event.cancel(gcStats, error);
1706
- throw error;
1720
+ // If we are running in GC test mode, delete objects for unused routes. This enables testing scenarios
1721
+ // involving access to deleted data.
1722
+ if (this.gcTestMode) {
1723
+ this.dataStores.deleteUnusedRoutes(deletedNodeIds);
1707
1724
  }
1708
1725
  event.end(gcStats);
1709
1726
  return gcStats as IGCStats;
1710
- });
1727
+ },
1728
+ { end: true, cancel: "error" });
1711
1729
  }
1712
1730
 
1713
1731
  private async summarizeInternal(fullTree: boolean, trackState: boolean): Promise<ISummarizeInternalResult> {
@@ -1767,7 +1785,6 @@ export class ContainerRuntime extends TypedEventEmitter<IContainerRuntimeEvents>
1767
1785
  */
1768
1786
  public async submitSummary(options: ISubmitSummaryOptions): Promise<SubmitSummaryResult> {
1769
1787
  const { fullTree, refreshLatestAck, summaryLogger } = options;
1770
-
1771
1788
  if (refreshLatestAck) {
1772
1789
  const latestSummaryRefSeq = await this.refreshLatestSummaryAckFromServer(
1773
1790
  ChildLogger.create(summaryLogger, undefined, { all: { safeSummary: true } }));
@@ -2259,10 +2276,8 @@ export class ContainerRuntime extends TypedEventEmitter<IContainerRuntimeEvents>
2259
2276
  }
2260
2277
 
2261
2278
  private async fetchSnapshotFromStorage(versionId: string, logger: ITelemetryLogger, event: ITelemetryGenericEvent) {
2262
- const perfEvent = PerformanceEvent.start(logger, event);
2263
- const stats: { getVersionDuration?: number; getSnapshotDuration?: number } = {};
2264
- let snapshot: ISnapshotTree;
2265
- try {
2279
+ return PerformanceEvent.timedExecAsync(logger, event, async (perfEvent) => {
2280
+ const stats: { getVersionDuration?: number; getSnapshotDuration?: number } = {};
2266
2281
  const trace = Trace.start();
2267
2282
 
2268
2283
  const versions = await this.storage.getVersions(versionId, 1);
@@ -2273,14 +2288,9 @@ export class ContainerRuntime extends TypedEventEmitter<IContainerRuntimeEvents>
2273
2288
  assert(!!maybeSnapshot, 0x138 /* "Failed to get snapshot from storage" */);
2274
2289
  stats.getSnapshotDuration = trace.trace().duration;
2275
2290
 
2276
- snapshot = maybeSnapshot;
2277
- } catch (error) {
2278
- perfEvent.cancel(stats, error);
2279
- throw error;
2280
- }
2281
-
2282
- perfEvent.end(stats);
2283
- return snapshot;
2291
+ perfEvent.end(stats);
2292
+ return maybeSnapshot;
2293
+ });
2284
2294
  }
2285
2295
 
2286
2296
  public getPendingLocalState() {
@@ -563,6 +563,7 @@ export abstract class FluidDataStoreContext extends TypedEventEmitter<IFluidData
563
563
  return this._containerRuntime.submitDataStoreSignal(this.id, type, content);
564
564
  }
565
565
 
566
+ // @deprecated Warnings are being deprecated
566
567
  public raiseContainerWarning(warning: ContainerWarning): void {
567
568
  this.containerRuntime.raiseContainerWarning(warning);
568
569
  }
@@ -990,7 +991,7 @@ export class LocalDetachedFluidDataStoreContext
990
991
  super.bindRuntime(dataStoreRuntime);
991
992
 
992
993
  if (this.isRootDataStore) {
993
- dataStoreRuntime.bindToContext();
994
+ dataStoreRuntime.attachGraph();
994
995
  }
995
996
  }
996
997
 
package/src/dataStores.ts CHANGED
@@ -64,7 +64,7 @@ export class DataStores implements IDisposable {
64
64
 
65
65
  private readonly logger: ITelemetryLogger;
66
66
 
67
- private readonly disposeOnce = new Lazy<void>(()=>this.contexts.dispose());
67
+ private readonly disposeOnce = new Lazy<void>(() => this.contexts.dispose());
68
68
 
69
69
  constructor(
70
70
  private readonly baseSnapshot: ISnapshotTree | undefined,
package/src/index.ts CHANGED
@@ -10,4 +10,4 @@ export * from "./pendingStateManager";
10
10
  export * from "./summarizer";
11
11
  export * from "./summarizerTypes";
12
12
  export * from "./summaryCollection";
13
- export { neverCancelledSummaryToken } from "./runWhileConnectedCoordinator";
13
+ export { ICancellableSummarizerController, neverCancelledSummaryToken } from "./runWhileConnectedCoordinator";
@@ -6,4 +6,4 @@
6
6
  */
7
7
 
8
8
  export const pkgName = "@fluidframework/container-runtime";
9
- export const pkgVersion = "0.49.2";
9
+ export const pkgVersion = "0.50.1";
package/src/summarizer.ts CHANGED
@@ -19,7 +19,7 @@ import {
19
19
  ISummaryConfiguration,
20
20
  } from "@fluidframework/protocol-definitions";
21
21
  import { create404Response } from "@fluidframework/runtime-utils";
22
- import { RunWhileConnectedCoordinator } from "./runWhileConnectedCoordinator";
22
+ import { ICancellableSummarizerController } from "./runWhileConnectedCoordinator";
23
23
  import { SummaryCollection } from "./summaryCollection";
24
24
  import { SummarizerHandle } from "./summarizerHandle";
25
25
  import { RunningSummarizer } from "./runningSummarizer";
@@ -32,6 +32,7 @@ import {
32
32
  SummarizerStopReason,
33
33
  } from "./summarizerTypes";
34
34
  import { SummarizeHeuristicData } from "./summarizerHeuristics";
35
+ import { IConnectableRuntime } from ".";
35
36
 
36
37
  const summarizingError = "summarizingError";
37
38
 
@@ -90,6 +91,8 @@ export class Summarizer extends EventEmitter implements ISummarizer {
90
91
  private readonly internalsProvider: ISummarizerInternalsProvider,
91
92
  handleContext: IFluidHandleContext,
92
93
  public readonly summaryCollection: SummaryCollection,
94
+ private readonly runCoordinatorCreateFn:
95
+ (runtime: IConnectableRuntime) => Promise<ICancellableSummarizerController>,
93
96
  ) {
94
97
  super();
95
98
  this.logger = ChildLogger.create(this.runtime.logger, "Summarizer");
@@ -142,7 +145,7 @@ export class Summarizer extends EventEmitter implements ISummarizer {
142
145
  initSummarySeqNumber: this.runtime.deltaManager.initialSequenceNumber,
143
146
  });
144
147
 
145
- const runCoordinator = await RunWhileConnectedCoordinator.create(this.runtime);
148
+ const runCoordinator: ICancellableSummarizerController = await this.runCoordinatorCreateFn(this.runtime);
146
149
 
147
150
  // Wait for either external signal to cancel, or loss of connectivity.
148
151
  const stopP = Promise.race([runCoordinator.waitCancelled, this.stopDeferred.promise]);
@@ -21,7 +21,7 @@ export interface ISummarizerClientElection extends IEventProvider<ISummarizerCli
21
21
 
22
22
  /**
23
23
  * This class encapsulates logic around tracking the elected summarizer client.
24
- * It will handle updated the elected client when a summary ack hasn't been seen
24
+ * It will handle updating the elected client when a summary ack hasn't been seen
25
25
  * for some configured number of ops.
26
26
  */
27
27
  export class SummarizerClientElection
@@ -7,7 +7,7 @@ import { IDisposable, IEvent, IEventProvider, ITelemetryLogger } from "@fluidfra
7
7
  import { TypedEventEmitter, assert } from "@fluidframework/common-utils";
8
8
  import { ChildLogger, PerformanceEvent } from "@fluidframework/telemetry-utils";
9
9
  import { IFluidRouter, IRequest } from "@fluidframework/core-interfaces";
10
- import { IDeltaManager, LoaderHeader } from "@fluidframework/container-definitions";
10
+ import { LoaderHeader } from "@fluidframework/container-definitions";
11
11
  import { DriverHeader } from "@fluidframework/driver-definitions";
12
12
  import { requestFluidObject } from "@fluidframework/runtime-utils";
13
13
  import { createSummarizingWarning } from "./summarizer";
@@ -358,26 +358,36 @@ export class SummaryManager extends TypedEventEmitter<ISummaryManagerEvents> imp
358
358
  }
359
359
  }
360
360
 
361
+ export interface ISummarizerRequestOptions {
362
+ cache: boolean,
363
+ reconnect: boolean,
364
+ summarizingClient: boolean,
365
+ }
366
+
361
367
  /**
362
368
  * Forms a function that will request a Summarizer.
363
369
  * @param loaderRouter - the loader acting as an IFluidRouter
364
- * @param deltaManager - delta manager to get last sequence number
370
+ * @param lastSequenceNumber - the last sequence number (e.g., from DeltaManager)
371
+ * @param cache - use cache to retrieve summarizer
372
+ * @param summarizingClient - is summarizer client
373
+ * @param reconnect - can reconnect on connection loss
365
374
  */
366
375
  export const formRequestSummarizerFn = (
367
376
  loaderRouter: IFluidRouter,
368
- deltaManager: Pick<IDeltaManager<unknown, unknown>, "lastSequenceNumber">,
377
+ lastSequenceNumber: number,
378
+ { cache, reconnect, summarizingClient }: ISummarizerRequestOptions,
369
379
  ) => async () => {
370
380
  // TODO eventually we may wish to spawn an execution context from which to run this
371
381
  const request: IRequest = {
372
382
  headers: {
373
- [LoaderHeader.cache]: false,
383
+ [LoaderHeader.cache]: cache,
374
384
  [LoaderHeader.clientDetails]: {
375
385
  capabilities: { interactive: false },
376
386
  type: summarizerClientType,
377
387
  },
378
- [DriverHeader.summarizingClient]: true,
379
- [LoaderHeader.reconnect]: false,
380
- [LoaderHeader.sequenceNumber]: deltaManager.lastSequenceNumber,
388
+ [DriverHeader.summarizingClient]: summarizingClient,
389
+ [LoaderHeader.reconnect]: reconnect,
390
+ [LoaderHeader.sequenceNumber]: lastSequenceNumber,
381
391
  },
382
392
  url: "/_summarizer",
383
393
  };