Skip to content

Commit a104f51

Browse files
jatgargJatin Garg
andauthored
Delay load parts of summary module to reduce the container runtime bundle size. (#24161)
## Description This redccues bundle size of container runtime by ~20KB. Delay load parts of summary module like RunningSummarizer, SummaryGenerator etc to reduce the container runtime bundle size. This effort is done as part of reducing fluid bundle size for loop so as to make uop for some of the increased bundle size due to new shared tree. --------- Co-authored-by: Jatin Garg <[email protected]>
1 parent f2c6567 commit a104f51

18 files changed

+597
-500
lines changed

packages/runtime/container-runtime/src/containerRuntime.ts

Lines changed: 157 additions & 140 deletions
Large diffs are not rendered by default.

packages/runtime/container-runtime/src/summary/index.ts

Lines changed: 35 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -3,31 +3,6 @@
33
* Licensed under the MIT License.
44
*/
55

6-
export {
7-
IOrderedClientCollection,
8-
IOrderedClientElection,
9-
ISerializedElection,
10-
ITrackedClient,
11-
OrderedClientCollection,
12-
OrderedClientElection,
13-
} from "./orderedClientElection.js";
14-
export {
15-
defaultMaxAttemptsForSubmitFailures,
16-
RunningSummarizer,
17-
} from "./runningSummarizer.js";
18-
export {
19-
ICancellableSummarizerController,
20-
neverCancelledSummaryToken,
21-
RunWhileConnectedCoordinator,
22-
} from "./runWhileConnectedCoordinator.js";
23-
export { Summarizer } from "./summarizer.js";
24-
export {
25-
ISummarizerClientElection,
26-
ISummarizerClientElectionEvents,
27-
SummarizerClientElection,
28-
summarizerClientType,
29-
} from "./summarizerClientElection.js";
30-
export { SummarizeHeuristicData, SummarizeHeuristicRunner } from "./summarizerHeuristics.js";
316
export {
327
createRootSummarizerNode,
338
createRootSummarizerNodeWithGC,
@@ -36,26 +11,22 @@ export {
3611
IRootSummarizerNodeWithGC,
3712
} from "./summarizerNode/index.js";
3813
export {
14+
summarizerClientType,
3915
IConnectableRuntime,
4016
IGeneratedSummaryStats,
4117
IRefreshSummaryAckOptions,
4218
ISubmitSummaryOptions,
4319
ISummarizeAttempt,
4420
ISummarizeHeuristicData,
4521
ISummarizer,
46-
ISummarizeResults,
4722
ISummarizerInternalsProvider,
4823
ISummarizerRuntime,
4924
ISummaryCancellationToken,
5025
SubmitSummaryResult,
51-
EnqueueSummarizeResult,
52-
IAckSummaryResult,
5326
IBaseSummarizeResult,
54-
IBroadcastSummaryResult,
5527
ICancellationToken,
5628
IEnqueueSummarizeOptions,
5729
IGenerateSummaryTreeResult,
58-
INackSummaryResult,
5930
IOnDemandSummarizeOptions,
6031
ISubmitSummaryOpResult,
6132
ISummarizeOptions,
@@ -71,6 +42,14 @@ export {
7142
type ISummaryConfigurationHeuristics,
7243
type ISummaryBaseConfiguration,
7344
} from "./summarizerTypes.js";
45+
export {
46+
IOrderedClientCollection,
47+
IOrderedClientElection,
48+
ISerializedElection,
49+
ITrackedClient,
50+
OrderedClientCollection,
51+
OrderedClientElection,
52+
} from "./orderedClientElection.js";
7453
export {
7554
IAckedSummary,
7655
ISummaryCollectionOpEvents,
@@ -83,6 +62,11 @@ export {
8362
OpActionEventListener,
8463
OpActionEventName,
8564
} from "./summaryCollection.js";
65+
export {
66+
ISummarizerClientElection,
67+
ISummarizerClientElectionEvents,
68+
SummarizerClientElection,
69+
} from "./summarizerClientElection.js";
8670
export {
8771
aliasBlobName,
8872
chunksBlobName,
@@ -125,11 +109,31 @@ export {
125109
IDocumentSchemaChangeMessage,
126110
IDocumentSchemaFeatures,
127111
} from "./documentSchema.js";
128-
export { getFailMessage, RetriableSummaryError, SummarizeReason } from "./summaryGenerator.js";
112+
export {
113+
getFailMessage,
114+
RetriableSummaryError,
115+
SummarizeReason,
116+
} from "./summarizerUtils.js";
129117
export {
130118
IConnectedEvents,
131119
IConnectedState,
132120
ISummaryManagerConfig,
133121
SummaryManager,
134122
SummaryManagerState,
135123
} from "./summaryManager.js";
124+
export {
125+
defaultMaxAttempts,
126+
defaultMaxAttemptsForSubmitFailures,
127+
ICancellableSummarizerController,
128+
neverCancelledSummaryToken,
129+
RunWhileConnectedCoordinator,
130+
Summarizer,
131+
IBroadcastSummaryResult,
132+
ISummarizeResults,
133+
EnqueueSummarizeResult,
134+
IAckSummaryResult,
135+
INackSummaryResult,
136+
RunningSummarizer,
137+
SummarizeHeuristicData,
138+
SummarizeHeuristicRunner,
139+
} from "./summaryDelayLoadedModule/index.js";

packages/runtime/container-runtime/src/summary/orderedClientElection.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import {
1616
createChildLogger,
1717
} from "@fluidframework/telemetry-utils/internal";
1818

19-
import { summarizerClientType } from "./summarizerClientElection.js";
19+
import { summarizerClientType } from "./index.js";
2020

2121
// helper types for recursive readonly.
2222
// eslint-disable-next-line @typescript-eslint/ban-types

packages/runtime/container-runtime/src/summary/summarizerClientElection.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,9 @@ import {
1414
ISerializedElection,
1515
ITrackedClient,
1616
} from "./orderedClientElection.js";
17+
import { summarizerClientType } from "./summarizerTypes.js";
1718
import { ISummaryCollectionOpEvents } from "./summaryCollection.js";
1819

19-
export const summarizerClientType = "summarizer";
20-
2120
export interface ISummarizerClientElectionEvents extends IEvent {
2221
(event: "electedSummarizerChanged", handler: () => void): void;
2322
}

packages/runtime/container-runtime/src/summary/summarizerTypes.ts

Lines changed: 7 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,13 @@ import {
2727
ITelemetryLoggerPropertyBag,
2828
} from "@fluidframework/telemetry-utils/internal";
2929

30-
import {
31-
ISummaryAckMessage,
32-
ISummaryNackMessage,
33-
ISummaryOpMessage,
34-
} from "./summaryCollection.js";
35-
import { SummarizeReason } from "./summaryGenerator.js";
30+
import type { SummarizeReason } from "./summarizerUtils.js";
31+
import type {
32+
EnqueueSummarizeResult,
33+
ISummarizeResults,
34+
} from "./summaryDelayLoadedModule/index.js";
35+
36+
export const summarizerClientType = "summarizer";
3637

3738
/**
3839
* Similar to AbortSignal, but using promise instead of events
@@ -359,33 +360,6 @@ export interface SubmitSummaryFailureData {
359360
stage: SummaryStage;
360361
}
361362

362-
/**
363-
* @legacy
364-
* @alpha
365-
*/
366-
export interface IBroadcastSummaryResult {
367-
readonly summarizeOp: ISummaryOpMessage;
368-
readonly broadcastDuration: number;
369-
}
370-
371-
/**
372-
* @legacy
373-
* @alpha
374-
*/
375-
export interface IAckSummaryResult {
376-
readonly summaryAckOp: ISummaryAckMessage;
377-
readonly ackNackDuration: number;
378-
}
379-
380-
/**
381-
* @legacy
382-
* @alpha
383-
*/
384-
export interface INackSummaryResult {
385-
readonly summaryNackOp: ISummaryNackMessage;
386-
readonly ackNackDuration: number;
387-
}
388-
389363
/**
390364
* @legacy
391365
* @alpha
@@ -402,64 +376,6 @@ export type SummarizeResultPart<TSuccess, TFailure = undefined> =
402376
error: IRetriableFailureError;
403377
};
404378

405-
/**
406-
* @legacy
407-
* @alpha
408-
*/
409-
export interface ISummarizeResults {
410-
/**
411-
* Resolves when we generate, upload, and submit the summary.
412-
*/
413-
readonly summarySubmitted: Promise<
414-
SummarizeResultPart<SubmitSummaryResult, SubmitSummaryFailureData>
415-
>;
416-
/**
417-
* Resolves when we observe our summarize op broadcast.
418-
*/
419-
readonly summaryOpBroadcasted: Promise<SummarizeResultPart<IBroadcastSummaryResult>>;
420-
/**
421-
* Resolves when we receive a summaryAck or summaryNack.
422-
*/
423-
readonly receivedSummaryAckOrNack: Promise<
424-
SummarizeResultPart<IAckSummaryResult, INackSummaryResult>
425-
>;
426-
}
427-
428-
/**
429-
* @legacy
430-
* @alpha
431-
*/
432-
export type EnqueueSummarizeResult =
433-
| (ISummarizeResults & {
434-
/**
435-
* Indicates that another summarize attempt is not already enqueued,
436-
* and this attempt has been enqueued.
437-
*/
438-
readonly alreadyEnqueued?: undefined;
439-
})
440-
| (ISummarizeResults & {
441-
/**
442-
* Indicates that another summarize attempt was already enqueued.
443-
*/
444-
readonly alreadyEnqueued: true;
445-
/**
446-
* Indicates that the other enqueued summarize attempt was abandoned,
447-
* and this attempt has been enqueued enqueued.
448-
*/
449-
readonly overridden: true;
450-
})
451-
| {
452-
/**
453-
* Indicates that another summarize attempt was already enqueued.
454-
*/
455-
readonly alreadyEnqueued: true;
456-
/**
457-
* Indicates that the other enqueued summarize attempt remains enqueued,
458-
* and this attempt has not been enqueued.
459-
*/
460-
readonly overridden?: undefined;
461-
};
462-
463379
/**
464380
* @legacy
465381
* @alpha
Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
/*!
2+
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3+
* Licensed under the MIT License.
4+
*/
5+
6+
import type { SummarizerStopReason } from "@fluidframework/container-runtime-definitions/internal";
7+
import { ITelemetryBaseProperties } from "@fluidframework/core-interfaces";
8+
import { IPromiseTimerResult } from "@fluidframework/core-utils/internal";
9+
import { LoggingError } from "@fluidframework/telemetry-utils/internal";
10+
11+
import { ISummaryCancellationToken, type IRetriableFailureError } from "./summarizerTypes.js";
12+
13+
export type raceTimerResult<T> =
14+
| { result: "done"; value: T }
15+
| { result: IPromiseTimerResult["timerResult"] }
16+
| { result: "cancelled" };
17+
18+
/**
19+
* Wait for a promise or PromiseTimer to elapse.
20+
*/
21+
export async function raceTimer<T>(
22+
promise: Promise<T>,
23+
timer: Promise<IPromiseTimerResult>,
24+
25+
cancellationToken?: ISummaryCancellationToken,
26+
): Promise<raceTimerResult<T>> {
27+
const promises: Promise<raceTimerResult<T>>[] = [
28+
promise.then((value) => ({ result: "done", value }) as const),
29+
timer.then(({ timerResult: result }) => ({ result }) as const),
30+
];
31+
if (cancellationToken !== undefined) {
32+
promises.push(
33+
cancellationToken.waitCancelled.then(() => ({ result: "cancelled" }) as const),
34+
);
35+
}
36+
return Promise.race(promises);
37+
}
38+
39+
/**
40+
* Should we try to run a last summary for the given stop reason?
41+
* Currently only allows "parentNotConnected"
42+
* @param stopReason - SummarizerStopReason
43+
* @returns `true` if the stop reason can run a last summary, otherwise `false`.
44+
*/
45+
export function stopReasonCanRunLastSummary(stopReason: SummarizerStopReason): boolean {
46+
return stopReason === "parentNotConnected";
47+
}
48+
49+
export type SummarizeReason =
50+
/**
51+
* Attempt to summarize after idle timeout has elapsed.
52+
* Idle timer restarts whenever an op is received. So this
53+
* triggers only after some amount of time has passed with
54+
* no ops being received.
55+
*/
56+
| "idle"
57+
/**
58+
* Attempt to summarize after a maximum time since last
59+
* successful summary has passed. This measures time since
60+
* last summary ack op was processed.
61+
*/
62+
| "maxTime"
63+
/**
64+
* Attempt to summarize after a maximum number of ops have
65+
* passed since the last successful summary. This compares
66+
* op sequence numbers with the reference sequence number
67+
* of the summarize op corresponding to the last summary
68+
* ack op.
69+
*/
70+
| "maxOps"
71+
/**
72+
* Special case to attempt to summarize one last time before the
73+
* summarizer client closes itself. This is to prevent cases where
74+
* the summarizer client never gets a chance to summarize, because
75+
* there are too many outstanding ops and/or parent client cannot
76+
* stay connected long enough for summarizer client to catch up.
77+
*/
78+
| "lastSummary"
79+
/**
80+
* On-demand summary requested with specified reason.
81+
*/
82+
| `onDemand;${string}`
83+
/**
84+
* Enqueue summarize attempt with specified reason.
85+
*/
86+
| `enqueue;${string}`;
87+
88+
const summarizeErrors = {
89+
/**
90+
* Error encountered while generating the summary tree, uploading
91+
* it to storage, or submitting the op. It could be a result of
92+
* the client becoming disconnected while generating or an actual error.
93+
*/
94+
submitSummaryFailure: "Error while generating, uploading, or submitting summary",
95+
/**
96+
* The summaryAckWaitTimeout time has elapsed before receiving the summarize op
97+
* sent by this summarize attempt. It is expected to be broadcast quickly.
98+
*/
99+
summaryOpWaitTimeout: "Timeout while waiting for summarize op broadcast",
100+
/**
101+
* The summaryAckWaitTimeout time has elapsed before receiving either a
102+
* summaryAck or summaryNack op from the server in response to this
103+
* summarize attempt. It is expected that the server should respond.
104+
*/
105+
summaryAckWaitTimeout: "Timeout while waiting for summaryAck/summaryNack op",
106+
/**
107+
* The server responded with a summaryNack op, thus rejecting this
108+
* summarize attempt.
109+
*/
110+
summaryNack: "Server rejected summary via summaryNack op",
111+
112+
disconnect: "Summary cancelled due to summarizer or main client disconnect",
113+
} as const;
114+
115+
export type SummarizeErrorCode = keyof typeof summarizeErrors;
116+
117+
// Helper functions to report failures and return.
118+
export const getFailMessage = (errorCode: SummarizeErrorCode): string =>
119+
`${errorCode}: ${summarizeErrors[errorCode]}`;
120+
121+
/**
122+
* Errors type for errors hit during summary that may be retriable.
123+
*/
124+
export class RetriableSummaryError extends LoggingError implements IRetriableFailureError {
125+
constructor(
126+
message: string,
127+
public readonly retryAfterSeconds?: number,
128+
props?: ITelemetryBaseProperties,
129+
) {
130+
super(message, props);
131+
}
132+
}

0 commit comments

Comments
 (0)