@fluidframework/container-loader 2.1.0-274160 → 2.1.0-276326
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/.eslintrc.cjs +2 -5
- package/dist/attachment.d.ts +2 -1
- package/dist/attachment.d.ts.map +1 -1
- package/dist/attachment.js.map +1 -1
- package/dist/audience.d.ts.map +1 -1
- package/dist/audience.js +4 -4
- package/dist/audience.js.map +1 -1
- package/dist/catchUpMonitor.d.ts +15 -4
- package/dist/catchUpMonitor.d.ts.map +1 -1
- package/dist/catchUpMonitor.js +12 -3
- package/dist/catchUpMonitor.js.map +1 -1
- package/dist/connectionManager.d.ts +24 -8
- package/dist/connectionManager.d.ts.map +1 -1
- package/dist/connectionManager.js +36 -23
- package/dist/connectionManager.js.map +1 -1
- package/dist/connectionStateHandler.d.ts +30 -20
- package/dist/connectionStateHandler.d.ts.map +1 -1
- package/dist/connectionStateHandler.js +15 -11
- package/dist/connectionStateHandler.js.map +1 -1
- package/dist/container.d.ts +7 -2
- package/dist/container.d.ts.map +1 -1
- package/dist/container.js +53 -32
- package/dist/container.js.map +1 -1
- package/dist/containerContext.d.ts +8 -4
- package/dist/containerContext.d.ts.map +1 -1
- package/dist/containerContext.js +3 -1
- package/dist/containerContext.js.map +1 -1
- package/dist/containerStorageAdapter.d.ts +1 -1
- package/dist/containerStorageAdapter.d.ts.map +1 -1
- package/dist/containerStorageAdapter.js +12 -6
- package/dist/containerStorageAdapter.js.map +1 -1
- package/dist/contracts.d.ts +17 -8
- package/dist/contracts.d.ts.map +1 -1
- package/dist/contracts.js +4 -2
- package/dist/contracts.js.map +1 -1
- package/dist/debugLogger.js +3 -3
- package/dist/debugLogger.js.map +1 -1
- package/dist/deltaManager.d.ts +13 -9
- package/dist/deltaManager.d.ts.map +1 -1
- package/dist/deltaManager.js +32 -23
- package/dist/deltaManager.js.map +1 -1
- package/dist/deltaQueue.d.ts +1 -4
- package/dist/deltaQueue.d.ts.map +1 -1
- package/dist/deltaQueue.js +2 -2
- package/dist/deltaQueue.js.map +1 -1
- package/dist/disposal.d.ts +1 -1
- package/dist/disposal.d.ts.map +1 -1
- package/dist/disposal.js.map +1 -1
- package/dist/error.d.ts.map +1 -1
- package/dist/error.js.map +1 -1
- package/dist/legacy.d.ts +1 -1
- package/dist/loadPaused.d.ts +2 -2
- package/dist/loadPaused.d.ts.map +1 -1
- package/dist/loadPaused.js +7 -3
- package/dist/loadPaused.js.map +1 -1
- package/dist/loader.d.ts +10 -1
- package/dist/loader.d.ts.map +1 -1
- package/dist/loader.js +11 -1
- package/dist/loader.js.map +1 -1
- package/dist/location-redirection-utilities/resolveWithLocationRedirection.d.ts +2 -1
- package/dist/location-redirection-utilities/resolveWithLocationRedirection.d.ts.map +1 -1
- package/dist/location-redirection-utilities/resolveWithLocationRedirection.js +3 -1
- package/dist/location-redirection-utilities/resolveWithLocationRedirection.js.map +1 -1
- package/dist/memoryBlobStorage.d.ts +2 -2
- package/dist/memoryBlobStorage.d.ts.map +1 -1
- package/dist/memoryBlobStorage.js +7 -3
- package/dist/memoryBlobStorage.js.map +1 -1
- package/dist/noopHeuristic.js +1 -1
- package/dist/noopHeuristic.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/protocol/protocol.d.ts +4 -3
- package/dist/protocol/protocol.d.ts.map +1 -1
- package/dist/protocol/protocol.js +6 -5
- package/dist/protocol/protocol.js.map +1 -1
- package/dist/protocol/quorum.d.ts +11 -8
- package/dist/protocol/quorum.d.ts.map +1 -1
- package/dist/protocol/quorum.js +8 -8
- package/dist/protocol/quorum.js.map +1 -1
- package/dist/protocol.d.ts +2 -0
- package/dist/protocol.d.ts.map +1 -1
- package/dist/protocol.js +7 -2
- package/dist/protocol.js.map +1 -1
- package/dist/protocolTreeDocumentStorageService.d.ts +2 -2
- package/dist/protocolTreeDocumentStorageService.d.ts.map +1 -1
- package/dist/protocolTreeDocumentStorageService.js.map +1 -1
- package/dist/retriableDocumentStorageService.d.ts.map +1 -1
- package/dist/retriableDocumentStorageService.js +4 -1
- package/dist/retriableDocumentStorageService.js.map +1 -1
- package/dist/serializedStateManager.d.ts +29 -12
- package/dist/serializedStateManager.d.ts.map +1 -1
- package/dist/serializedStateManager.js +55 -24
- package/dist/serializedStateManager.js.map +1 -1
- package/dist/utils.d.ts +4 -2
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +15 -6
- package/dist/utils.js.map +1 -1
- package/lib/attachment.d.ts +2 -1
- package/lib/attachment.d.ts.map +1 -1
- package/lib/attachment.js.map +1 -1
- package/lib/audience.d.ts.map +1 -1
- package/lib/audience.js +4 -4
- package/lib/audience.js.map +1 -1
- package/lib/catchUpMonitor.d.ts +15 -4
- package/lib/catchUpMonitor.d.ts.map +1 -1
- package/lib/catchUpMonitor.js +12 -3
- package/lib/catchUpMonitor.js.map +1 -1
- package/lib/connectionManager.d.ts +24 -8
- package/lib/connectionManager.d.ts.map +1 -1
- package/lib/connectionManager.js +36 -23
- package/lib/connectionManager.js.map +1 -1
- package/lib/connectionStateHandler.d.ts +30 -20
- package/lib/connectionStateHandler.d.ts.map +1 -1
- package/lib/connectionStateHandler.js +14 -12
- package/lib/connectionStateHandler.js.map +1 -1
- package/lib/container.d.ts +7 -2
- package/lib/container.d.ts.map +1 -1
- package/lib/container.js +53 -32
- package/lib/container.js.map +1 -1
- package/lib/containerContext.d.ts +8 -4
- package/lib/containerContext.d.ts.map +1 -1
- package/lib/containerContext.js +3 -1
- package/lib/containerContext.js.map +1 -1
- package/lib/containerStorageAdapter.d.ts +1 -1
- package/lib/containerStorageAdapter.d.ts.map +1 -1
- package/lib/containerStorageAdapter.js +12 -6
- package/lib/containerStorageAdapter.js.map +1 -1
- package/lib/contracts.d.ts +17 -8
- package/lib/contracts.d.ts.map +1 -1
- package/lib/contracts.js +4 -2
- package/lib/contracts.js.map +1 -1
- package/lib/debugLogger.js +3 -3
- package/lib/debugLogger.js.map +1 -1
- package/lib/deltaManager.d.ts +13 -9
- package/lib/deltaManager.d.ts.map +1 -1
- package/lib/deltaManager.js +32 -23
- package/lib/deltaManager.js.map +1 -1
- package/lib/deltaQueue.d.ts +1 -4
- package/lib/deltaQueue.d.ts.map +1 -1
- package/lib/deltaQueue.js +2 -2
- package/lib/deltaQueue.js.map +1 -1
- package/lib/disposal.d.ts +1 -1
- package/lib/disposal.d.ts.map +1 -1
- package/lib/disposal.js.map +1 -1
- package/lib/error.d.ts.map +1 -1
- package/lib/error.js.map +1 -1
- package/lib/legacy.d.ts +1 -1
- package/lib/loadPaused.d.ts +2 -2
- package/lib/loadPaused.d.ts.map +1 -1
- package/lib/loadPaused.js +8 -4
- package/lib/loadPaused.js.map +1 -1
- package/lib/loader.d.ts +10 -1
- package/lib/loader.d.ts.map +1 -1
- package/lib/loader.js +11 -1
- package/lib/loader.js.map +1 -1
- package/lib/location-redirection-utilities/resolveWithLocationRedirection.d.ts +2 -1
- package/lib/location-redirection-utilities/resolveWithLocationRedirection.d.ts.map +1 -1
- package/lib/location-redirection-utilities/resolveWithLocationRedirection.js +3 -1
- package/lib/location-redirection-utilities/resolveWithLocationRedirection.js.map +1 -1
- package/lib/memoryBlobStorage.d.ts +2 -2
- package/lib/memoryBlobStorage.d.ts.map +1 -1
- package/lib/memoryBlobStorage.js +7 -3
- package/lib/memoryBlobStorage.js.map +1 -1
- package/lib/noopHeuristic.js +1 -1
- package/lib/noopHeuristic.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/protocol/protocol.d.ts +4 -3
- package/lib/protocol/protocol.d.ts.map +1 -1
- package/lib/protocol/protocol.js +6 -5
- package/lib/protocol/protocol.js.map +1 -1
- package/lib/protocol/quorum.d.ts +11 -8
- package/lib/protocol/quorum.d.ts.map +1 -1
- package/lib/protocol/quorum.js +8 -8
- package/lib/protocol/quorum.js.map +1 -1
- package/lib/protocol.d.ts +2 -0
- package/lib/protocol.d.ts.map +1 -1
- package/lib/protocol.js +7 -2
- package/lib/protocol.js.map +1 -1
- package/lib/protocolTreeDocumentStorageService.d.ts +2 -2
- package/lib/protocolTreeDocumentStorageService.d.ts.map +1 -1
- package/lib/protocolTreeDocumentStorageService.js.map +1 -1
- package/lib/retriableDocumentStorageService.d.ts.map +1 -1
- package/lib/retriableDocumentStorageService.js +4 -1
- package/lib/retriableDocumentStorageService.js.map +1 -1
- package/lib/serializedStateManager.d.ts +29 -12
- package/lib/serializedStateManager.d.ts.map +1 -1
- package/lib/serializedStateManager.js +56 -25
- package/lib/serializedStateManager.js.map +1 -1
- package/lib/utils.d.ts +4 -2
- package/lib/utils.d.ts.map +1 -1
- package/lib/utils.js +16 -7
- package/lib/utils.js.map +1 -1
- package/package.json +13 -13
- package/src/attachment.ts +2 -1
- package/src/audience.ts +4 -4
- package/src/catchUpMonitor.ts +23 -8
- package/src/connectionManager.ts +85 -60
- package/src/connectionStateHandler.ts +85 -63
- package/src/container.ts +129 -89
- package/src/containerContext.ts +5 -3
- package/src/containerStorageAdapter.ts +20 -13
- package/src/contracts.ts +21 -9
- package/src/debugLogger.ts +4 -4
- package/src/deltaManager.ts +75 -56
- package/src/deltaQueue.ts +16 -10
- package/src/disposal.ts +3 -3
- package/src/error.ts +2 -1
- package/src/loadPaused.ts +16 -8
- package/src/loader.ts +20 -2
- package/src/location-redirection-utilities/resolveWithLocationRedirection.ts +7 -3
- package/src/memoryBlobStorage.ts +13 -7
- package/src/noopHeuristic.ts +1 -1
- package/src/packageVersion.ts +1 -1
- package/src/protocol/protocol.ts +12 -11
- package/src/protocol/quorum.ts +49 -40
- package/src/protocol.ts +12 -4
- package/src/protocolTreeDocumentStorageService.ts +3 -2
- package/src/retriableDocumentStorageService.ts +6 -3
- package/src/serializedStateManager.ts +95 -39
- package/src/utils.ts +26 -10
- /package/api-report/{container-loader.alpha.api.md → container-loader.legacy.alpha.api.md} +0 -0
package/src/container.ts
CHANGED
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
+
/* eslint-disable unicorn/consistent-function-scoping */
|
|
7
|
+
|
|
6
8
|
import { TypedEventEmitter, performance } from "@fluid-internal/client-utils";
|
|
7
9
|
import {
|
|
8
10
|
AttachState,
|
|
@@ -64,6 +66,7 @@ import {
|
|
|
64
66
|
MessageType,
|
|
65
67
|
ISequencedDocumentMessage,
|
|
66
68
|
ISignalMessage,
|
|
69
|
+
type ConnectionMode,
|
|
67
70
|
} from "@fluidframework/driver-definitions/internal";
|
|
68
71
|
import {
|
|
69
72
|
getSnapshotTree,
|
|
@@ -74,6 +77,7 @@ import {
|
|
|
74
77
|
isOnline,
|
|
75
78
|
readAndParse,
|
|
76
79
|
runWithRetry,
|
|
80
|
+
type CombinedAppAndProtocolSummary,
|
|
77
81
|
} from "@fluidframework/driver-utils/internal";
|
|
78
82
|
import {
|
|
79
83
|
type TelemetryEventCategory,
|
|
@@ -92,6 +96,7 @@ import {
|
|
|
92
96
|
raiseConnectedEvent,
|
|
93
97
|
wrapError,
|
|
94
98
|
loggerToMonitoringContext,
|
|
99
|
+
type ITelemetryErrorEventExt,
|
|
95
100
|
} from "@fluidframework/telemetry-utils/internal";
|
|
96
101
|
import structuredClone from "@ungap/structured-clone";
|
|
97
102
|
import { v4 as uuid } from "uuid";
|
|
@@ -257,9 +262,10 @@ export interface IContainerCreateProps {
|
|
|
257
262
|
* but it maybe still behind.
|
|
258
263
|
*
|
|
259
264
|
* @throws an error beginning with `"Container closed"` if the container is closed before it catches up.
|
|
265
|
+
* @legacy
|
|
260
266
|
* @alpha
|
|
261
267
|
*/
|
|
262
|
-
export async function waitContainerToCatchUp(container: IContainer) {
|
|
268
|
+
export async function waitContainerToCatchUp(container: IContainer): Promise<boolean> {
|
|
263
269
|
// Make sure we stop waiting if container is closed.
|
|
264
270
|
if (container.closed) {
|
|
265
271
|
throw new UsageError("waitContainerToCatchUp: Container closed");
|
|
@@ -268,16 +274,16 @@ export async function waitContainerToCatchUp(container: IContainer) {
|
|
|
268
274
|
return new Promise<boolean>((resolve, reject) => {
|
|
269
275
|
const deltaManager = container.deltaManager;
|
|
270
276
|
|
|
271
|
-
const closedCallback = (err?: ICriticalContainerError | undefined) => {
|
|
277
|
+
const closedCallback = (err?: ICriticalContainerError | undefined): void => {
|
|
272
278
|
container.off("closed", closedCallback);
|
|
273
279
|
const baseMessage = "Container closed while waiting to catch up";
|
|
274
280
|
reject(
|
|
275
|
-
err
|
|
276
|
-
?
|
|
281
|
+
err === undefined
|
|
282
|
+
? new GenericError(baseMessage)
|
|
283
|
+
: wrapError(
|
|
277
284
|
err,
|
|
278
285
|
(innerMessage) => new GenericError(`${baseMessage}: ${innerMessage}`),
|
|
279
|
-
)
|
|
280
|
-
: new GenericError(baseMessage),
|
|
286
|
+
),
|
|
281
287
|
);
|
|
282
288
|
};
|
|
283
289
|
container.on("closed", closedCallback);
|
|
@@ -286,7 +292,7 @@ export async function waitContainerToCatchUp(container: IContainer) {
|
|
|
286
292
|
// that all known ops have been processed. If so, we may introduce additional wait here.
|
|
287
293
|
// Waiting for "connected" state in either case gets us at least to our own Join op
|
|
288
294
|
// which is a reasonable approximation of "caught up"
|
|
289
|
-
const waitForOps = () => {
|
|
295
|
+
const waitForOps = (): void => {
|
|
290
296
|
assert(
|
|
291
297
|
container.connectionState === ConnectionState.CatchingUp ||
|
|
292
298
|
container.connectionState === ConnectionState.Connected,
|
|
@@ -304,7 +310,7 @@ export async function waitContainerToCatchUp(container: IContainer) {
|
|
|
304
310
|
resolve(hasCheckpointSequenceNumber);
|
|
305
311
|
return;
|
|
306
312
|
}
|
|
307
|
-
const callbackOps = (message: ISequencedDocumentMessage) => {
|
|
313
|
+
const callbackOps = (message: ISequencedDocumentMessage): void => {
|
|
308
314
|
if (connectionOpSeqNumber <= message.sequenceNumber) {
|
|
309
315
|
container.off("closed", closedCallback);
|
|
310
316
|
resolve(hasCheckpointSequenceNumber);
|
|
@@ -323,7 +329,7 @@ export async function waitContainerToCatchUp(container: IContainer) {
|
|
|
323
329
|
return;
|
|
324
330
|
}
|
|
325
331
|
|
|
326
|
-
const callback = () => {
|
|
332
|
+
const callback = (): void => {
|
|
327
333
|
container.off(connectedEventName, callback);
|
|
328
334
|
waitForOps();
|
|
329
335
|
};
|
|
@@ -335,7 +341,7 @@ export async function waitContainerToCatchUp(container: IContainer) {
|
|
|
335
341
|
});
|
|
336
342
|
}
|
|
337
343
|
|
|
338
|
-
const getCodeProposal = (quorum: IQuorumProposals) =>
|
|
344
|
+
const getCodeProposal = (quorum: IQuorumProposals): unknown =>
|
|
339
345
|
quorum.get("code") ?? quorum.get("code2");
|
|
340
346
|
|
|
341
347
|
/**
|
|
@@ -348,7 +354,7 @@ export async function ReportIfTooLong(
|
|
|
348
354
|
logger: ITelemetryLoggerExt,
|
|
349
355
|
eventName: string,
|
|
350
356
|
action: () => Promise<ITelemetryBaseProperties>,
|
|
351
|
-
) {
|
|
357
|
+
): Promise<void> {
|
|
352
358
|
const event = PerformanceEvent.start(logger, { eventName });
|
|
353
359
|
const props = await action();
|
|
354
360
|
if (event.duration > 200) {
|
|
@@ -390,7 +396,7 @@ export class Container
|
|
|
390
396
|
? { ...(loadMode ?? defaultMode), opsBeforeReturn: undefined }
|
|
391
397
|
: loadMode ?? defaultMode;
|
|
392
398
|
|
|
393
|
-
const onClosed = (err?: ICriticalContainerError) => {
|
|
399
|
+
const onClosed = (err?: ICriticalContainerError): void => {
|
|
394
400
|
// pre-0.58 error message: containerClosedWithoutErrorDuringLoad
|
|
395
401
|
reject(err ?? new GenericError("Container closed without error during load"));
|
|
396
402
|
};
|
|
@@ -480,7 +486,7 @@ export class Container
|
|
|
480
486
|
private readonly scope: FluidObject;
|
|
481
487
|
private readonly subLogger: ITelemetryLoggerExt;
|
|
482
488
|
// eslint-disable-next-line import/no-deprecated
|
|
483
|
-
private readonly detachedBlobStorage: IDetachedBlobStorage;
|
|
489
|
+
private readonly detachedBlobStorage: IDetachedBlobStorage | undefined;
|
|
484
490
|
private readonly protocolHandlerBuilder: ProtocolHandlerBuilder;
|
|
485
491
|
private readonly client: IClient;
|
|
486
492
|
|
|
@@ -517,7 +523,7 @@ export class Container
|
|
|
517
523
|
| "closed"
|
|
518
524
|
| "disposed" = "loading";
|
|
519
525
|
|
|
520
|
-
private setLoaded() {
|
|
526
|
+
private setLoaded(): void {
|
|
521
527
|
// It's conceivable the container could be closed when this is called
|
|
522
528
|
// Only transition states if currently loading
|
|
523
529
|
if (this._lifecycleState === "loading") {
|
|
@@ -577,21 +583,23 @@ export class Container
|
|
|
577
583
|
private service: IDocumentService | undefined;
|
|
578
584
|
|
|
579
585
|
private _runtime: IRuntime | undefined;
|
|
580
|
-
private get runtime() {
|
|
586
|
+
private get runtime(): IRuntime {
|
|
581
587
|
if (this._runtime === undefined) {
|
|
582
588
|
throw new Error("Attempted to access runtime before it was defined");
|
|
583
589
|
}
|
|
584
590
|
return this._runtime;
|
|
585
591
|
}
|
|
586
592
|
private _protocolHandler: IProtocolHandler | undefined;
|
|
587
|
-
private get protocolHandler() {
|
|
593
|
+
private get protocolHandler(): IProtocolHandler {
|
|
588
594
|
if (this._protocolHandler === undefined) {
|
|
589
595
|
throw new Error("Attempted to access protocolHandler before it was defined");
|
|
590
596
|
}
|
|
591
597
|
return this._protocolHandler;
|
|
592
598
|
}
|
|
593
599
|
|
|
594
|
-
/**
|
|
600
|
+
/**
|
|
601
|
+
* During initialization we pause the inbound queues. We track this state to ensure we only call resume once
|
|
602
|
+
*/
|
|
595
603
|
private inboundQueuePausedFromInit = true;
|
|
596
604
|
private firstConnection = true;
|
|
597
605
|
private readonly connectionTransitionTimes: number[] = [];
|
|
@@ -611,7 +619,7 @@ export class Container
|
|
|
611
619
|
|
|
612
620
|
private noopHeuristic: NoopHeuristic | undefined;
|
|
613
621
|
|
|
614
|
-
private get connectionMode() {
|
|
622
|
+
private get connectionMode(): ConnectionMode {
|
|
615
623
|
return this._deltaManager.connectionManager.connectionMode;
|
|
616
624
|
}
|
|
617
625
|
|
|
@@ -655,7 +663,7 @@ export class Container
|
|
|
655
663
|
*
|
|
656
664
|
* @param readonly - set or clear force readonly.
|
|
657
665
|
*/
|
|
658
|
-
public forceReadonly(readonly: boolean) {
|
|
666
|
+
public forceReadonly(readonly: boolean): void {
|
|
659
667
|
this._deltaManager.connectionManager.forceReadonly(readonly);
|
|
660
668
|
}
|
|
661
669
|
|
|
@@ -723,7 +731,7 @@ export class Container
|
|
|
723
731
|
* Which means data loss if container is closed at that same moment
|
|
724
732
|
* Most likely that happens when there is no network connection to Relay Service
|
|
725
733
|
*/
|
|
726
|
-
public get isDirty() {
|
|
734
|
+
public get isDirty(): boolean {
|
|
727
735
|
return this._dirtyContainer;
|
|
728
736
|
}
|
|
729
737
|
|
|
@@ -738,7 +746,7 @@ export class Container
|
|
|
738
746
|
return this._runtime.getEntryPoint?.();
|
|
739
747
|
}
|
|
740
748
|
return new Promise<FluidObject>((resolve, reject) => {
|
|
741
|
-
const runtimeInstantiatedHandler = () => {
|
|
749
|
+
const runtimeInstantiatedHandler = (): void => {
|
|
742
750
|
assert(
|
|
743
751
|
this._runtime !== undefined,
|
|
744
752
|
0x5a3 /* runtimeInstantiated fired but runtime is still undefined */,
|
|
@@ -746,7 +754,7 @@ export class Container
|
|
|
746
754
|
resolve(this._runtime.getEntryPoint?.());
|
|
747
755
|
this._lifecycleEvents.off("disposed", disposedHandler);
|
|
748
756
|
};
|
|
749
|
-
const disposedHandler = () => {
|
|
757
|
+
const disposedHandler = (): void => {
|
|
750
758
|
reject(new Error("ContainerContext was disposed"));
|
|
751
759
|
this._lifecycleEvents.off("runtimeInstantiated", runtimeInstantiatedHandler);
|
|
752
760
|
};
|
|
@@ -798,14 +806,13 @@ export class Container
|
|
|
798
806
|
// Tracking alternative ways to handle this in AB#4129.
|
|
799
807
|
this.options = { ...options };
|
|
800
808
|
this.scope = scope;
|
|
801
|
-
this.detachedBlobStorage = detachedBlobStorage ?? createMemoryDetachedBlobStorage();
|
|
802
809
|
this.protocolHandlerBuilder =
|
|
803
810
|
protocolHandlerBuilder ??
|
|
804
811
|
((
|
|
805
812
|
attributes: IDocumentAttributes,
|
|
806
813
|
quorumSnapshot: IQuorumSnapshot,
|
|
807
|
-
sendProposal: (key: string, value:
|
|
808
|
-
) =>
|
|
814
|
+
sendProposal: (key: string, value: unknown) => number,
|
|
815
|
+
): ProtocolHandler =>
|
|
809
816
|
new ProtocolHandler(
|
|
810
817
|
attributes,
|
|
811
818
|
quorumSnapshot,
|
|
@@ -818,7 +825,7 @@ export class Container
|
|
|
818
825
|
this.clone = async (
|
|
819
826
|
_loadProps: IContainerLoadProps,
|
|
820
827
|
createParamOverrides: Partial<IContainerCreateProps>,
|
|
821
|
-
) => {
|
|
828
|
+
): Promise<Container> => {
|
|
822
829
|
return Container.load(_loadProps, {
|
|
823
830
|
...createProps,
|
|
824
831
|
...createParamOverrides,
|
|
@@ -965,7 +972,9 @@ export class Container
|
|
|
965
972
|
// We expose our storage publicly, so it's possible others may call uploadSummaryWithContext() with a
|
|
966
973
|
// non-combined summary tree (in particular, ContainerRuntime.submitSummary). We'll intercept those calls
|
|
967
974
|
// using this callback and fix them up.
|
|
968
|
-
const addProtocolSummaryIfMissing = (
|
|
975
|
+
const addProtocolSummaryIfMissing = (
|
|
976
|
+
summaryTree: ISummaryTree,
|
|
977
|
+
): CombinedAppAndProtocolSummary =>
|
|
969
978
|
isCombinedAppAndProtocolSummary(summaryTree) === true
|
|
970
979
|
? summaryTree
|
|
971
980
|
: combineAppAndProtocolSummary(summaryTree, this.captureProtocolSummary());
|
|
@@ -975,6 +984,12 @@ export class Container
|
|
|
975
984
|
this.mc.config.getBoolean("Fluid.Container.summarizeProtocolTree2") ??
|
|
976
985
|
options.summarizeProtocolTree;
|
|
977
986
|
|
|
987
|
+
this.detachedBlobStorage =
|
|
988
|
+
detachedBlobStorage ??
|
|
989
|
+
(this.mc.config.getBoolean("Fluid.Container.MemoryBlobStorageEnabled") === true
|
|
990
|
+
? createMemoryDetachedBlobStorage()
|
|
991
|
+
: undefined);
|
|
992
|
+
|
|
978
993
|
this.storageAdapter = new ContainerStorageAdapter(
|
|
979
994
|
this.detachedBlobStorage,
|
|
980
995
|
this.mc.logger,
|
|
@@ -996,6 +1011,7 @@ export class Container
|
|
|
996
1011
|
this,
|
|
997
1012
|
() => this._deltaManager.connectionManager.shouldJoinWrite(),
|
|
998
1013
|
() => this.supportGetSnapshotApi(),
|
|
1014
|
+
this.mc.config.getNumber("Fluid.Container.snapshotRefreshTimeoutMs"),
|
|
999
1015
|
);
|
|
1000
1016
|
|
|
1001
1017
|
const isDomAvailable =
|
|
@@ -1006,7 +1022,7 @@ export class Container
|
|
|
1006
1022
|
// keep track of last time page was visible for telemetry (on interactive clients only)
|
|
1007
1023
|
if (isDomAvailable && interactive) {
|
|
1008
1024
|
this.lastVisible = document.hidden ? performance.now() : undefined;
|
|
1009
|
-
this.visibilityEventHandler = () => {
|
|
1025
|
+
this.visibilityEventHandler = (): void => {
|
|
1010
1026
|
if (document.hidden) {
|
|
1011
1027
|
this.lastVisible = performance.now();
|
|
1012
1028
|
} else {
|
|
@@ -1027,12 +1043,12 @@ export class Container
|
|
|
1027
1043
|
return this.protocolHandler.quorum;
|
|
1028
1044
|
}
|
|
1029
1045
|
|
|
1030
|
-
public dispose(error?: ICriticalContainerError) {
|
|
1046
|
+
public dispose(error?: ICriticalContainerError): void {
|
|
1031
1047
|
this._deltaManager.dispose(error);
|
|
1032
1048
|
this.verifyClosed();
|
|
1033
1049
|
}
|
|
1034
1050
|
|
|
1035
|
-
public close(error?: ICriticalContainerError) {
|
|
1051
|
+
public close(error?: ICriticalContainerError): void {
|
|
1036
1052
|
// 1. Ensure that close sequence is exactly the same no matter if it's initiated by host or by DeltaManager
|
|
1037
1053
|
// 2. We need to ensure that we deliver disconnect event to runtime properly. See connectionStateChanged
|
|
1038
1054
|
// handler. We only deliver events if container fully loaded. Transitioning from "loading" ->
|
|
@@ -1053,7 +1069,7 @@ export class Container
|
|
|
1053
1069
|
);
|
|
1054
1070
|
}
|
|
1055
1071
|
|
|
1056
|
-
private closeCore(error?: ICriticalContainerError) {
|
|
1072
|
+
private closeCore(error?: ICriticalContainerError): void {
|
|
1057
1073
|
assert(!this.closed, 0x315 /* re-entrancy */);
|
|
1058
1074
|
|
|
1059
1075
|
try {
|
|
@@ -1082,8 +1098,8 @@ export class Container
|
|
|
1082
1098
|
this._protocolHandler?.close();
|
|
1083
1099
|
|
|
1084
1100
|
this.connectionStateHandler.dispose();
|
|
1085
|
-
} catch (
|
|
1086
|
-
this.mc.logger.sendErrorEvent({ eventName: "ContainerCloseException" },
|
|
1101
|
+
} catch (newError) {
|
|
1102
|
+
this.mc.logger.sendErrorEvent({ eventName: "ContainerCloseException" }, newError);
|
|
1087
1103
|
}
|
|
1088
1104
|
|
|
1089
1105
|
this.emit("closed", error);
|
|
@@ -1102,7 +1118,7 @@ export class Container
|
|
|
1102
1118
|
}
|
|
1103
1119
|
|
|
1104
1120
|
private _disposed = false;
|
|
1105
|
-
private disposeCore(error?: ICriticalContainerError) {
|
|
1121
|
+
private disposeCore(error?: ICriticalContainerError): void {
|
|
1106
1122
|
assert(!this._disposed, 0x54c /* Container already disposed */);
|
|
1107
1123
|
this._disposed = true;
|
|
1108
1124
|
|
|
@@ -1129,7 +1145,7 @@ export class Container
|
|
|
1129
1145
|
|
|
1130
1146
|
this.connectionStateHandler.dispose();
|
|
1131
1147
|
|
|
1132
|
-
const maybeError = error
|
|
1148
|
+
const maybeError = error === undefined ? undefined : new Error(error.message);
|
|
1133
1149
|
this._runtime?.dispose(maybeError);
|
|
1134
1150
|
|
|
1135
1151
|
this.storageAdapter.dispose();
|
|
@@ -1138,8 +1154,8 @@ export class Container
|
|
|
1138
1154
|
// about file, like file being overwritten in storage, but client having stale local cache.
|
|
1139
1155
|
// Driver need to ensure all caches are cleared on critical errors
|
|
1140
1156
|
this.service?.dispose(error);
|
|
1141
|
-
} catch (
|
|
1142
|
-
this.mc.logger.sendErrorEvent({ eventName: "ContainerDisposeException" },
|
|
1157
|
+
} catch (error_) {
|
|
1158
|
+
this.mc.logger.sendErrorEvent({ eventName: "ContainerDisposeException" }, error_);
|
|
1143
1159
|
}
|
|
1144
1160
|
|
|
1145
1161
|
this.emit("disposed", error);
|
|
@@ -1177,7 +1193,7 @@ export class Container
|
|
|
1177
1193
|
return this.getPendingLocalStateCore({ notifyImminentClosure: false });
|
|
1178
1194
|
}
|
|
1179
1195
|
|
|
1180
|
-
private async getPendingLocalStateCore(props: IGetPendingLocalStateProps) {
|
|
1196
|
+
private async getPendingLocalStateCore(props: IGetPendingLocalStateProps): Promise<string> {
|
|
1181
1197
|
if (this.closed || this._disposed) {
|
|
1182
1198
|
throw new UsageError(
|
|
1183
1199
|
"Pending state cannot be retried if the container is closed or disposed",
|
|
@@ -1228,7 +1244,7 @@ export class Container
|
|
|
1228
1244
|
const { baseSnapshot, snapshotBlobs } =
|
|
1229
1245
|
getSnapshotTreeAndBlobsFromSerializedContainer(combinedSummary);
|
|
1230
1246
|
const pendingRuntimeState =
|
|
1231
|
-
attachingData
|
|
1247
|
+
attachingData === undefined ? undefined : this.runtime.getPendingLocalState();
|
|
1232
1248
|
assert(!isPromiseLike(pendingRuntimeState), 0x8e3 /* should not be a promise */);
|
|
1233
1249
|
|
|
1234
1250
|
const detachedContainerState: IPendingDetachedContainerState = {
|
|
@@ -1236,7 +1252,8 @@ export class Container
|
|
|
1236
1252
|
baseSnapshot,
|
|
1237
1253
|
snapshotBlobs,
|
|
1238
1254
|
pendingRuntimeState,
|
|
1239
|
-
hasAttachmentBlobs:
|
|
1255
|
+
hasAttachmentBlobs:
|
|
1256
|
+
this.detachedBlobStorage !== undefined && this.detachedBlobStorage.size > 0,
|
|
1240
1257
|
attachmentBlobs: serializeMemoryDetachedBlobStorage(this.detachedBlobStorage),
|
|
1241
1258
|
};
|
|
1242
1259
|
return JSON.stringify(detachedContainerState);
|
|
@@ -1353,7 +1370,7 @@ export class Container
|
|
|
1353
1370
|
const snapshotWithBlobs = await attachP;
|
|
1354
1371
|
this.serializedStateManager.setInitialSnapshot(snapshotWithBlobs);
|
|
1355
1372
|
if (!this.closed) {
|
|
1356
|
-
this.detachedBlobStorage
|
|
1373
|
+
this.detachedBlobStorage?.dispose?.();
|
|
1357
1374
|
this.handleDeltaConnectionArg(attachProps?.deltaConnection, {
|
|
1358
1375
|
fetchOpsFromStorage: false,
|
|
1359
1376
|
reason: { text: "createDetached" },
|
|
@@ -1365,7 +1382,10 @@ export class Container
|
|
|
1365
1382
|
},
|
|
1366
1383
|
);
|
|
1367
1384
|
|
|
1368
|
-
private setAutoReconnectInternal(
|
|
1385
|
+
private setAutoReconnectInternal(
|
|
1386
|
+
mode: ReconnectMode,
|
|
1387
|
+
reason: IConnectionStateChangeReason,
|
|
1388
|
+
): void {
|
|
1369
1389
|
const currentMode = this._deltaManager.connectionManager.reconnectMode;
|
|
1370
1390
|
|
|
1371
1391
|
if (currentMode === mode) {
|
|
@@ -1387,7 +1407,7 @@ export class Container
|
|
|
1387
1407
|
this._deltaManager.connectionManager.setAutoReconnect(mode, reason);
|
|
1388
1408
|
}
|
|
1389
1409
|
|
|
1390
|
-
public connect() {
|
|
1410
|
+
public connect(): void {
|
|
1391
1411
|
if (this.closed) {
|
|
1392
1412
|
throw new UsageError(`The Container is closed and cannot be connected`);
|
|
1393
1413
|
} else if (this.attachState !== AttachState.Attached) {
|
|
@@ -1403,7 +1423,7 @@ export class Container
|
|
|
1403
1423
|
}
|
|
1404
1424
|
}
|
|
1405
1425
|
|
|
1406
|
-
private connectInternal(args: IConnectionArgs) {
|
|
1426
|
+
private connectInternal(args: IConnectionArgs): void {
|
|
1407
1427
|
assert(!this.closed, 0x2c5 /* "Attempting to connect() a closed Container" */);
|
|
1408
1428
|
assert(
|
|
1409
1429
|
this.attachState === AttachState.Attached,
|
|
@@ -1418,7 +1438,7 @@ export class Container
|
|
|
1418
1438
|
this.resumeInternal(args);
|
|
1419
1439
|
}
|
|
1420
1440
|
|
|
1421
|
-
public disconnect() {
|
|
1441
|
+
public disconnect(): void {
|
|
1422
1442
|
if (this.closed) {
|
|
1423
1443
|
throw new UsageError(`The Container is closed and cannot be disconnected`);
|
|
1424
1444
|
} else {
|
|
@@ -1426,7 +1446,7 @@ export class Container
|
|
|
1426
1446
|
}
|
|
1427
1447
|
}
|
|
1428
1448
|
|
|
1429
|
-
private disconnectInternal(reason: IConnectionStateChangeReason) {
|
|
1449
|
+
private disconnectInternal(reason: IConnectionStateChangeReason): void {
|
|
1430
1450
|
assert(!this.closed, 0x2c7 /* "Attempting to disconnect() a closed Container" */);
|
|
1431
1451
|
|
|
1432
1452
|
// Set Auto Reconnect Mode
|
|
@@ -1434,7 +1454,7 @@ export class Container
|
|
|
1434
1454
|
this.setAutoReconnectInternal(mode, reason);
|
|
1435
1455
|
}
|
|
1436
1456
|
|
|
1437
|
-
private resumeInternal(args: IConnectionArgs) {
|
|
1457
|
+
private resumeInternal(args: IConnectionArgs): void {
|
|
1438
1458
|
assert(!this.closed, 0x0d9 /* "Attempting to connect() a closed DeltaManager" */);
|
|
1439
1459
|
|
|
1440
1460
|
// Resume processing ops
|
|
@@ -1468,7 +1488,7 @@ export class Container
|
|
|
1468
1488
|
);
|
|
1469
1489
|
};
|
|
1470
1490
|
|
|
1471
|
-
public async proposeCodeDetails(codeDetails: IFluidCodeDetails) {
|
|
1491
|
+
public async proposeCodeDetails(codeDetails: IFluidCodeDetails): Promise<boolean> {
|
|
1472
1492
|
if (!isFluidCodeDetails(codeDetails)) {
|
|
1473
1493
|
throw new Error("Provided codeDetails are not IFluidCodeDetails");
|
|
1474
1494
|
}
|
|
@@ -1511,7 +1531,7 @@ export class Container
|
|
|
1511
1531
|
/**
|
|
1512
1532
|
* Determines if the currently loaded module satisfies the incoming constraint code details
|
|
1513
1533
|
*/
|
|
1514
|
-
private async satisfies(constraintCodeDetails: IFluidCodeDetails) {
|
|
1534
|
+
private async satisfies(constraintCodeDetails: IFluidCodeDetails): Promise<boolean> {
|
|
1515
1535
|
// If we have no module, it can't satisfy anything.
|
|
1516
1536
|
if (this._loadedModule === undefined) {
|
|
1517
1537
|
return false;
|
|
@@ -1549,7 +1569,7 @@ export class Container
|
|
|
1549
1569
|
return true;
|
|
1550
1570
|
}
|
|
1551
1571
|
|
|
1552
|
-
private connectToDeltaStream(args: IConnectionArgs) {
|
|
1572
|
+
private connectToDeltaStream(args: IConnectionArgs): void {
|
|
1553
1573
|
// All agents need "write" access, including summarizer.
|
|
1554
1574
|
if (!this._canReconnect || !this.client.details.capabilities.interactive) {
|
|
1555
1575
|
args.mode = "write";
|
|
@@ -1558,7 +1578,7 @@ export class Container
|
|
|
1558
1578
|
this._deltaManager.connect(args);
|
|
1559
1579
|
}
|
|
1560
1580
|
|
|
1561
|
-
private readonly metadataUpdateHandler = (metadata: Record<string, string>) => {
|
|
1581
|
+
private readonly metadataUpdateHandler = (metadata: Record<string, string>): void => {
|
|
1562
1582
|
this._containerMetadata = { ...this._containerMetadata, ...metadata };
|
|
1563
1583
|
this.emit("metadataUpdate", metadata);
|
|
1564
1584
|
};
|
|
@@ -1584,7 +1604,12 @@ export class Container
|
|
|
1584
1604
|
loadMode: IContainerLoadMode,
|
|
1585
1605
|
resolvedUrl: IResolvedUrl,
|
|
1586
1606
|
pendingLocalState: IPendingContainerState | undefined,
|
|
1587
|
-
) {
|
|
1607
|
+
): Promise<{
|
|
1608
|
+
sequenceNumber: number;
|
|
1609
|
+
version: string | undefined;
|
|
1610
|
+
dmLastProcessedSeqNumber: number;
|
|
1611
|
+
dmLastKnownSeqNumber: number;
|
|
1612
|
+
}> {
|
|
1588
1613
|
const timings: Record<string, number> = { phase1: performance.now() };
|
|
1589
1614
|
this.service = await this.createDocumentService(async () =>
|
|
1590
1615
|
this.serviceFactory.createDocumentService(
|
|
@@ -1639,25 +1664,28 @@ export class Container
|
|
|
1639
1664
|
// Attach op handlers to finish initialization and be able to start processing ops
|
|
1640
1665
|
// Kick off any ops fetching if required.
|
|
1641
1666
|
switch (loadMode.opsBeforeReturn) {
|
|
1642
|
-
case undefined:
|
|
1667
|
+
case undefined: {
|
|
1643
1668
|
// Start prefetch, but not set opsBeforeReturnP - boot is not blocked by it!
|
|
1644
1669
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
1645
1670
|
this.attachDeltaManagerOpHandler(
|
|
1646
1671
|
attributes,
|
|
1647
|
-
loadMode.deltaConnection
|
|
1672
|
+
loadMode.deltaConnection === "none" ? "none" : "all",
|
|
1648
1673
|
lastProcessedSequenceNumber,
|
|
1649
1674
|
);
|
|
1650
1675
|
break;
|
|
1676
|
+
}
|
|
1651
1677
|
case "cached":
|
|
1652
|
-
case "all":
|
|
1678
|
+
case "all": {
|
|
1653
1679
|
opsBeforeReturnP = this.attachDeltaManagerOpHandler(
|
|
1654
1680
|
attributes,
|
|
1655
1681
|
loadMode.opsBeforeReturn,
|
|
1656
1682
|
lastProcessedSequenceNumber,
|
|
1657
1683
|
);
|
|
1658
1684
|
break;
|
|
1659
|
-
|
|
1685
|
+
}
|
|
1686
|
+
default: {
|
|
1660
1687
|
unreachableCase(loadMode.opsBeforeReturn);
|
|
1688
|
+
}
|
|
1661
1689
|
}
|
|
1662
1690
|
|
|
1663
1691
|
// ...load in the existing quorum
|
|
@@ -1755,7 +1783,7 @@ export class Container
|
|
|
1755
1783
|
};
|
|
1756
1784
|
}
|
|
1757
1785
|
|
|
1758
|
-
private async createDetached(codeDetails: IFluidCodeDetails) {
|
|
1786
|
+
private async createDetached(codeDetails: IFluidCodeDetails): Promise<void> {
|
|
1759
1787
|
const attributes: IDocumentAttributes = {
|
|
1760
1788
|
sequenceNumber: detachedContainerRefSeqNumber,
|
|
1761
1789
|
minimumSequenceNumber: 0,
|
|
@@ -1785,13 +1813,13 @@ export class Container
|
|
|
1785
1813
|
hasAttachmentBlobs,
|
|
1786
1814
|
attachmentBlobs,
|
|
1787
1815
|
pendingRuntimeState,
|
|
1788
|
-
}: IPendingDetachedContainerState) {
|
|
1816
|
+
}: IPendingDetachedContainerState): Promise<void> {
|
|
1789
1817
|
if (hasAttachmentBlobs) {
|
|
1790
1818
|
if (attachmentBlobs !== undefined) {
|
|
1791
1819
|
tryInitializeMemoryDetachedBlobStorage(this.detachedBlobStorage, attachmentBlobs);
|
|
1792
1820
|
}
|
|
1793
1821
|
assert(
|
|
1794
|
-
this.detachedBlobStorage.size > 0,
|
|
1822
|
+
this.detachedBlobStorage !== undefined && this.detachedBlobStorage.size > 0,
|
|
1795
1823
|
0x250 /* "serialized container with attachment blobs must be rehydrated with detached blob storage" */,
|
|
1796
1824
|
);
|
|
1797
1825
|
}
|
|
@@ -1862,6 +1890,7 @@ export class Container
|
|
|
1862
1890
|
quorumSnapshot: IQuorumSnapshot,
|
|
1863
1891
|
): void {
|
|
1864
1892
|
const protocol = this.protocolHandlerBuilder(attributes, quorumSnapshot, (key, value) =>
|
|
1893
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
1865
1894
|
this.submitMessage(MessageType.Propose, JSON.stringify({ key, value })),
|
|
1866
1895
|
);
|
|
1867
1896
|
|
|
@@ -1870,7 +1899,7 @@ export class Container
|
|
|
1870
1899
|
namespace: "ProtocolHandler",
|
|
1871
1900
|
});
|
|
1872
1901
|
|
|
1873
|
-
protocol.quorum.on("error", (error) => {
|
|
1902
|
+
protocol.quorum.on("error", (error: ITelemetryErrorEventExt) => {
|
|
1874
1903
|
protocolLogger.sendErrorEvent(error);
|
|
1875
1904
|
});
|
|
1876
1905
|
|
|
@@ -1942,9 +1971,8 @@ export class Container
|
|
|
1942
1971
|
clientDetailsOverride?: IClientDetails,
|
|
1943
1972
|
): IClient {
|
|
1944
1973
|
const client: IClient =
|
|
1945
|
-
loaderOptionsClient
|
|
1946
|
-
?
|
|
1947
|
-
: {
|
|
1974
|
+
loaderOptionsClient === undefined
|
|
1975
|
+
? {
|
|
1948
1976
|
details: {
|
|
1949
1977
|
capabilities: { interactive: true },
|
|
1950
1978
|
},
|
|
@@ -1952,7 +1980,8 @@ export class Container
|
|
|
1952
1980
|
permission: [],
|
|
1953
1981
|
scopes: [],
|
|
1954
1982
|
user: { id: "" },
|
|
1955
|
-
}
|
|
1983
|
+
}
|
|
1984
|
+
: structuredClone(loaderOptionsClient);
|
|
1956
1985
|
|
|
1957
1986
|
if (clientDetailsOverride !== undefined) {
|
|
1958
1987
|
client.details = {
|
|
@@ -1979,14 +2008,14 @@ export class Container
|
|
|
1979
2008
|
* This happens after client received its own joinOp and thus is in the quorum.
|
|
1980
2009
|
* If it's not true, runtime is not in position to send ops.
|
|
1981
2010
|
*/
|
|
1982
|
-
private activeConnection() {
|
|
2011
|
+
private activeConnection(): boolean {
|
|
1983
2012
|
return (
|
|
1984
2013
|
this.connectionState === ConnectionState.Connected && this.connectionMode === "write"
|
|
1985
2014
|
);
|
|
1986
2015
|
}
|
|
1987
2016
|
|
|
1988
|
-
private createDeltaManager() {
|
|
1989
|
-
const serviceProvider = () => this.service;
|
|
2017
|
+
private createDeltaManager(): DeltaManager<ConnectionManager> {
|
|
2018
|
+
const serviceProvider = (): IDocumentService | undefined => this.service;
|
|
1990
2019
|
const deltaManager = new DeltaManager<ConnectionManager>(
|
|
1991
2020
|
serviceProvider,
|
|
1992
2021
|
createChildLogger({ logger: this.subLogger, namespace: "DeltaManager" }),
|
|
@@ -2083,7 +2112,7 @@ export class Container
|
|
|
2083
2112
|
attributes: IDocumentAttributes,
|
|
2084
2113
|
prefetchType?: "cached" | "all" | "none",
|
|
2085
2114
|
lastProcessedSequenceNumber?: number,
|
|
2086
|
-
) {
|
|
2115
|
+
): Promise<void> {
|
|
2087
2116
|
return this._deltaManager.attachOpHandler(
|
|
2088
2117
|
attributes.minimumSequenceNumber,
|
|
2089
2118
|
attributes.sequenceNumber,
|
|
@@ -2102,7 +2131,7 @@ export class Container
|
|
|
2102
2131
|
value: ConnectionState,
|
|
2103
2132
|
oldState: ConnectionState,
|
|
2104
2133
|
reason?: IConnectionStateChangeReason,
|
|
2105
|
-
) {
|
|
2134
|
+
): void {
|
|
2106
2135
|
// Log actual event
|
|
2107
2136
|
const time = performance.now();
|
|
2108
2137
|
this.connectionTransitionTimes[value] = time;
|
|
@@ -2145,7 +2174,7 @@ export class Container
|
|
|
2145
2174
|
opsBehind,
|
|
2146
2175
|
online: OnlineStatus[isOnline()],
|
|
2147
2176
|
lastVisible:
|
|
2148
|
-
this.lastVisible
|
|
2177
|
+
this.lastVisible === undefined ? undefined : performance.now() - this.lastVisible,
|
|
2149
2178
|
checkpointSequenceNumber,
|
|
2150
2179
|
quorumSize: this._protocolHandler?.quorum.getMembers().size,
|
|
2151
2180
|
isDirty: this.isDirty,
|
|
@@ -2159,7 +2188,7 @@ export class Container
|
|
|
2159
2188
|
}
|
|
2160
2189
|
}
|
|
2161
2190
|
|
|
2162
|
-
private propagateConnectionState(disconnectedReason?: IConnectionStateChangeReason) {
|
|
2191
|
+
private propagateConnectionState(disconnectedReason?: IConnectionStateChangeReason): void {
|
|
2163
2192
|
const connected = this.connectionState === ConnectionState.Connected;
|
|
2164
2193
|
|
|
2165
2194
|
if (connected) {
|
|
@@ -2193,15 +2222,17 @@ export class Container
|
|
|
2193
2222
|
// back-compat: ADO #1385: Remove in the future, summary op should come through submitSummaryMessage()
|
|
2194
2223
|
private submitContainerMessage(
|
|
2195
2224
|
type: MessageType,
|
|
2196
|
-
contents:
|
|
2225
|
+
contents: unknown,
|
|
2197
2226
|
batch?: boolean,
|
|
2198
|
-
metadata?:
|
|
2227
|
+
metadata?: unknown,
|
|
2199
2228
|
): number {
|
|
2200
2229
|
switch (type) {
|
|
2201
|
-
case MessageType.Operation:
|
|
2230
|
+
case MessageType.Operation: {
|
|
2202
2231
|
return this.submitMessage(type, JSON.stringify(contents), batch, metadata);
|
|
2203
|
-
|
|
2204
|
-
|
|
2232
|
+
}
|
|
2233
|
+
case MessageType.Summarize: {
|
|
2234
|
+
return this.submitSummaryMessage(contents as ISummaryContent);
|
|
2235
|
+
}
|
|
2205
2236
|
default: {
|
|
2206
2237
|
const newError = new GenericError(
|
|
2207
2238
|
"invalidContainerSubmitOpType",
|
|
@@ -2214,7 +2245,9 @@ export class Container
|
|
|
2214
2245
|
}
|
|
2215
2246
|
}
|
|
2216
2247
|
|
|
2217
|
-
/**
|
|
2248
|
+
/**
|
|
2249
|
+
* Gets the `clientSequenceNumber` of last message in a batch.
|
|
2250
|
+
*/
|
|
2218
2251
|
private submitBatch(batch: IBatchMessage[], referenceSequenceNumber?: number): number {
|
|
2219
2252
|
let clientSequenceNumber = -1;
|
|
2220
2253
|
for (const message of batch) {
|
|
@@ -2231,7 +2264,10 @@ export class Container
|
|
|
2231
2264
|
return clientSequenceNumber;
|
|
2232
2265
|
}
|
|
2233
2266
|
|
|
2234
|
-
private submitSummaryMessage(
|
|
2267
|
+
private submitSummaryMessage(
|
|
2268
|
+
summary: ISummaryContent,
|
|
2269
|
+
referenceSequenceNumber?: number,
|
|
2270
|
+
): number {
|
|
2235
2271
|
// github #6451: this is only needed for staging so the server
|
|
2236
2272
|
// know when the protocol tree is included
|
|
2237
2273
|
// this can be removed once all clients send
|
|
@@ -2254,7 +2290,7 @@ export class Container
|
|
|
2254
2290
|
type: MessageType,
|
|
2255
2291
|
contents?: string,
|
|
2256
2292
|
batch?: boolean,
|
|
2257
|
-
metadata?:
|
|
2293
|
+
metadata?: unknown,
|
|
2258
2294
|
compression?: string,
|
|
2259
2295
|
referenceSequenceNumber?: number,
|
|
2260
2296
|
): number {
|
|
@@ -2274,7 +2310,7 @@ export class Container
|
|
|
2274
2310
|
);
|
|
2275
2311
|
}
|
|
2276
2312
|
|
|
2277
|
-
private processRemoteMessage(message: ISequencedDocumentMessage) {
|
|
2313
|
+
private processRemoteMessage(message: ISequencedDocumentMessage): void {
|
|
2278
2314
|
const local = this.clientId === message.clientId;
|
|
2279
2315
|
|
|
2280
2316
|
// Allow the protocol handler to process the message
|
|
@@ -2322,11 +2358,11 @@ export class Container
|
|
|
2322
2358
|
}
|
|
2323
2359
|
|
|
2324
2360
|
// unknown should be removed once `@alpha` tag is removed from IContainerContext
|
|
2325
|
-
private submitSignal(content: unknown | ISignalEnvelope, targetClientId?: string) {
|
|
2361
|
+
private submitSignal(content: unknown | ISignalEnvelope, targetClientId?: string): void {
|
|
2326
2362
|
this._deltaManager.submitSignal(JSON.stringify(content), targetClientId);
|
|
2327
2363
|
}
|
|
2328
2364
|
|
|
2329
|
-
private processSignal(message: ISignalMessage) {
|
|
2365
|
+
private processSignal(message: ISignalMessage): void {
|
|
2330
2366
|
// No clientId indicates a system signal message.
|
|
2331
2367
|
if (protocolHandlerShouldProcessSignal(message)) {
|
|
2332
2368
|
this.protocolHandler.processSignal(message);
|
|
@@ -2341,7 +2377,7 @@ export class Container
|
|
|
2341
2377
|
snapshotTree: ISnapshotTree | undefined,
|
|
2342
2378
|
pendingLocalState?: unknown,
|
|
2343
2379
|
snapshot?: ISnapshot,
|
|
2344
|
-
) {
|
|
2380
|
+
): Promise<void> {
|
|
2345
2381
|
assert(this._runtime?.disposed !== false, 0x0dd /* "Existing runtime not disposed" */);
|
|
2346
2382
|
|
|
2347
2383
|
// The relative loader will proxy requests to '/' to the loader itself assuming no non-cache flags
|
|
@@ -2414,7 +2450,7 @@ export class Container
|
|
|
2414
2450
|
this._loadedCodeDetails = codeDetails;
|
|
2415
2451
|
}
|
|
2416
2452
|
|
|
2417
|
-
private readonly updateDirtyContainerState = (dirty: boolean) => {
|
|
2453
|
+
private readonly updateDirtyContainerState = (dirty: boolean): void => {
|
|
2418
2454
|
if (this._dirtyContainer === dirty) {
|
|
2419
2455
|
return;
|
|
2420
2456
|
}
|
|
@@ -2443,7 +2479,7 @@ export class Container
|
|
|
2443
2479
|
private handleDeltaConnectionArg(
|
|
2444
2480
|
deltaConnectionArg?: "none" | "delayed",
|
|
2445
2481
|
connectionArgs?: IConnectionArgs,
|
|
2446
|
-
) {
|
|
2482
|
+
): void {
|
|
2447
2483
|
// This ensures that we allow transitions to "connected" state only after container has been fully loaded
|
|
2448
2484
|
// and we propagate such events to container runtime. All events prior to being loaded are ignored.
|
|
2449
2485
|
// This means if we get here in non-loaded state, we might not deliver proper events to container runtime,
|
|
@@ -2454,13 +2490,14 @@ export class Container
|
|
|
2454
2490
|
);
|
|
2455
2491
|
|
|
2456
2492
|
switch (deltaConnectionArg) {
|
|
2457
|
-
case undefined:
|
|
2493
|
+
case undefined: {
|
|
2458
2494
|
if (connectionArgs) {
|
|
2459
2495
|
// connect to delta stream now since we did not before
|
|
2460
2496
|
this.connectToDeltaStream(connectionArgs);
|
|
2461
2497
|
}
|
|
2498
|
+
}
|
|
2462
2499
|
// intentional fallthrough
|
|
2463
|
-
case "delayed":
|
|
2500
|
+
case "delayed": {
|
|
2464
2501
|
assert(
|
|
2465
2502
|
this.inboundQueuePausedFromInit,
|
|
2466
2503
|
0x346 /* inboundQueuePausedFromInit should be true */,
|
|
@@ -2469,10 +2506,13 @@ export class Container
|
|
|
2469
2506
|
this._deltaManager.inbound.resume();
|
|
2470
2507
|
this._deltaManager.inboundSignal.resume();
|
|
2471
2508
|
break;
|
|
2472
|
-
|
|
2509
|
+
}
|
|
2510
|
+
case "none": {
|
|
2473
2511
|
break;
|
|
2474
|
-
|
|
2512
|
+
}
|
|
2513
|
+
default: {
|
|
2475
2514
|
unreachableCase(deltaConnectionArg);
|
|
2515
|
+
}
|
|
2476
2516
|
}
|
|
2477
2517
|
}
|
|
2478
2518
|
}
|