@fluidframework/container-loader 2.0.0-dev.2.3.0.115467 → 2.0.0-dev.4.1.0.148229
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.js +18 -21
- package/.mocharc.js +2 -2
- package/README.md +65 -44
- package/api-extractor.json +2 -2
- package/closeAndGetPendingLocalState.md +51 -0
- package/dist/audience.d.ts +0 -1
- package/dist/audience.d.ts.map +1 -1
- package/dist/audience.js.map +1 -1
- package/dist/catchUpMonitor.d.ts.map +1 -1
- package/dist/catchUpMonitor.js.map +1 -1
- package/dist/collabWindowTracker.d.ts.map +1 -1
- package/dist/collabWindowTracker.js.map +1 -1
- package/dist/connectionManager.d.ts +5 -5
- package/dist/connectionManager.d.ts.map +1 -1
- package/dist/connectionManager.js +107 -44
- package/dist/connectionManager.js.map +1 -1
- package/dist/connectionState.d.ts.map +1 -1
- package/dist/connectionState.js.map +1 -1
- package/dist/connectionStateHandler.d.ts +7 -7
- package/dist/connectionStateHandler.d.ts.map +1 -1
- package/dist/connectionStateHandler.js +50 -21
- package/dist/connectionStateHandler.js.map +1 -1
- package/dist/container.d.ts +64 -5
- package/dist/container.d.ts.map +1 -1
- package/dist/container.js +329 -137
- package/dist/container.js.map +1 -1
- package/dist/containerContext.d.ts +19 -8
- package/dist/containerContext.d.ts.map +1 -1
- package/dist/containerContext.js +58 -14
- package/dist/containerContext.js.map +1 -1
- package/dist/containerStorageAdapter.d.ts +41 -2
- package/dist/containerStorageAdapter.d.ts.map +1 -1
- package/dist/containerStorageAdapter.js +88 -14
- package/dist/containerStorageAdapter.js.map +1 -1
- package/dist/contracts.d.ts +3 -3
- package/dist/contracts.d.ts.map +1 -1
- package/dist/contracts.js.map +1 -1
- package/dist/deltaManager.d.ts +21 -8
- package/dist/deltaManager.d.ts.map +1 -1
- package/dist/deltaManager.js +112 -37
- package/dist/deltaManager.js.map +1 -1
- package/dist/deltaManagerProxy.d.ts +10 -22
- package/dist/deltaManagerProxy.d.ts.map +1 -1
- package/dist/deltaManagerProxy.js +14 -50
- package/dist/deltaManagerProxy.js.map +1 -1
- package/dist/deltaQueue.d.ts.map +1 -1
- package/dist/deltaQueue.js +4 -2
- package/dist/deltaQueue.js.map +1 -1
- package/dist/index.d.ts +4 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -3
- package/dist/index.js.map +1 -1
- package/dist/loader.d.ts +13 -4
- package/dist/loader.d.ts.map +1 -1
- package/dist/loader.js +38 -24
- package/dist/loader.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.d.ts.map +1 -1
- package/dist/protocol.js +2 -1
- package/dist/protocol.js.map +1 -1
- package/dist/protocolTreeDocumentStorageService.d.ts +6 -2
- package/dist/protocolTreeDocumentStorageService.d.ts.map +1 -1
- package/dist/protocolTreeDocumentStorageService.js +7 -4
- package/dist/protocolTreeDocumentStorageService.js.map +1 -1
- package/dist/quorum.d.ts.map +1 -1
- package/dist/quorum.js.map +1 -1
- package/dist/retriableDocumentStorageService.d.ts.map +1 -1
- package/dist/retriableDocumentStorageService.js +6 -2
- package/dist/retriableDocumentStorageService.js.map +1 -1
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +8 -5
- package/dist/utils.js.map +1 -1
- package/lib/audience.d.ts +0 -1
- package/lib/audience.d.ts.map +1 -1
- package/lib/audience.js.map +1 -1
- package/lib/catchUpMonitor.d.ts.map +1 -1
- package/lib/catchUpMonitor.js.map +1 -1
- package/lib/collabWindowTracker.d.ts.map +1 -1
- package/lib/collabWindowTracker.js.map +1 -1
- package/lib/connectionManager.d.ts +5 -5
- package/lib/connectionManager.d.ts.map +1 -1
- package/lib/connectionManager.js +110 -47
- package/lib/connectionManager.js.map +1 -1
- package/lib/connectionState.d.ts.map +1 -1
- package/lib/connectionState.js.map +1 -1
- package/lib/connectionStateHandler.d.ts +7 -7
- package/lib/connectionStateHandler.d.ts.map +1 -1
- package/lib/connectionStateHandler.js +50 -21
- package/lib/connectionStateHandler.js.map +1 -1
- package/lib/container.d.ts +64 -5
- package/lib/container.d.ts.map +1 -1
- package/lib/container.js +336 -144
- package/lib/container.js.map +1 -1
- package/lib/containerContext.d.ts +19 -8
- package/lib/containerContext.d.ts.map +1 -1
- package/lib/containerContext.js +59 -15
- package/lib/containerContext.js.map +1 -1
- package/lib/containerStorageAdapter.d.ts +41 -2
- package/lib/containerStorageAdapter.d.ts.map +1 -1
- package/lib/containerStorageAdapter.js +86 -14
- package/lib/containerStorageAdapter.js.map +1 -1
- package/lib/contracts.d.ts +3 -3
- package/lib/contracts.d.ts.map +1 -1
- package/lib/contracts.js.map +1 -1
- package/lib/deltaManager.d.ts +21 -8
- package/lib/deltaManager.d.ts.map +1 -1
- package/lib/deltaManager.js +114 -39
- package/lib/deltaManager.js.map +1 -1
- package/lib/deltaManagerProxy.d.ts +10 -22
- package/lib/deltaManagerProxy.d.ts.map +1 -1
- package/lib/deltaManagerProxy.js +14 -50
- package/lib/deltaManagerProxy.js.map +1 -1
- package/lib/deltaQueue.d.ts.map +1 -1
- package/lib/deltaQueue.js +4 -2
- package/lib/deltaQueue.js.map +1 -1
- package/lib/index.d.ts +4 -3
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +2 -2
- package/lib/index.js.map +1 -1
- package/lib/loader.d.ts +13 -4
- package/lib/loader.d.ts.map +1 -1
- package/lib/loader.js +37 -24
- package/lib/loader.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.d.ts.map +1 -1
- package/lib/protocol.js +2 -1
- package/lib/protocol.js.map +1 -1
- package/lib/protocolTreeDocumentStorageService.d.ts +6 -2
- package/lib/protocolTreeDocumentStorageService.d.ts.map +1 -1
- package/lib/protocolTreeDocumentStorageService.js +7 -4
- package/lib/protocolTreeDocumentStorageService.js.map +1 -1
- package/lib/quorum.d.ts.map +1 -1
- package/lib/quorum.js.map +1 -1
- package/lib/retriableDocumentStorageService.d.ts.map +1 -1
- package/lib/retriableDocumentStorageService.js +6 -2
- package/lib/retriableDocumentStorageService.js.map +1 -1
- package/lib/utils.d.ts.map +1 -1
- package/lib/utils.js +8 -5
- package/lib/utils.js.map +1 -1
- package/package.json +67 -56
- package/prettier.config.cjs +1 -1
- package/src/audience.ts +51 -46
- package/src/catchUpMonitor.ts +39 -37
- package/src/collabWindowTracker.ts +75 -70
- package/src/connectionManager.ts +1040 -941
- package/src/connectionState.ts +19 -19
- package/src/connectionStateHandler.ts +557 -463
- package/src/container.ts +2147 -1784
- package/src/containerContext.ts +417 -345
- package/src/containerStorageAdapter.ts +268 -154
- package/src/contracts.ts +155 -153
- package/src/deltaManager.ts +1074 -945
- package/src/deltaManagerProxy.ts +88 -137
- package/src/deltaQueue.ts +155 -151
- package/src/index.ts +13 -17
- package/src/loader.ts +434 -427
- package/src/packageVersion.ts +1 -1
- package/src/protocol.ts +93 -87
- package/src/protocolTreeDocumentStorageService.ts +34 -34
- package/src/quorum.ts +34 -34
- package/src/retriableDocumentStorageService.ts +118 -102
- package/src/utils.ts +93 -83
- package/tsconfig.esnext.json +6 -6
- package/tsconfig.json +8 -12
package/lib/contracts.d.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
5
|
import { ITelemetryProperties } from "@fluidframework/common-definitions";
|
|
6
|
-
import { IDeltaQueue, ReadOnlyInfo,
|
|
6
|
+
import { IDeltaQueue, ReadOnlyInfo, IConnectionDetailsInternal, ICriticalContainerError, IFluidCodeDetails } from "@fluidframework/container-definitions";
|
|
7
7
|
import { ConnectionMode, IDocumentMessage, ISequencedDocumentMessage, IClientConfiguration, IClientDetails, ISignalMessage } from "@fluidframework/protocol-definitions";
|
|
8
8
|
import { IContainerPackageInfo } from "@fluidframework/driver-definitions";
|
|
9
9
|
export declare enum ReconnectMode {
|
|
@@ -60,7 +60,7 @@ export interface IConnectionManager {
|
|
|
60
60
|
/**
|
|
61
61
|
* Disposed connection manager
|
|
62
62
|
*/
|
|
63
|
-
dispose(error?: ICriticalContainerError): void;
|
|
63
|
+
dispose(error?: ICriticalContainerError, switchToReadonly?: boolean): void;
|
|
64
64
|
get connectionMode(): ConnectionMode;
|
|
65
65
|
}
|
|
66
66
|
/**
|
|
@@ -97,7 +97,7 @@ export interface IConnectionManagerFactoryArgs {
|
|
|
97
97
|
/**
|
|
98
98
|
* Called whenever new connection to rely service is established
|
|
99
99
|
*/
|
|
100
|
-
readonly connectHandler: (connection:
|
|
100
|
+
readonly connectHandler: (connection: IConnectionDetailsInternal) => void;
|
|
101
101
|
/**
|
|
102
102
|
* Called whenever ping/pong messages are roundtripped on connection.
|
|
103
103
|
*
|
package/lib/contracts.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"contracts.d.ts","sourceRoot":"","sources":["../src/contracts.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,
|
|
1
|
+
{"version":3,"file":"contracts.d.ts","sourceRoot":"","sources":["../src/contracts.ts"],"names":[],"mappings":"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"}
|
package/lib/contracts.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"contracts.js","sourceRoot":"","sources":["../src/contracts.ts"],"names":[],"mappings":"AAAA;;;GAGG;
|
|
1
|
+
{"version":3,"file":"contracts.js","sourceRoot":"","sources":["../src/contracts.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAMN,cAAc,GACd,MAAM,uCAAuC,CAAC;AAW/C,MAAM,CAAN,IAAY,aAIX;AAJD,WAAY,aAAa;IACxB,gCAAe,CAAA;IACf,sCAAqB,CAAA;IACrB,oCAAmB,CAAA;AACpB,CAAC,EAJW,aAAa,KAAb,aAAa,QAIxB;AA+ID;;;;GAIG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,CAC7B,WAA0C,EAClB,EAAE;IAC1B,IAAI,oBAAoB,CAAC;IACzB,IAAI,WAAW,IAAI,MAAM,IAAI,WAAW,EAAE;QACzC,oBAAoB,GAAG,WAAW,CAAC;KACnC;SAAM,IAAI,cAAc,CAAC,WAAW,aAAX,WAAW,uBAAX,WAAW,CAAE,OAAO,CAAC,EAAE;QAChD,oBAAoB,GAAG,WAAW,aAAX,WAAW,uBAAX,WAAW,CAAE,OAAO,CAAC,IAAI,CAAC;KACjD;SAAM;QACN,oBAAoB,GAAG,WAAW,aAAX,WAAW,uBAAX,WAAW,CAAE,OAAO,CAAC;KAC5C;IACD,OAAO,EAAE,IAAI,EAAE,oBAAoB,EAAE,CAAC;AACvC,CAAC,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { ITelemetryProperties } from \"@fluidframework/common-definitions\";\nimport {\n\tIDeltaQueue,\n\tReadOnlyInfo,\n\tIConnectionDetailsInternal,\n\tICriticalContainerError,\n\tIFluidCodeDetails,\n\tisFluidPackage,\n} from \"@fluidframework/container-definitions\";\nimport {\n\tConnectionMode,\n\tIDocumentMessage,\n\tISequencedDocumentMessage,\n\tIClientConfiguration,\n\tIClientDetails,\n\tISignalMessage,\n} from \"@fluidframework/protocol-definitions\";\nimport { IContainerPackageInfo } from \"@fluidframework/driver-definitions\";\n\nexport enum ReconnectMode {\n\tNever = \"Never\",\n\tDisabled = \"Disabled\",\n\tEnabled = \"Enabled\",\n}\n\n/**\n * Connection manager (implements this interface) is responsible for maintaining connection\n * to relay service.\n */\nexport interface IConnectionManager {\n\treadonly connected: boolean;\n\n\treadonly clientId: string | undefined;\n\n\t/** The queue of outbound delta messages */\n\treadonly outbound: IDeltaQueue<IDocumentMessage[]>;\n\n\t/** Details of client */\n\treadonly clientDetails: IClientDetails;\n\n\t/** Protocol version being used to communicate with the service */\n\treadonly version: string;\n\n\t/** Max message size allowed to the delta manager */\n\treadonly maxMessageSize: number;\n\n\t/** Service configuration provided by the service. */\n\treadonly serviceConfiguration: IClientConfiguration | undefined;\n\n\treadonly readOnlyInfo: ReadOnlyInfo;\n\n\t// Various connectivity properties for telemetry describing type of current connection\n\t// Things like connection mode, service info, etc.\n\t// Called when connection state changes (connect / disconnect)\n\treadonly connectionProps: ITelemetryProperties;\n\n\t// Verbose information about connection logged to telemetry in case of issues with\n\t// maintaining healthy connection, including op gaps, not receiving join op in time, etc.\n\t// Contains details information, like sequence numbers at connection time, initial ops info, etc.\n\treadonly connectionVerboseProps: ITelemetryProperties;\n\n\t/**\n\t * Prepares message to be sent. Fills in clientSequenceNumber.\n\t * Called only when active connection is present.\n\t */\n\tprepareMessageToSend(\n\t\tmessage: Omit<IDocumentMessage, \"clientSequenceNumber\">,\n\t): IDocumentMessage | undefined;\n\n\t/**\n\t * Called before incoming message is processed. Incoming messages can be combing from connection,\n\t * but also could come from storage.\n\t * This call allows connection manager to adjust knowledge about acked ops sent on previous connection.\n\t * Can be called at any time, including when there is no active connection.\n\t */\n\tbeforeProcessingIncomingOp(message: ISequencedDocumentMessage): void;\n\n\t/**\n\t * Submits signal to relay service.\n\t * Called only when active connection is present.\n\t */\n\tsubmitSignal(content: any): void;\n\n\t/**\n\t * Submits messages to relay service.\n\t * Called only when active connection is present.\n\t */\n\tsendMessages(messages: IDocumentMessage[]): void;\n\n\t/**\n\t * Initiates connection to relay service (noop if already connected).\n\t */\n\tconnect(connectionMode?: ConnectionMode): void;\n\n\t/**\n\t * Disposed connection manager\n\t */\n\tdispose(error?: ICriticalContainerError, switchToReadonly?: boolean): void;\n\n\tget connectionMode(): ConnectionMode;\n}\n\n/**\n * This interface represents a set of callbacks provided by DeltaManager to IConnectionManager on its creation\n * IConnectionManager instance will use them to communicate to DeltaManager about various events.\n */\nexport interface IConnectionManagerFactoryArgs {\n\t/**\n\t * Called by connection manager for each incoming op. Some ops maybe delivered before\n\t * connectHandler is called (initial ops on socket connection)\n\t */\n\treadonly incomingOpHandler: (messages: ISequencedDocumentMessage[], reason: string) => void;\n\n\t/**\n\t * Called by connection manager for each incoming signals.\n\t * Maybe called before connectHandler is called (initial signals on socket connection)\n\t */\n\treadonly signalHandler: (message: ISignalMessage) => void;\n\n\t/**\n\t * Called when connection manager experiences delay in connecting to relay service.\n\t * This can happen because client is offline, or service is busy and asks to not connect for some time.\n\t * Can be called many times while not connected.\n\t * Situation is considered resolved when connection is established and connectHandler is called.\n\t */\n\treadonly reconnectionDelayHandler: (delayMs: number, error: unknown) => void;\n\n\t/**\n\t * Called by connection manager whenever critical error happens and container should be closed.\n\t * Expects dispose() call in response to this call.\n\t */\n\treadonly closeHandler: (error?: any) => void;\n\n\t/**\n\t * Called whenever connection to relay service is lost.\n\t */\n\treadonly disconnectHandler: (reason: string) => void;\n\n\t/**\n\t * Called whenever new connection to rely service is established\n\t */\n\treadonly connectHandler: (connection: IConnectionDetailsInternal) => void;\n\n\t/**\n\t * Called whenever ping/pong messages are roundtripped on connection.\n\t *\n\t * @deprecated No replacement API intended.\n\t */\n\treadonly pongHandler: (latency: number) => void;\n\n\t/**\n\t * Called whenever connection type changes from writable to read-only or vice versa.\n\t *\n\t * @remarks\n\t *\n\t * Connection can be read-only if user has no edit permissions, or if container forced\n\t * connection to be read-only.\n\t * This should not be confused with \"read\" / \"write\"connection mode which is internal\n\t * optimization.\n\t *\n\t * @param readonly - Whether or not the container is now read-only.\n\t * `undefined` indicates that user permissions are not yet known.\n\t */\n\treadonly readonlyChangeHandler: (readonly?: boolean) => void;\n}\n\n/**\n *\n * @param codeDetails- - Data structure used to describe the code to load on the Fluid document\n * @returns The name of the Fluid package\n */\nexport const getPackageName = (\n\tcodeDetails: IFluidCodeDetails | undefined,\n): IContainerPackageInfo => {\n\tlet containerPackageName;\n\tif (codeDetails && \"name\" in codeDetails) {\n\t\tcontainerPackageName = codeDetails;\n\t} else if (isFluidPackage(codeDetails?.package)) {\n\t\tcontainerPackageName = codeDetails?.package.name;\n\t} else {\n\t\tcontainerPackageName = codeDetails?.package;\n\t}\n\treturn { name: containerPackageName };\n};\n"]}
|
package/lib/deltaManager.d.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import { default as AbortController } from "abort-controller";
|
|
6
6
|
import { ITelemetryLogger, IEventProvider, ITelemetryProperties, ITelemetryErrorEvent } from "@fluidframework/common-definitions";
|
|
7
|
-
import { IDeltaHandlerStrategy, IDeltaManager, IDeltaManagerEvents, IDeltaQueue, ICriticalContainerError, IThrottlingWarning } from "@fluidframework/container-definitions";
|
|
7
|
+
import { IDeltaHandlerStrategy, IDeltaManager, IDeltaManagerEvents, IDeltaQueue, ICriticalContainerError, IThrottlingWarning, IConnectionDetailsInternal } from "@fluidframework/container-definitions";
|
|
8
8
|
import { TypedEventEmitter } from "@fluidframework/common-utils";
|
|
9
9
|
import { IDocumentService } from "@fluidframework/driver-definitions";
|
|
10
10
|
import { IDocumentMessage, ISequencedDocumentMessage, ISignalMessage, MessageType, ConnectionMode } from "@fluidframework/protocol-definitions";
|
|
@@ -20,7 +20,8 @@ export interface IConnectionArgs {
|
|
|
20
20
|
*/
|
|
21
21
|
export interface IDeltaManagerInternalEvents extends IDeltaManagerEvents {
|
|
22
22
|
(event: "throttled", listener: (error: IThrottlingWarning) => void): any;
|
|
23
|
-
(event: "closed", listener: (error?: ICriticalContainerError) => void): any;
|
|
23
|
+
(event: "closed" | "disposed", listener: (error?: ICriticalContainerError) => void): any;
|
|
24
|
+
(event: "connect", listener: (details: IConnectionDetailsInternal, opsBehind?: number) => void): any;
|
|
24
25
|
}
|
|
25
26
|
/**
|
|
26
27
|
* Manages the flow of both inbound and outbound messages. This class ensures that shared objects receive delta
|
|
@@ -43,16 +44,21 @@ export declare class DeltaManager<TConnectionManager extends IConnectionManager>
|
|
|
43
44
|
private lastProcessedSequenceNumber;
|
|
44
45
|
private lastProcessedMessage;
|
|
45
46
|
private baseTerm;
|
|
47
|
+
/** count number of noops sent by the client which may not be acked */
|
|
48
|
+
private noOpCount;
|
|
49
|
+
/** Track clientSequenceNumber of the last op */
|
|
50
|
+
private lastClientSequenceNumber;
|
|
46
51
|
/**
|
|
47
52
|
* Track down the ops size.
|
|
48
|
-
|
|
53
|
+
*/
|
|
49
54
|
private opsSize;
|
|
50
55
|
private prevEnqueueMessagesReason;
|
|
51
56
|
private previouslyProcessedMessage;
|
|
52
57
|
private initSequenceNumber;
|
|
53
58
|
private readonly _inbound;
|
|
54
59
|
private readonly _inboundSignal;
|
|
55
|
-
private
|
|
60
|
+
private _closed;
|
|
61
|
+
private _disposed;
|
|
56
62
|
private handler;
|
|
57
63
|
private deltaStorage;
|
|
58
64
|
private readonly throttlingIdSet;
|
|
@@ -81,7 +87,7 @@ export declare class DeltaManager<TConnectionManager extends IConnectionManager>
|
|
|
81
87
|
get outbound(): IDeltaQueue<IDocumentMessage[]>;
|
|
82
88
|
get readOnlyInfo(): import("@fluidframework/container-definitions").ReadOnlyInfo;
|
|
83
89
|
get clientDetails(): import("@fluidframework/protocol-definitions").IClientDetails;
|
|
84
|
-
submit(type: MessageType, contents?: string, batch?: boolean, metadata?: any, compression?: string): number;
|
|
90
|
+
submit(type: MessageType, contents?: string, batch?: boolean, metadata?: any, compression?: string, referenceSequenceNumber?: number): number;
|
|
85
91
|
submitSignal(content: any): void;
|
|
86
92
|
flush(): void;
|
|
87
93
|
get connectionProps(): ITelemetryProperties;
|
|
@@ -103,8 +109,15 @@ export declare class DeltaManager<TConnectionManager extends IConnectionManager>
|
|
|
103
109
|
private getDeltas;
|
|
104
110
|
/**
|
|
105
111
|
* Closes the connection and clears inbound & outbound queues.
|
|
112
|
+
*
|
|
113
|
+
* @param doDispose - should the DeltaManager treat this close call as a dispose?
|
|
114
|
+
* Differences between close and dispose:
|
|
115
|
+
* - dispose will emit "disposed" event while close emits "closed"
|
|
116
|
+
* - dispose will remove all listeners
|
|
117
|
+
* - dispose can be called after closure, but not vis versa
|
|
106
118
|
*/
|
|
107
|
-
close(error?: ICriticalContainerError): void;
|
|
119
|
+
close(error?: ICriticalContainerError, doDispose?: boolean): void;
|
|
120
|
+
private disposeInternal;
|
|
108
121
|
refreshDelayInfo(id: string): void;
|
|
109
122
|
private disconnectHandler;
|
|
110
123
|
/**
|
|
@@ -122,8 +135,8 @@ export declare class DeltaManager<TConnectionManager extends IConnectionManager>
|
|
|
122
135
|
*/
|
|
123
136
|
private fetchMissingDeltas;
|
|
124
137
|
/**
|
|
125
|
-
|
|
126
|
-
|
|
138
|
+
* Retrieves the missing deltas between the given sequence numbers
|
|
139
|
+
*/
|
|
127
140
|
private fetchMissingDeltasCore;
|
|
128
141
|
/**
|
|
129
142
|
* Sorts pending ops and attempts to apply them
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"deltaManager.d.ts","sourceRoot":"","sources":["../src/deltaManager.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,OAAO,IAAI,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAE9D,OAAO,
|
|
1
|
+
{"version":3,"file":"deltaManager.d.ts","sourceRoot":"","sources":["../src/deltaManager.ts"],"names":[],"mappings":"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"}
|
package/lib/deltaManager.js
CHANGED
|
@@ -5,10 +5,10 @@
|
|
|
5
5
|
import { default as AbortController } from "abort-controller";
|
|
6
6
|
import { v4 as uuid } from "uuid";
|
|
7
7
|
import { assert, TypedEventEmitter } from "@fluidframework/common-utils";
|
|
8
|
-
import { normalizeError, logIfFalse, safeRaiseEvent
|
|
8
|
+
import { normalizeError, logIfFalse, safeRaiseEvent } from "@fluidframework/telemetry-utils";
|
|
9
9
|
import { DriverErrorType, } from "@fluidframework/driver-definitions";
|
|
10
10
|
import { MessageType, } from "@fluidframework/protocol-definitions";
|
|
11
|
-
import { NonRetryableError, isRuntimeMessage, MessageType2
|
|
11
|
+
import { NonRetryableError, isRuntimeMessage, MessageType2 } from "@fluidframework/driver-utils";
|
|
12
12
|
import { ThrottlingWarning, DataCorruptionError, extractSafePropertiesFromMessage, DataProcessingError, } from "@fluidframework/container-utils";
|
|
13
13
|
import { DeltaQueue } from "./deltaQueue";
|
|
14
14
|
/**
|
|
@@ -55,15 +55,20 @@ export class DeltaManager extends TypedEventEmitter {
|
|
|
55
55
|
this.lastObservedSeqNumber = 0;
|
|
56
56
|
this.lastProcessedSequenceNumber = 0;
|
|
57
57
|
this.baseTerm = 0;
|
|
58
|
+
/** count number of noops sent by the client which may not be acked */
|
|
59
|
+
this.noOpCount = 0;
|
|
60
|
+
/** Track clientSequenceNumber of the last op */
|
|
61
|
+
this.lastClientSequenceNumber = 0;
|
|
58
62
|
/**
|
|
59
63
|
* Track down the ops size.
|
|
60
|
-
|
|
64
|
+
*/
|
|
61
65
|
this.opsSize = 0;
|
|
62
66
|
// The sequence number we initially loaded from
|
|
63
67
|
// In case of reading from a snapshot or pending state, its value will be equal to
|
|
64
68
|
// the last message that got serialized.
|
|
65
69
|
this.initSequenceNumber = 0;
|
|
66
|
-
this.
|
|
70
|
+
this._closed = false;
|
|
71
|
+
this._disposed = false;
|
|
67
72
|
this.throttlingIdSet = new Set();
|
|
68
73
|
this.timeTillThrottling = 0;
|
|
69
74
|
this.closeAbortController = new AbortController();
|
|
@@ -112,9 +117,15 @@ export class DeltaManager extends TypedEventEmitter {
|
|
|
112
117
|
// - outbound is flipped back and forth in setupNewSuccessfulConnection / disconnectFromDeltaStream
|
|
113
118
|
// - inbound & inboundSignal are resumed in attachOpHandler() when we have handler setup
|
|
114
119
|
}
|
|
115
|
-
get active() {
|
|
116
|
-
|
|
117
|
-
|
|
120
|
+
get active() {
|
|
121
|
+
return this._active();
|
|
122
|
+
}
|
|
123
|
+
get disposed() {
|
|
124
|
+
return this._closed;
|
|
125
|
+
}
|
|
126
|
+
get IDeltaSender() {
|
|
127
|
+
return this;
|
|
128
|
+
}
|
|
118
129
|
get inbound() {
|
|
119
130
|
return this._inbound;
|
|
120
131
|
}
|
|
@@ -149,17 +160,31 @@ export class DeltaManager extends TypedEventEmitter {
|
|
|
149
160
|
return this._checkpointSequenceNumber !== undefined;
|
|
150
161
|
}
|
|
151
162
|
// Forwarding connection manager properties / IDeltaManager implementation
|
|
152
|
-
get maxMessageSize() {
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
get
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
163
|
+
get maxMessageSize() {
|
|
164
|
+
return this.connectionManager.maxMessageSize;
|
|
165
|
+
}
|
|
166
|
+
get version() {
|
|
167
|
+
return this.connectionManager.version;
|
|
168
|
+
}
|
|
169
|
+
get serviceConfiguration() {
|
|
170
|
+
return this.connectionManager.serviceConfiguration;
|
|
171
|
+
}
|
|
172
|
+
get outbound() {
|
|
173
|
+
return this.connectionManager.outbound;
|
|
174
|
+
}
|
|
175
|
+
get readOnlyInfo() {
|
|
176
|
+
return this.connectionManager.readOnlyInfo;
|
|
177
|
+
}
|
|
178
|
+
get clientDetails() {
|
|
179
|
+
return this.connectionManager.clientDetails;
|
|
180
|
+
}
|
|
181
|
+
submit(type, contents, batch = false, metadata, compression, referenceSequenceNumber) {
|
|
182
|
+
// Back-compat ADO:3455
|
|
183
|
+
const backCompatRefSeqNum = referenceSequenceNumber !== null && referenceSequenceNumber !== void 0 ? referenceSequenceNumber : this.lastProcessedSequenceNumber;
|
|
159
184
|
const messagePartial = {
|
|
160
185
|
contents,
|
|
161
186
|
metadata,
|
|
162
|
-
referenceSequenceNumber:
|
|
187
|
+
referenceSequenceNumber: backCompatRefSeqNum,
|
|
163
188
|
type,
|
|
164
189
|
compression,
|
|
165
190
|
};
|
|
@@ -175,13 +200,18 @@ export class DeltaManager extends TypedEventEmitter {
|
|
|
175
200
|
this.opsSize += contents.length;
|
|
176
201
|
}
|
|
177
202
|
this.messageBuffer.push(message);
|
|
203
|
+
if (message.type === MessageType.NoOp) {
|
|
204
|
+
this.noOpCount++;
|
|
205
|
+
}
|
|
178
206
|
this.emit("submitOp", message);
|
|
179
207
|
if (!batch) {
|
|
180
208
|
this.flush();
|
|
181
209
|
}
|
|
182
210
|
return message.clientSequenceNumber;
|
|
183
211
|
}
|
|
184
|
-
submitSignal(content) {
|
|
212
|
+
submitSignal(content) {
|
|
213
|
+
return this.connectionManager.submitSignal(content);
|
|
214
|
+
}
|
|
185
215
|
flush() {
|
|
186
216
|
var _a, _b, _c;
|
|
187
217
|
const batch = this.messageBuffer;
|
|
@@ -238,8 +268,10 @@ export class DeltaManager extends TypedEventEmitter {
|
|
|
238
268
|
// state. As requirements change, so should these checks.
|
|
239
269
|
assert(this.messageBuffer.length === 0, 0x0e9 /* "messageBuffer is not empty on new connection" */);
|
|
240
270
|
this.opsSize = 0;
|
|
241
|
-
this.
|
|
242
|
-
|
|
271
|
+
this.noOpCount = 0;
|
|
272
|
+
this.emit("connect", connection, checkpointSequenceNumber !== undefined
|
|
273
|
+
? this.lastObservedSeqNumber - this.lastSequenceNumber
|
|
274
|
+
: undefined);
|
|
243
275
|
// If we got some initial ops, then we know the gap and call above fetched ops to fill it.
|
|
244
276
|
// Same is true for "write" mode even if we have no ops - we will get "join" own op very very soon.
|
|
245
277
|
// However if we are connecting as view-only, then there is no good signal to realize if client is behind.
|
|
@@ -279,7 +311,7 @@ export class DeltaManager extends TypedEventEmitter {
|
|
|
279
311
|
// setupNewSuccessfulConnection. But it should do nothing, because there is no way to fetch ops before
|
|
280
312
|
// we know snapshot sequence number that is set in attachOpHandler. So all such calls should be noop.
|
|
281
313
|
assert(this.fetchReason === undefined, 0x268 /* "There can't be pending fetch that early in boot sequence!" */);
|
|
282
|
-
if (this.
|
|
314
|
+
if (this._closed) {
|
|
283
315
|
return;
|
|
284
316
|
}
|
|
285
317
|
this._inbound.resume();
|
|
@@ -394,13 +426,22 @@ export class DeltaManager extends TypedEventEmitter {
|
|
|
394
426
|
}
|
|
395
427
|
/**
|
|
396
428
|
* Closes the connection and clears inbound & outbound queues.
|
|
429
|
+
*
|
|
430
|
+
* @param doDispose - should the DeltaManager treat this close call as a dispose?
|
|
431
|
+
* Differences between close and dispose:
|
|
432
|
+
* - dispose will emit "disposed" event while close emits "closed"
|
|
433
|
+
* - dispose will remove all listeners
|
|
434
|
+
* - dispose can be called after closure, but not vis versa
|
|
397
435
|
*/
|
|
398
|
-
close(error) {
|
|
399
|
-
if (this.
|
|
436
|
+
close(error, doDispose) {
|
|
437
|
+
if (this._closed) {
|
|
438
|
+
if (doDispose === true) {
|
|
439
|
+
this.disposeInternal(error);
|
|
440
|
+
}
|
|
400
441
|
return;
|
|
401
442
|
}
|
|
402
|
-
this.
|
|
403
|
-
this.connectionManager.dispose(error);
|
|
443
|
+
this._closed = true;
|
|
444
|
+
this.connectionManager.dispose(error, doDispose !== true);
|
|
404
445
|
this.closeAbortController.abort();
|
|
405
446
|
this._inbound.clear();
|
|
406
447
|
this._inboundSignal.clear();
|
|
@@ -410,10 +451,23 @@ export class DeltaManager extends TypedEventEmitter {
|
|
|
410
451
|
this._inboundSignal.pause();
|
|
411
452
|
// Drop pending messages - this will ensure catchUp() does not go into infinite loop
|
|
412
453
|
this.pending = [];
|
|
454
|
+
if (doDispose === true) {
|
|
455
|
+
this.disposeInternal(error);
|
|
456
|
+
}
|
|
457
|
+
else {
|
|
458
|
+
this.emit("closed", error);
|
|
459
|
+
this.disposeInternal(error); // ! TODO: remove this call when Container close no longer disposes
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
disposeInternal(error) {
|
|
463
|
+
if (this._disposed) {
|
|
464
|
+
return;
|
|
465
|
+
}
|
|
466
|
+
this._disposed = true;
|
|
413
467
|
// This needs to be the last thing we do (before removing listeners), as it causes
|
|
414
468
|
// Container to dispose context and break ability of data stores / runtime to "hear"
|
|
415
469
|
// from delta manager, including notification (above) about readonly state.
|
|
416
|
-
this.emit("
|
|
470
|
+
this.emit("disposed", error);
|
|
417
471
|
this.removeAllListeners();
|
|
418
472
|
}
|
|
419
473
|
refreshDelayInfo(id) {
|
|
@@ -435,7 +489,7 @@ export class DeltaManager extends TypedEventEmitter {
|
|
|
435
489
|
emitDelayInfo(id, delayMs, error) {
|
|
436
490
|
const timeNow = Date.now();
|
|
437
491
|
this.throttlingIdSet.add(id);
|
|
438
|
-
if (delayMs > 0 &&
|
|
492
|
+
if (delayMs > 0 && timeNow + delayMs > this.timeTillThrottling) {
|
|
439
493
|
this.timeTillThrottling = timeNow + delayMs;
|
|
440
494
|
const throttlingWarning = ThrottlingWarning.wrap(error, delayMs / 1000 /* retryAfterSeconds */, this.logger);
|
|
441
495
|
this.emit("throttled", throttlingWarning);
|
|
@@ -499,12 +553,16 @@ export class DeltaManager extends TypedEventEmitter {
|
|
|
499
553
|
}
|
|
500
554
|
let eventName;
|
|
501
555
|
// Report if we found some issues
|
|
502
|
-
if (duplicate !== 0 ||
|
|
556
|
+
if (duplicate !== 0 ||
|
|
557
|
+
(gap !== 0 && !allowGaps) ||
|
|
558
|
+
(initialGap > 0 && this.fetchReason === undefined)) {
|
|
503
559
|
eventName = "enqueueMessages";
|
|
504
560
|
// Also report if we are fetching ops, and same range comes in, thus making this fetch obsolete.
|
|
505
561
|
}
|
|
506
|
-
else if (this.fetchReason !== undefined &&
|
|
507
|
-
|
|
562
|
+
else if (this.fetchReason !== undefined &&
|
|
563
|
+
this.fetchReason !== reason &&
|
|
564
|
+
from <= this.lastQueuedSequenceNumber + 1 &&
|
|
565
|
+
last > this.lastQueuedSequenceNumber) {
|
|
508
566
|
eventName = "enqueueMessagesExtraFetch";
|
|
509
567
|
}
|
|
510
568
|
// Report if there is something to report
|
|
@@ -535,8 +593,8 @@ export class DeltaManager extends TypedEventEmitter {
|
|
|
535
593
|
// hit. One example is that some clients could be submitting ops to two different service
|
|
536
594
|
// instances such that the same sequence number is reused for two different ops.
|
|
537
595
|
// pre-0.58 error message: twoMessagesWithSameSeqNumAndDifferentPayload
|
|
538
|
-
"Found two messages with the same sequenceNumber but different payloads. Likely to be a "
|
|
539
|
-
|
|
596
|
+
"Found two messages with the same sequenceNumber but different payloads. Likely to be a " +
|
|
597
|
+
"service issue", DriverErrorType.fileOverwrittenInStorage, {
|
|
540
598
|
clientId: this.connectionManager.clientId,
|
|
541
599
|
sequenceNumber: message.sequenceNumber,
|
|
542
600
|
message1,
|
|
@@ -577,11 +635,25 @@ export class DeltaManager extends TypedEventEmitter {
|
|
|
577
635
|
throw new DataCorruptionError("Mismatch in clientId", Object.assign(Object.assign({}, extractSafePropertiesFromMessage(message)), { messageType: message.type }));
|
|
578
636
|
}
|
|
579
637
|
// TODO Remove after SPO picks up the latest build.
|
|
580
|
-
if (typeof message.contents === "string"
|
|
581
|
-
|
|
582
|
-
|
|
638
|
+
if (typeof message.contents === "string" &&
|
|
639
|
+
message.contents !== "" &&
|
|
640
|
+
message.type !== MessageType.ClientLeave) {
|
|
583
641
|
message.contents = JSON.parse(message.contents);
|
|
584
642
|
}
|
|
643
|
+
// Validate client sequence number has no gap. Decrement the noOpCount by gap
|
|
644
|
+
// If the count ends up negative, that means we have a real gap and throw error
|
|
645
|
+
if (this.connectionManager.clientId !== undefined &&
|
|
646
|
+
this.connectionManager.clientId === message.clientId) {
|
|
647
|
+
if (message.type === MessageType.NoOp) {
|
|
648
|
+
this.noOpCount--;
|
|
649
|
+
}
|
|
650
|
+
const clientSeqNumGap = message.clientSequenceNumber - this.lastClientSequenceNumber - 1;
|
|
651
|
+
this.noOpCount -= clientSeqNumGap;
|
|
652
|
+
if (this.noOpCount < 0) {
|
|
653
|
+
throw new Error(`gap in client sequence number: ${clientSeqNumGap}`);
|
|
654
|
+
}
|
|
655
|
+
this.lastClientSequenceNumber = message.clientSequenceNumber;
|
|
656
|
+
}
|
|
585
657
|
this.connectionManager.beforeProcessingIncomingOp(message);
|
|
586
658
|
// Watch the minimum sequence number and be ready to update as needed
|
|
587
659
|
if (this.minSequenceNumber > message.minimumSequenceNumber) {
|
|
@@ -592,7 +664,7 @@ export class DeltaManager extends TypedEventEmitter {
|
|
|
592
664
|
// reference sequence number as this op.
|
|
593
665
|
// System ops (when no clients are connected) are the only ops where equation is possible.
|
|
594
666
|
const diff = message.sequenceNumber - message.minimumSequenceNumber;
|
|
595
|
-
if (diff < 0 || diff === 0 && message.clientId !== null) {
|
|
667
|
+
if (diff < 0 || (diff === 0 && message.clientId !== null)) {
|
|
596
668
|
throw new DataCorruptionError("MSN has to be lower than sequence #", extractSafePropertiesFromMessage(message));
|
|
597
669
|
}
|
|
598
670
|
this.minSequenceNumber = message.minimumSequenceNumber;
|
|
@@ -627,16 +699,19 @@ export class DeltaManager extends TypedEventEmitter {
|
|
|
627
699
|
});
|
|
628
700
|
}
|
|
629
701
|
/**
|
|
630
|
-
|
|
631
|
-
|
|
702
|
+
* Retrieves the missing deltas between the given sequence numbers
|
|
703
|
+
*/
|
|
632
704
|
async fetchMissingDeltasCore(reason, cacheOnly, to) {
|
|
633
705
|
var _a;
|
|
634
706
|
// Exit out early if we're already fetching deltas
|
|
635
707
|
if (this.fetchReason !== undefined) {
|
|
636
708
|
return;
|
|
637
709
|
}
|
|
638
|
-
if (this.
|
|
639
|
-
this.logger.sendTelemetryEvent({
|
|
710
|
+
if (this._closed) {
|
|
711
|
+
this.logger.sendTelemetryEvent({
|
|
712
|
+
eventName: "fetchMissingDeltasClosedConnection",
|
|
713
|
+
reason,
|
|
714
|
+
});
|
|
640
715
|
return;
|
|
641
716
|
}
|
|
642
717
|
if (this.handler === undefined) {
|
|
@@ -678,7 +753,7 @@ export class DeltaManager extends TypedEventEmitter {
|
|
|
678
753
|
* Sorts pending ops and attempts to apply them
|
|
679
754
|
*/
|
|
680
755
|
processPendingOps(reason) {
|
|
681
|
-
if (this.
|
|
756
|
+
if (this._closed) {
|
|
682
757
|
return;
|
|
683
758
|
}
|
|
684
759
|
assert(this.handler !== undefined, 0x26c /* "handler should be installed" */);
|