@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.
- package/dist/containerRuntime.d.ts +2 -2
- package/dist/containerRuntime.d.ts.map +1 -1
- package/dist/containerRuntime.js +73 -71
- package/dist/containerRuntime.js.map +1 -1
- package/dist/dataStoreContext.d.ts.map +1 -1
- package/dist/dataStoreContext.js +2 -1
- package/dist/dataStoreContext.js.map +1 -1
- package/dist/dataStores.d.ts.map +1 -1
- package/dist/dataStores.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/packageVersion.d.ts +1 -1
- package/dist/packageVersion.js +1 -1
- package/dist/packageVersion.js.map +1 -1
- package/dist/summarizer.d.ts +4 -1
- package/dist/summarizer.d.ts.map +1 -1
- package/dist/summarizer.js +3 -3
- package/dist/summarizer.js.map +1 -1
- package/dist/summarizerClientElection.d.ts +1 -1
- package/dist/summarizerClientElection.js +1 -1
- package/dist/summarizerClientElection.js.map +1 -1
- package/dist/summaryManager.d.ts +10 -3
- package/dist/summaryManager.d.ts.map +1 -1
- package/dist/summaryManager.js +9 -6
- package/dist/summaryManager.js.map +1 -1
- package/lib/containerRuntime.d.ts +2 -2
- package/lib/containerRuntime.d.ts.map +1 -1
- package/lib/containerRuntime.js +73 -71
- package/lib/containerRuntime.js.map +1 -1
- package/lib/dataStoreContext.d.ts.map +1 -1
- package/lib/dataStoreContext.js +2 -1
- package/lib/dataStoreContext.js.map +1 -1
- package/lib/dataStores.d.ts.map +1 -1
- package/lib/dataStores.js.map +1 -1
- package/lib/index.d.ts +1 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js.map +1 -1
- package/lib/packageVersion.d.ts +1 -1
- package/lib/packageVersion.js +1 -1
- package/lib/packageVersion.js.map +1 -1
- package/lib/summarizer.d.ts +4 -1
- package/lib/summarizer.d.ts.map +1 -1
- package/lib/summarizer.js +3 -3
- package/lib/summarizer.js.map +1 -1
- package/lib/summarizerClientElection.d.ts +1 -1
- package/lib/summarizerClientElection.js +1 -1
- package/lib/summarizerClientElection.js.map +1 -1
- package/lib/summaryManager.d.ts +10 -3
- package/lib/summaryManager.d.ts.map +1 -1
- package/lib/summaryManager.js +9 -6
- package/lib/summaryManager.js.map +1 -1
- package/package.json +16 -16
- package/src/containerRuntime.ts +106 -96
- package/src/dataStoreContext.ts +2 -1
- package/src/dataStores.ts +1 -1
- package/src/index.ts +1 -1
- package/src/packageVersion.ts +1 -1
- package/src/summarizer.ts +5 -2
- package/src/summarizerClientElection.ts +1 -1
- package/src/summaryManager.ts +17 -7
package/src/containerRuntime.ts
CHANGED
|
@@ -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
|
|
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
|
|
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
|
|
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(
|
|
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.
|
|
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
|
-
|
|
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
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
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
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
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
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
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
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
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
|
-
|
|
2263
|
-
|
|
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
|
-
|
|
2277
|
-
|
|
2278
|
-
|
|
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() {
|
package/src/dataStoreContext.ts
CHANGED
|
@@ -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.
|
|
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";
|
package/src/packageVersion.ts
CHANGED
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 {
|
|
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
|
|
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
|
|
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
|
package/src/summaryManager.ts
CHANGED
|
@@ -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 {
|
|
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
|
|
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
|
-
|
|
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]:
|
|
383
|
+
[LoaderHeader.cache]: cache,
|
|
374
384
|
[LoaderHeader.clientDetails]: {
|
|
375
385
|
capabilities: { interactive: false },
|
|
376
386
|
type: summarizerClientType,
|
|
377
387
|
},
|
|
378
|
-
[DriverHeader.summarizingClient]:
|
|
379
|
-
[LoaderHeader.reconnect]:
|
|
380
|
-
[LoaderHeader.sequenceNumber]:
|
|
388
|
+
[DriverHeader.summarizingClient]: summarizingClient,
|
|
389
|
+
[LoaderHeader.reconnect]: reconnect,
|
|
390
|
+
[LoaderHeader.sequenceNumber]: lastSequenceNumber,
|
|
381
391
|
},
|
|
382
392
|
url: "/_summarizer",
|
|
383
393
|
};
|