@fluidframework/container-loader 2.0.0-dev.5.2.0.169897 → 2.0.0-dev.6.4.0.191258
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/CHANGELOG.md +162 -0
- package/README.md +10 -6
- package/dist/audience.d.ts +1 -0
- package/dist/audience.d.ts.map +1 -1
- package/dist/audience.js +5 -3
- package/dist/audience.js.map +1 -1
- package/dist/catchUpMonitor.d.ts +1 -1
- package/dist/catchUpMonitor.d.ts.map +1 -1
- package/dist/catchUpMonitor.js +2 -2
- package/dist/catchUpMonitor.js.map +1 -1
- package/dist/connectionManager.d.ts +6 -6
- package/dist/connectionManager.d.ts.map +1 -1
- package/dist/connectionManager.js +97 -93
- package/dist/connectionManager.js.map +1 -1
- package/dist/connectionStateHandler.d.ts +19 -15
- package/dist/connectionStateHandler.d.ts.map +1 -1
- package/dist/connectionStateHandler.js +59 -59
- package/dist/connectionStateHandler.js.map +1 -1
- package/dist/container.d.ts +48 -38
- package/dist/container.d.ts.map +1 -1
- package/dist/container.js +447 -325
- package/dist/container.js.map +1 -1
- package/dist/containerContext.d.ts +22 -70
- package/dist/containerContext.d.ts.map +1 -1
- package/dist/containerContext.js +24 -221
- 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 +47 -16
- package/dist/containerStorageAdapter.js.map +1 -1
- package/dist/contracts.d.ts +21 -10
- package/dist/contracts.d.ts.map +1 -1
- package/dist/contracts.js +3 -3
- package/dist/contracts.js.map +1 -1
- package/dist/debugLogger.d.ts +30 -0
- package/dist/debugLogger.d.ts.map +1 -0
- package/dist/debugLogger.js +95 -0
- package/dist/debugLogger.js.map +1 -0
- package/dist/deltaManager.d.ts +21 -9
- package/dist/deltaManager.d.ts.map +1 -1
- package/dist/deltaManager.js +114 -66
- package/dist/deltaManager.js.map +1 -1
- package/dist/deltaQueue.d.ts +1 -1
- package/dist/deltaQueue.d.ts.map +1 -1
- package/dist/deltaQueue.js +10 -10
- package/dist/deltaQueue.js.map +1 -1
- package/dist/disposal.d.ts +13 -0
- package/dist/disposal.d.ts.map +1 -0
- package/dist/disposal.js +25 -0
- package/dist/disposal.js.map +1 -0
- package/dist/error.d.ts +23 -0
- package/dist/error.d.ts.map +1 -0
- package/dist/error.js +32 -0
- package/dist/error.js.map +1 -0
- package/dist/loader.d.ts +23 -5
- package/dist/loader.d.ts.map +1 -1
- package/dist/loader.js +82 -51
- package/dist/loader.js.map +1 -1
- package/dist/noopHeuristic.d.ts +23 -0
- package/dist/noopHeuristic.d.ts.map +1 -0
- package/dist/noopHeuristic.js +90 -0
- package/dist/noopHeuristic.js.map +1 -0
- 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 +9 -12
- package/dist/protocol.d.ts.map +1 -1
- package/dist/protocol.js +26 -7
- package/dist/protocol.js.map +1 -1
- package/dist/protocolTreeDocumentStorageService.d.ts +1 -1
- package/dist/protocolTreeDocumentStorageService.d.ts.map +1 -1
- package/dist/protocolTreeDocumentStorageService.js.map +1 -1
- package/dist/quorum.d.ts +1 -14
- package/dist/quorum.d.ts.map +1 -1
- package/dist/quorum.js +1 -29
- package/dist/quorum.js.map +1 -1
- package/dist/retriableDocumentStorageService.d.ts +1 -1
- package/dist/retriableDocumentStorageService.d.ts.map +1 -1
- package/dist/retriableDocumentStorageService.js +4 -4
- package/dist/retriableDocumentStorageService.js.map +1 -1
- package/dist/utils.d.ts +8 -1
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +30 -11
- package/dist/utils.js.map +1 -1
- package/lib/audience.d.ts +1 -0
- package/lib/audience.d.ts.map +1 -1
- package/lib/audience.js +4 -2
- package/lib/audience.js.map +1 -1
- package/lib/catchUpMonitor.d.ts +1 -1
- package/lib/catchUpMonitor.d.ts.map +1 -1
- package/lib/catchUpMonitor.js +1 -1
- package/lib/catchUpMonitor.js.map +1 -1
- package/lib/connectionManager.d.ts +6 -6
- package/lib/connectionManager.d.ts.map +1 -1
- package/lib/connectionManager.js +74 -67
- package/lib/connectionManager.js.map +1 -1
- package/lib/connectionStateHandler.d.ts +19 -15
- package/lib/connectionStateHandler.d.ts.map +1 -1
- package/lib/connectionStateHandler.js +36 -36
- package/lib/connectionStateHandler.js.map +1 -1
- package/lib/container.d.ts +48 -38
- package/lib/container.d.ts.map +1 -1
- package/lib/container.js +414 -292
- package/lib/container.js.map +1 -1
- package/lib/containerContext.d.ts +22 -70
- package/lib/containerContext.d.ts.map +1 -1
- package/lib/containerContext.js +24 -221
- 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 +43 -12
- package/lib/containerStorageAdapter.js.map +1 -1
- package/lib/contracts.d.ts +21 -10
- package/lib/contracts.d.ts.map +1 -1
- package/lib/contracts.js +3 -3
- package/lib/contracts.js.map +1 -1
- package/lib/debugLogger.d.ts +30 -0
- package/lib/debugLogger.d.ts.map +1 -0
- package/lib/debugLogger.js +91 -0
- package/lib/debugLogger.js.map +1 -0
- package/lib/deltaManager.d.ts +21 -9
- package/lib/deltaManager.d.ts.map +1 -1
- package/lib/deltaManager.js +88 -37
- package/lib/deltaManager.js.map +1 -1
- package/lib/deltaQueue.d.ts +1 -1
- package/lib/deltaQueue.d.ts.map +1 -1
- package/lib/deltaQueue.js +3 -3
- package/lib/deltaQueue.js.map +1 -1
- package/lib/disposal.d.ts +13 -0
- package/lib/disposal.d.ts.map +1 -0
- package/lib/disposal.js +21 -0
- package/lib/disposal.js.map +1 -0
- package/lib/error.d.ts +23 -0
- package/lib/error.d.ts.map +1 -0
- package/lib/error.js +28 -0
- package/lib/error.js.map +1 -0
- package/lib/loader.d.ts +23 -5
- package/lib/loader.d.ts.map +1 -1
- package/lib/loader.js +82 -51
- package/lib/loader.js.map +1 -1
- package/lib/noopHeuristic.d.ts +23 -0
- package/lib/noopHeuristic.d.ts.map +1 -0
- package/lib/{collabWindowTracker.js → noopHeuristic.js} +31 -42
- package/lib/noopHeuristic.js.map +1 -0
- 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 +9 -12
- package/lib/protocol.d.ts.map +1 -1
- package/lib/protocol.js +24 -6
- package/lib/protocol.js.map +1 -1
- package/lib/protocolTreeDocumentStorageService.d.ts +1 -1
- package/lib/protocolTreeDocumentStorageService.d.ts.map +1 -1
- package/lib/protocolTreeDocumentStorageService.js.map +1 -1
- package/lib/quorum.d.ts +1 -14
- package/lib/quorum.d.ts.map +1 -1
- package/lib/quorum.js +0 -26
- package/lib/quorum.js.map +1 -1
- package/lib/retriableDocumentStorageService.d.ts +1 -1
- package/lib/retriableDocumentStorageService.d.ts.map +1 -1
- package/lib/retriableDocumentStorageService.js +2 -2
- package/lib/retriableDocumentStorageService.js.map +1 -1
- package/lib/utils.d.ts +8 -1
- package/lib/utils.d.ts.map +1 -1
- package/lib/utils.js +25 -7
- package/lib/utils.js.map +1 -1
- package/package.json +26 -28
- package/src/audience.ts +7 -1
- package/src/catchUpMonitor.ts +2 -2
- package/src/connectionManager.ts +76 -52
- package/src/connectionStateHandler.ts +46 -48
- package/src/container.ts +561 -326
- package/src/containerContext.ts +31 -349
- package/src/containerStorageAdapter.ts +49 -6
- package/src/contracts.ts +27 -13
- package/src/debugLogger.ts +113 -0
- package/src/deltaManager.ts +93 -36
- package/src/deltaQueue.ts +2 -1
- package/src/disposal.ts +25 -0
- package/src/error.ts +44 -0
- package/src/loader.ts +84 -36
- package/src/{collabWindowTracker.ts → noopHeuristic.ts} +38 -47
- package/src/packageVersion.ts +1 -1
- package/src/protocol.ts +26 -16
- package/src/protocolTreeDocumentStorageService.ts +1 -1
- package/src/quorum.ts +1 -40
- package/src/retriableDocumentStorageService.ts +3 -4
- package/src/utils.ts +33 -8
- package/dist/collabWindowTracker.d.ts +0 -19
- package/dist/collabWindowTracker.d.ts.map +0 -1
- package/dist/collabWindowTracker.js +0 -101
- package/dist/collabWindowTracker.js.map +0 -1
- package/dist/deltaManagerProxy.d.ts +0 -42
- package/dist/deltaManagerProxy.d.ts.map +0 -1
- package/dist/deltaManagerProxy.js +0 -79
- package/dist/deltaManagerProxy.js.map +0 -1
- package/lib/collabWindowTracker.d.ts +0 -19
- package/lib/collabWindowTracker.d.ts.map +0 -1
- package/lib/collabWindowTracker.js.map +0 -1
- package/lib/deltaManagerProxy.d.ts +0 -42
- package/lib/deltaManagerProxy.d.ts.map +0 -1
- package/lib/deltaManagerProxy.js +0 -74
- package/lib/deltaManagerProxy.js.map +0 -1
- package/src/deltaManagerProxy.ts +0 -109
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
|
+
* Licensed under the MIT License.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import {
|
|
7
|
+
ITelemetryBaseEvent,
|
|
8
|
+
ITelemetryBaseLogger,
|
|
9
|
+
ITelemetryProperties,
|
|
10
|
+
} from "@fluidframework/core-interfaces";
|
|
11
|
+
import { performance } from "@fluid-internal/client-utils";
|
|
12
|
+
import { debug as registerDebug, IDebugger } from "debug";
|
|
13
|
+
import {
|
|
14
|
+
ITelemetryLoggerExt,
|
|
15
|
+
ITelemetryLoggerPropertyBags,
|
|
16
|
+
createMultiSinkLogger,
|
|
17
|
+
eventNamespaceSeparator,
|
|
18
|
+
formatTick,
|
|
19
|
+
} from "@fluidframework/telemetry-utils";
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Implementation of debug logger
|
|
23
|
+
*/
|
|
24
|
+
export class DebugLogger implements ITelemetryBaseLogger {
|
|
25
|
+
/**
|
|
26
|
+
* Mix in debug logger with another logger.
|
|
27
|
+
* Returned logger will output events to both newly created debug logger, as well as base logger
|
|
28
|
+
* @param namespace - Telemetry event name prefix to add to all events
|
|
29
|
+
* @param properties - Base properties to add to all events
|
|
30
|
+
* @param propertyGetters - Getters to add additional properties to all events
|
|
31
|
+
* @param baseLogger - Base logger to output events (in addition to debug logger being created). Can be undefined.
|
|
32
|
+
*/
|
|
33
|
+
public static mixinDebugLogger(
|
|
34
|
+
namespace: string,
|
|
35
|
+
baseLogger?: ITelemetryBaseLogger,
|
|
36
|
+
properties?: ITelemetryLoggerPropertyBags,
|
|
37
|
+
): ITelemetryLoggerExt {
|
|
38
|
+
// Setup base logger upfront, such that host can disable it (if needed)
|
|
39
|
+
const debug = registerDebug(namespace);
|
|
40
|
+
|
|
41
|
+
// Create one for errors that is always enabled
|
|
42
|
+
// It can be silenced by replacing console.error if the debug namespace is not enabled.
|
|
43
|
+
const debugErr = registerDebug(namespace);
|
|
44
|
+
debugErr.log = function (...args) {
|
|
45
|
+
if (debug.enabled === true) {
|
|
46
|
+
// if the namespace is enabled, just use the default logger
|
|
47
|
+
registerDebug.log(...args);
|
|
48
|
+
} else {
|
|
49
|
+
// other wise, use the console logger (which could be replaced and silenced)
|
|
50
|
+
console.error(...args);
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
debugErr.enabled = true;
|
|
54
|
+
|
|
55
|
+
return createMultiSinkLogger({
|
|
56
|
+
namespace,
|
|
57
|
+
loggers: [baseLogger, new DebugLogger(debug, debugErr)],
|
|
58
|
+
properties,
|
|
59
|
+
tryInheritProperties: true,
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
private constructor(private readonly debug: IDebugger, private readonly debugErr: IDebugger) {}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Send an event to debug loggers
|
|
67
|
+
*
|
|
68
|
+
* @param event - the event to send
|
|
69
|
+
*/
|
|
70
|
+
public send(event: ITelemetryBaseEvent): void {
|
|
71
|
+
const newEvent: ITelemetryProperties = { ...event };
|
|
72
|
+
const isError = newEvent.category === "error";
|
|
73
|
+
let logger = isError ? this.debugErr : this.debug;
|
|
74
|
+
|
|
75
|
+
// Use debug's coloring schema for base of the event
|
|
76
|
+
const index = event.eventName.lastIndexOf(eventNamespaceSeparator);
|
|
77
|
+
const name = event.eventName.substring(index + 1);
|
|
78
|
+
if (index > 0) {
|
|
79
|
+
logger = logger.extend(event.eventName.substring(0, index));
|
|
80
|
+
}
|
|
81
|
+
newEvent.eventName = undefined;
|
|
82
|
+
|
|
83
|
+
let tick = "";
|
|
84
|
+
tick = `tick=${formatTick(performance.now())}`;
|
|
85
|
+
|
|
86
|
+
// Extract stack to put it last, but also to avoid escaping '\n' in it by JSON.stringify below
|
|
87
|
+
const stack = newEvent.stack ?? "";
|
|
88
|
+
newEvent.stack = undefined;
|
|
89
|
+
|
|
90
|
+
// Watch out for circular references - they can come from two sources
|
|
91
|
+
// 1) error object - we do not control it and should remove it and retry
|
|
92
|
+
// 2) properties supplied by telemetry caller - that's a bug that should be addressed!
|
|
93
|
+
let payload: string;
|
|
94
|
+
try {
|
|
95
|
+
payload = JSON.stringify(newEvent);
|
|
96
|
+
} catch (error) {
|
|
97
|
+
newEvent.error = undefined;
|
|
98
|
+
payload = JSON.stringify(newEvent);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
if (payload === "{}") {
|
|
102
|
+
payload = "";
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// Force errors out, to help with diagnostics
|
|
106
|
+
if (isError) {
|
|
107
|
+
logger.enabled = true;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Print multi-line.
|
|
111
|
+
logger(`${name} ${payload} ${tick} ${stack}`);
|
|
112
|
+
}
|
|
113
|
+
}
|
package/src/deltaManager.ts
CHANGED
|
@@ -3,35 +3,36 @@
|
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import { default as AbortController } from "abort-controller";
|
|
7
6
|
import { v4 as uuid } from "uuid";
|
|
8
7
|
import {
|
|
8
|
+
IThrottlingWarning,
|
|
9
9
|
IEventProvider,
|
|
10
10
|
ITelemetryProperties,
|
|
11
11
|
ITelemetryErrorEvent,
|
|
12
|
-
} from "@fluidframework/
|
|
12
|
+
} from "@fluidframework/core-interfaces";
|
|
13
13
|
import {
|
|
14
|
-
|
|
14
|
+
ICriticalContainerError,
|
|
15
15
|
IDeltaManager,
|
|
16
16
|
IDeltaManagerEvents,
|
|
17
17
|
IDeltaQueue,
|
|
18
|
-
ICriticalContainerError,
|
|
19
|
-
IThrottlingWarning,
|
|
20
|
-
IConnectionDetailsInternal,
|
|
21
18
|
} from "@fluidframework/container-definitions";
|
|
22
|
-
import {
|
|
19
|
+
import { TypedEventEmitter } from "@fluid-internal/client-utils";
|
|
20
|
+
import { assert } from "@fluidframework/core-utils";
|
|
23
21
|
import {
|
|
22
|
+
DataProcessingError,
|
|
23
|
+
extractSafePropertiesFromMessage,
|
|
24
24
|
normalizeError,
|
|
25
25
|
logIfFalse,
|
|
26
26
|
safeRaiseEvent,
|
|
27
27
|
isFluidError,
|
|
28
28
|
ITelemetryLoggerExt,
|
|
29
|
+
DataCorruptionError,
|
|
30
|
+
UsageError,
|
|
29
31
|
} from "@fluidframework/telemetry-utils";
|
|
30
32
|
import {
|
|
31
33
|
IDocumentDeltaStorageService,
|
|
32
34
|
IDocumentService,
|
|
33
|
-
|
|
34
|
-
IAnyDriverError,
|
|
35
|
+
DriverErrorTypes,
|
|
35
36
|
} from "@fluidframework/driver-definitions";
|
|
36
37
|
import {
|
|
37
38
|
IDocumentMessage,
|
|
@@ -41,21 +42,21 @@ import {
|
|
|
41
42
|
ConnectionMode,
|
|
42
43
|
} from "@fluidframework/protocol-definitions";
|
|
43
44
|
import { NonRetryableError, isRuntimeMessage, MessageType2 } from "@fluidframework/driver-utils";
|
|
45
|
+
|
|
44
46
|
import {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
} from "@fluidframework/container-utils";
|
|
51
|
-
import { IConnectionManagerFactoryArgs, IConnectionManager } from "./contracts";
|
|
47
|
+
IConnectionDetailsInternal,
|
|
48
|
+
IConnectionManager,
|
|
49
|
+
IConnectionManagerFactoryArgs,
|
|
50
|
+
IConnectionStateChangeReason,
|
|
51
|
+
} from "./contracts";
|
|
52
52
|
import { DeltaQueue } from "./deltaQueue";
|
|
53
53
|
import { OnlyValidTermValue } from "./protocol";
|
|
54
|
+
import { ThrottlingWarning } from "./error";
|
|
54
55
|
|
|
55
56
|
export interface IConnectionArgs {
|
|
56
57
|
mode?: ConnectionMode;
|
|
57
58
|
fetchOpsFromStorage?: boolean;
|
|
58
|
-
reason:
|
|
59
|
+
reason: IConnectionStateChangeReason;
|
|
59
60
|
}
|
|
60
61
|
|
|
61
62
|
/**
|
|
@@ -66,8 +67,33 @@ export interface IDeltaManagerInternalEvents extends IDeltaManagerEvents {
|
|
|
66
67
|
(event: "throttled", listener: (error: IThrottlingWarning) => void);
|
|
67
68
|
(event: "closed" | "disposed", listener: (error?: ICriticalContainerError) => void);
|
|
68
69
|
(event: "connect", listener: (details: IConnectionDetailsInternal, opsBehind?: number) => void);
|
|
69
|
-
(event: "establishingConnection", listener: (reason:
|
|
70
|
-
(
|
|
70
|
+
(event: "establishingConnection", listener: (reason: IConnectionStateChangeReason) => void);
|
|
71
|
+
(
|
|
72
|
+
event: "cancelEstablishingConnection",
|
|
73
|
+
listener: (reason: IConnectionStateChangeReason) => void,
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Batching makes assumptions about what might be on the metadata. This interface codifies those assumptions, but does not validate them.
|
|
79
|
+
*/
|
|
80
|
+
interface IBatchMetadata {
|
|
81
|
+
batch?: boolean;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Interface used to define a strategy for handling incoming delta messages
|
|
86
|
+
*/
|
|
87
|
+
export interface IDeltaHandlerStrategy {
|
|
88
|
+
/**
|
|
89
|
+
* Processes the message.
|
|
90
|
+
*/
|
|
91
|
+
process: (message: ISequencedDocumentMessage) => void;
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Processes the signal.
|
|
95
|
+
*/
|
|
96
|
+
processSignal: (message: ISignalMessage) => void;
|
|
71
97
|
}
|
|
72
98
|
|
|
73
99
|
/**
|
|
@@ -89,6 +115,17 @@ function isClientMessage(message: ISequencedDocumentMessage | IDocumentMessage):
|
|
|
89
115
|
}
|
|
90
116
|
}
|
|
91
117
|
|
|
118
|
+
/**
|
|
119
|
+
* Type is used to cast AbortController to represent new version of DOM API and prevent build issues
|
|
120
|
+
* TODO: Remove when typescript version of the repo contains the AbortSignal.reason property (AB#5045)
|
|
121
|
+
*/
|
|
122
|
+
type AbortControllerReal = AbortController & { abort(reason?: any): void };
|
|
123
|
+
/**
|
|
124
|
+
* Type is used to cast AbortSignal to represent new version of DOM API and prevent build issues
|
|
125
|
+
* TODO: Remove when typescript version of the repo contains the AbortSignal.reason property (AB#5045)
|
|
126
|
+
*/
|
|
127
|
+
type AbortSignalReal = AbortSignal & { reason: any };
|
|
128
|
+
|
|
92
129
|
/**
|
|
93
130
|
* Manages the flow of both inbound and outbound messages. This class ensures that shared objects receive delta
|
|
94
131
|
* messages in order regardless of possible network conditions or timings causing out of order delivery.
|
|
@@ -293,13 +330,16 @@ export class DeltaManager<TConnectionManager extends IConnectionManager>
|
|
|
293
330
|
|
|
294
331
|
if (batch.length === 1) {
|
|
295
332
|
assert(
|
|
296
|
-
batch[0].metadata?.batch === undefined,
|
|
333
|
+
(batch[0].metadata as IBatchMetadata)?.batch === undefined,
|
|
297
334
|
0x3c9 /* no batch markup on single message */,
|
|
298
335
|
);
|
|
299
336
|
} else {
|
|
300
|
-
assert(batch[0].metadata?.batch === true, 0x3ca /* no start batch markup */);
|
|
301
337
|
assert(
|
|
302
|
-
batch[
|
|
338
|
+
(batch[0].metadata as IBatchMetadata)?.batch === true,
|
|
339
|
+
0x3ca /* no start batch markup */,
|
|
340
|
+
);
|
|
341
|
+
assert(
|
|
342
|
+
(batch[batch.length - 1].metadata as IBatchMetadata)?.batch === false,
|
|
303
343
|
0x3cb /* no end batch markup */,
|
|
304
344
|
);
|
|
305
345
|
}
|
|
@@ -313,6 +353,7 @@ export class DeltaManager<TConnectionManager extends IConnectionManager>
|
|
|
313
353
|
return {
|
|
314
354
|
sequenceNumber: this.lastSequenceNumber,
|
|
315
355
|
opsSize: this.opsSize > 0 ? this.opsSize : undefined,
|
|
356
|
+
deltaManagerState: this._disposed ? "disposed" : this._closed ? "closed" : "open",
|
|
316
357
|
...this.connectionManager.connectionProps,
|
|
317
358
|
};
|
|
318
359
|
}
|
|
@@ -366,15 +407,17 @@ export class DeltaManager<TConnectionManager extends IConnectionManager>
|
|
|
366
407
|
reconnectionDelayHandler: (delayMs: number, error: unknown) =>
|
|
367
408
|
this.emitDelayInfo(this.deltaStreamDelayId, delayMs, error),
|
|
368
409
|
closeHandler: (error: any) => this.close(error),
|
|
369
|
-
disconnectHandler: (reason:
|
|
370
|
-
this.disconnectHandler(reason
|
|
410
|
+
disconnectHandler: (reason: IConnectionStateChangeReason) =>
|
|
411
|
+
this.disconnectHandler(reason),
|
|
371
412
|
connectHandler: (connection: IConnectionDetailsInternal) =>
|
|
372
413
|
this.connectHandler(connection),
|
|
373
414
|
pongHandler: (latency: number) => this.emit("pong", latency),
|
|
374
415
|
readonlyChangeHandler: (readonly?: boolean) =>
|
|
375
416
|
safeRaiseEvent(this, this.logger, "readonly", readonly),
|
|
376
|
-
establishConnectionHandler: (reason:
|
|
377
|
-
|
|
417
|
+
establishConnectionHandler: (reason: IConnectionStateChangeReason) =>
|
|
418
|
+
this.establishingConnection(reason),
|
|
419
|
+
cancelConnectionHandler: (reason: IConnectionStateChangeReason) =>
|
|
420
|
+
this.cancelEstablishingConnection(reason),
|
|
378
421
|
};
|
|
379
422
|
|
|
380
423
|
this.connectionManager = createConnectionManager(props);
|
|
@@ -414,11 +457,11 @@ export class DeltaManager<TConnectionManager extends IConnectionManager>
|
|
|
414
457
|
// - inbound & inboundSignal are resumed in attachOpHandler() when we have handler setup
|
|
415
458
|
}
|
|
416
459
|
|
|
417
|
-
private cancelEstablishingConnection(reason:
|
|
460
|
+
private cancelEstablishingConnection(reason: IConnectionStateChangeReason) {
|
|
418
461
|
this.emit("cancelEstablishingConnection", reason);
|
|
419
462
|
}
|
|
420
463
|
|
|
421
|
-
private establishingConnection(reason:
|
|
464
|
+
private establishingConnection(reason: IConnectionStateChangeReason) {
|
|
422
465
|
this.emit("establishingConnection", reason);
|
|
423
466
|
}
|
|
424
467
|
|
|
@@ -478,7 +521,7 @@ export class DeltaManager<TConnectionManager extends IConnectionManager>
|
|
|
478
521
|
minSequenceNumber: number,
|
|
479
522
|
sequenceNumber: number,
|
|
480
523
|
handler: IDeltaHandlerStrategy,
|
|
481
|
-
prefetchType: "cached" | "all" | "none" = "none",
|
|
524
|
+
prefetchType: "sequenceNumber" | "cached" | "all" | "none" = "none",
|
|
482
525
|
) {
|
|
483
526
|
this.initSequenceNumber = sequenceNumber;
|
|
484
527
|
this.lastProcessedSequenceNumber = sequenceNumber;
|
|
@@ -552,7 +595,7 @@ export class DeltaManager<TConnectionManager extends IConnectionManager>
|
|
|
552
595
|
// on the wire, we might be always behind.
|
|
553
596
|
// See comment at the end of "connect" handler
|
|
554
597
|
if (fetchOpsFromStorage) {
|
|
555
|
-
this.fetchMissingDeltas(args.reason);
|
|
598
|
+
this.fetchMissingDeltas(args.reason.text);
|
|
556
599
|
}
|
|
557
600
|
|
|
558
601
|
this.connectionManager.connect(args.reason, args.mode);
|
|
@@ -617,7 +660,8 @@ export class DeltaManager<TConnectionManager extends IConnectionManager>
|
|
|
617
660
|
// This is useless for known ranges (to is defined) as it means request is over either way.
|
|
618
661
|
// And it will cancel unbound request too early, not allowing us to learn where the end of the file is.
|
|
619
662
|
if (!opsFromFetch && cancelFetch(op)) {
|
|
620
|
-
|
|
663
|
+
// TODO: Remove when typescript version of the repo contains the AbortSignal.reason property (AB#5045)
|
|
664
|
+
(controller as AbortControllerReal).abort("DeltaManager getDeltas fetch cancelled");
|
|
621
665
|
this._inbound.off("push", opListener);
|
|
622
666
|
}
|
|
623
667
|
};
|
|
@@ -625,7 +669,11 @@ export class DeltaManager<TConnectionManager extends IConnectionManager>
|
|
|
625
669
|
try {
|
|
626
670
|
this._inbound.on("push", opListener);
|
|
627
671
|
assert(this.closeAbortController.signal.onabort === null, 0x1e8 /* "reentrancy" */);
|
|
628
|
-
this.closeAbortController.signal.onabort = () =>
|
|
672
|
+
this.closeAbortController.signal.onabort = () =>
|
|
673
|
+
// TODO: Remove when typescript version of the repo contains the AbortSignal.reason property (AB#5045)
|
|
674
|
+
(controller as AbortControllerReal).abort(
|
|
675
|
+
(this.closeAbortController.signal as AbortSignalReal).reason,
|
|
676
|
+
);
|
|
629
677
|
|
|
630
678
|
const stream = this.deltaStorage.fetchMessages(
|
|
631
679
|
from, // inclusive
|
|
@@ -649,6 +697,14 @@ export class DeltaManager<TConnectionManager extends IConnectionManager>
|
|
|
649
697
|
}
|
|
650
698
|
}
|
|
651
699
|
} finally {
|
|
700
|
+
if (controller.signal.aborted) {
|
|
701
|
+
this.logger.sendTelemetryEvent({
|
|
702
|
+
eventName: "DeltaManager_GetDeltasAborted",
|
|
703
|
+
fetchReason,
|
|
704
|
+
// TODO: Remove when typescript version of the repo contains the AbortSignal.reason property (AB#5045)
|
|
705
|
+
reason: (controller.signal as AbortSignalReal).reason,
|
|
706
|
+
});
|
|
707
|
+
}
|
|
652
708
|
this.closeAbortController.signal.onabort = null;
|
|
653
709
|
this._inbound.off("push", opListener);
|
|
654
710
|
assert(!opsFromFetch, 0x289 /* "logic error" */);
|
|
@@ -703,7 +759,8 @@ export class DeltaManager<TConnectionManager extends IConnectionManager>
|
|
|
703
759
|
}
|
|
704
760
|
|
|
705
761
|
private clearQueues() {
|
|
706
|
-
|
|
762
|
+
// TODO: Remove when typescript version of the repo contains the AbortSignal.reason property (AB#5045)
|
|
763
|
+
(this.closeAbortController as AbortControllerReal).abort("DeltaManager is closed");
|
|
707
764
|
|
|
708
765
|
this._inbound.clear();
|
|
709
766
|
this._inboundSignal.clear();
|
|
@@ -724,9 +781,9 @@ export class DeltaManager<TConnectionManager extends IConnectionManager>
|
|
|
724
781
|
}
|
|
725
782
|
}
|
|
726
783
|
|
|
727
|
-
private disconnectHandler(reason:
|
|
784
|
+
private disconnectHandler(reason: IConnectionStateChangeReason) {
|
|
728
785
|
this.messageBuffer.length = 0;
|
|
729
|
-
this.emit("disconnect", reason
|
|
786
|
+
this.emit("disconnect", reason);
|
|
730
787
|
}
|
|
731
788
|
|
|
732
789
|
/**
|
|
@@ -886,7 +943,7 @@ export class DeltaManager<TConnectionManager extends IConnectionManager>
|
|
|
886
943
|
// pre-0.58 error message: twoMessagesWithSameSeqNumAndDifferentPayload
|
|
887
944
|
"Found two messages with the same sequenceNumber but different payloads. Likely to be a " +
|
|
888
945
|
"service issue",
|
|
889
|
-
|
|
946
|
+
DriverErrorTypes.fileOverwrittenInStorage,
|
|
890
947
|
{
|
|
891
948
|
clientId: this.connectionManager.clientId,
|
|
892
949
|
sequenceNumber: message.sequenceNumber,
|
package/src/deltaQueue.ts
CHANGED
|
@@ -4,7 +4,8 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import { IDeltaQueue, IDeltaQueueEvents } from "@fluidframework/container-definitions";
|
|
7
|
-
import { assert
|
|
7
|
+
import { assert } from "@fluidframework/core-utils";
|
|
8
|
+
import { performance, TypedEventEmitter } from "@fluid-internal/client-utils";
|
|
8
9
|
import Deque from "double-ended-queue";
|
|
9
10
|
|
|
10
11
|
export interface IDeltaQueueWriter<T> {
|
package/src/disposal.ts
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
|
+
* Licensed under the MIT License.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { IDisposable } from "@fluidframework/core-interfaces";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Returns a wrapper around the provided function, which will only invoke the inner function if the provided
|
|
10
|
+
* {@link @fluidframework/core-interfaces#IDisposable | disposable} object has not yet been disposed.
|
|
11
|
+
*
|
|
12
|
+
* @throws Will throw an error if the item has already been disposed.
|
|
13
|
+
*/
|
|
14
|
+
export function doIfNotDisposed<T>(
|
|
15
|
+
disposable: IDisposable,
|
|
16
|
+
f: (...args: any[]) => T,
|
|
17
|
+
): (...args: any[]) => T {
|
|
18
|
+
return (...args: any[]): T => {
|
|
19
|
+
if (disposable.disposed) {
|
|
20
|
+
throw new Error("Already disposed");
|
|
21
|
+
} else {
|
|
22
|
+
return f(...args);
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
}
|
package/src/error.ts
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
|
+
* Licensed under the MIT License.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { ITelemetryProperties, IThrottlingWarning } from "@fluidframework/core-interfaces";
|
|
7
|
+
import { ContainerErrorTypes } from "@fluidframework/container-definitions";
|
|
8
|
+
import {
|
|
9
|
+
IFluidErrorBase,
|
|
10
|
+
ITelemetryLoggerExt,
|
|
11
|
+
LoggingError,
|
|
12
|
+
wrapErrorAndLog,
|
|
13
|
+
} from "@fluidframework/telemetry-utils";
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Warning emitted when requests to storage are being throttled.
|
|
17
|
+
*/
|
|
18
|
+
export class ThrottlingWarning extends LoggingError implements IThrottlingWarning, IFluidErrorBase {
|
|
19
|
+
/**
|
|
20
|
+
* {@inheritDoc @fluidframework/telemetry-utils#IFluidErrorBase.errorType}
|
|
21
|
+
*/
|
|
22
|
+
public readonly errorType = ContainerErrorTypes.throttlingError;
|
|
23
|
+
|
|
24
|
+
private constructor(
|
|
25
|
+
message: string,
|
|
26
|
+
readonly retryAfterSeconds: number,
|
|
27
|
+
props?: ITelemetryProperties,
|
|
28
|
+
) {
|
|
29
|
+
super(message, props);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Wrap the given error as a ThrottlingWarning
|
|
34
|
+
* Only preserves the error message, and applies the given retry after to the new warning object
|
|
35
|
+
*/
|
|
36
|
+
public static wrap(
|
|
37
|
+
error: unknown,
|
|
38
|
+
retryAfterSeconds: number,
|
|
39
|
+
logger: ITelemetryLoggerExt,
|
|
40
|
+
): IThrottlingWarning {
|
|
41
|
+
const newErrorFn = (errMsg: string) => new ThrottlingWarning(errMsg, retryAfterSeconds);
|
|
42
|
+
return wrapErrorAndLog(error, newErrorFn, logger);
|
|
43
|
+
}
|
|
44
|
+
}
|