filemail-sdk 9.0.8 → 9.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/client/uploader/healthMonitor/transferUploadHealthMonitor.d.ts +3 -2
- package/dist/src/client/uploader/healthMonitor/transferUploadHealthMonitor.d.ts.map +1 -1
- package/dist/src/client/uploader/healthMonitor/transferUploadHealthMonitor.js +53 -28
- package/dist/src/client/uploader/healthMonitor/transferUploadHealthMonitor.js.map +1 -1
- package/package.json +1 -1
|
@@ -5,7 +5,7 @@ import UploadHealthMonitorUnhealthyEventArgs from "./events/eventArgs/uploadHeal
|
|
|
5
5
|
import OnlineChecker from "./onlineChecker/onlineChecker.js";
|
|
6
6
|
export default class TransferUploadHealthMonitor {
|
|
7
7
|
#private;
|
|
8
|
-
constructor(onlineChecker: OnlineChecker, transferEventsEngine: EventsEngine,
|
|
8
|
+
constructor(onlineChecker: OnlineChecker, transferEventsEngine: EventsEngine, healthCheckInterval?: number);
|
|
9
9
|
start(): void;
|
|
10
10
|
private resetState;
|
|
11
11
|
stop(): void;
|
|
@@ -13,11 +13,12 @@ export default class TransferUploadHealthMonitor {
|
|
|
13
13
|
private unsubscribeFromTransferRunningEvents;
|
|
14
14
|
private transferMetadataDetermined;
|
|
15
15
|
private transferProgressed;
|
|
16
|
+
private restartHealthCheck;
|
|
16
17
|
private checkHealth;
|
|
18
|
+
private clearCurrentPeriodProgressHistory;
|
|
17
19
|
private determineIsHealthy;
|
|
18
20
|
private figureOutUnhealthyReasonWithNotifications;
|
|
19
21
|
private isOnlineResultToStatus;
|
|
20
|
-
private getHealthCheckInterval;
|
|
21
22
|
private notifyHealthy;
|
|
22
23
|
private notifyStartedCheckingUnhealthyReason;
|
|
23
24
|
private notifyUnhealthyInternetOkRestCheckingReason;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transferUploadHealthMonitor.d.ts","sourceRoot":"","sources":["../../../../../src/client/uploader/healthMonitor/transferUploadHealthMonitor.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,YAAY,MAAM,uCAAuC,CAAC;AAEtE,OAAO,gCAAgC,MAAM,8CAA8C,CAAC;AAC5F,OAAO,mCAAmC,MAAM,2DAA2D,CAAC;AAC5G,OAAO,qCAAqC,MAAM,6DAA6D,CAAC;AAChH,OAAO,aAAsC,MAAM,kCAAkC,CAAC;AAGtF,MAAM,CAAC,OAAO,OAAO,2BAA2B;;
|
|
1
|
+
{"version":3,"file":"transferUploadHealthMonitor.d.ts","sourceRoot":"","sources":["../../../../../src/client/uploader/healthMonitor/transferUploadHealthMonitor.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,YAAY,MAAM,uCAAuC,CAAC;AAEtE,OAAO,gCAAgC,MAAM,8CAA8C,CAAC;AAC5F,OAAO,mCAAmC,MAAM,2DAA2D,CAAC;AAC5G,OAAO,qCAAqC,MAAM,6DAA6D,CAAC;AAChH,OAAO,aAAsC,MAAM,kCAAkC,CAAC;AAGtF,MAAM,CAAC,OAAO,OAAO,2BAA2B;;gBAgBhC,aAAa,EAAE,aAAa,EAAE,oBAAoB,EAAE,YAAY,EAAE,mBAAmB,SAAS;IAY1G,KAAK;IAWL,OAAO,CAAC,UAAU;IAOlB,IAAI;IAQJ,OAAO,CAAC,gCAAgC;IAKxC,OAAO,CAAC,oCAAoC;IAK5C,OAAO,CAAC,0BAA0B,CAEhC;IAEF,OAAO,CAAC,kBAAkB,CAaxB;IAEF,OAAO,CAAC,kBAAkB;IAU1B,OAAO,CAAC,WAAW,CAmBjB;IAEF,OAAO,CAAC,iCAAiC;IAIzC,OAAO,CAAC,kBAAkB;YASZ,yCAAyC;IA8BvD,OAAO,CAAC,sBAAsB;IAO9B,OAAO,CAAC,aAAa;IAQrB,OAAO,CAAC,oCAAoC;IAa5C,OAAO,CAAC,2CAA2C;IAanD,OAAO,CAAC,+BAA+B;IAavC,OAAO,CAAC,yCAAyC;IAajD,OAAO,CAAC,0BAA0B;IAalC,gBAAgB,CAAC,SAAS,EAAE,gCAAgC,CAAC,OAAO,EAAE,OAAO,EAAE,CAAC,KAAK,EAAE,mCAAmC,KAAK,IAAI,GAAG,IAAI;IAC1I,gBAAgB,CAAC,SAAS,EAAE,gCAAgC,CAAC,SAAS,EAAE,OAAO,EAAE,CAAC,KAAK,EAAE,qCAAqC,KAAK,IAAI,GAAG,IAAI;CAIjJ"}
|
|
@@ -3,32 +3,37 @@ import TransferUploadHealthMonitorEvent from "./events/transferUploadHealthMonit
|
|
|
3
3
|
export default class TransferUploadHealthMonitor {
|
|
4
4
|
#onlineChecker;
|
|
5
5
|
#transferEventsEngine;
|
|
6
|
-
#
|
|
7
|
-
#healthCheckIntervalWhenUnhealthy;
|
|
6
|
+
#healthCheckInterval;
|
|
8
7
|
#timeout;
|
|
9
8
|
#fileServerUrl;
|
|
10
|
-
#
|
|
11
|
-
#
|
|
12
|
-
|
|
9
|
+
#currentPeriodProgressHistory = [];
|
|
10
|
+
#lastProgressEventFromPreviousPeriod;
|
|
11
|
+
#isCurrentlyHealthy = true;
|
|
12
|
+
constructor(onlineChecker, transferEventsEngine, healthCheckInterval = 15_000) {
|
|
13
13
|
if (!onlineChecker)
|
|
14
14
|
throw new Error(`Online checker can't be empty`);
|
|
15
15
|
if (!transferEventsEngine)
|
|
16
16
|
throw new Error(`Events engine can't be empty`);
|
|
17
17
|
this.#onlineChecker = onlineChecker;
|
|
18
18
|
this.#transferEventsEngine = transferEventsEngine;
|
|
19
|
-
this.#
|
|
20
|
-
this.#healthCheckIntervalWhenUnhealthy = healthCheckIntervalWhenUnhealthy;
|
|
19
|
+
this.#healthCheckInterval = healthCheckInterval;
|
|
21
20
|
}
|
|
22
21
|
start() {
|
|
22
|
+
if (this.#timeout)
|
|
23
|
+
throw new Error(`Health Monitor is already running`);
|
|
23
24
|
this.resetState();
|
|
24
25
|
this.subscribeToTransferRunningEvents();
|
|
25
|
-
this.#timeout = setTimeout(() => this.checkHealth(), this.#
|
|
26
|
+
this.#timeout = setTimeout(() => this.checkHealth(), this.#healthCheckInterval);
|
|
26
27
|
}
|
|
27
28
|
resetState() {
|
|
28
|
-
this.#
|
|
29
|
+
this.#currentPeriodProgressHistory = [];
|
|
30
|
+
this.#lastProgressEventFromPreviousPeriod = undefined;
|
|
31
|
+
this.#timeout = undefined;
|
|
32
|
+
this.#isCurrentlyHealthy = true;
|
|
29
33
|
}
|
|
30
34
|
stop() {
|
|
31
35
|
clearTimeout(this.#timeout);
|
|
36
|
+
this.#timeout = undefined;
|
|
32
37
|
this.unsubscribeFromTransferRunningEvents();
|
|
33
38
|
}
|
|
34
39
|
subscribeToTransferRunningEvents() {
|
|
@@ -43,22 +48,45 @@ export default class TransferUploadHealthMonitor {
|
|
|
43
48
|
this.#fileServerUrl = eventArgs.fileServerUrl;
|
|
44
49
|
};
|
|
45
50
|
transferProgressed = (eventArgs) => {
|
|
46
|
-
this.#
|
|
51
|
+
this.#currentPeriodProgressHistory.push({ time: Date.now(), eventArgs });
|
|
52
|
+
if (this.#isCurrentlyHealthy)
|
|
53
|
+
return;
|
|
54
|
+
const isHealthy = this.determineIsHealthy(eventArgs);
|
|
55
|
+
if (!isHealthy)
|
|
56
|
+
return;
|
|
57
|
+
this.notifyHealthy();
|
|
58
|
+
this.restartHealthCheck(eventArgs);
|
|
47
59
|
};
|
|
60
|
+
restartHealthCheck(currentProgressEvent) {
|
|
61
|
+
this.#currentPeriodProgressHistory = [];
|
|
62
|
+
this.#lastProgressEventFromPreviousPeriod = currentProgressEvent;
|
|
63
|
+
this.#isCurrentlyHealthy = true;
|
|
64
|
+
clearTimeout(this.#timeout);
|
|
65
|
+
this.#timeout = setTimeout(() => this.checkHealth(), this.#healthCheckInterval);
|
|
66
|
+
}
|
|
48
67
|
checkHealth = async () => {
|
|
49
|
-
const
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
if (isHealthy)
|
|
68
|
+
const currentPeriodLastProgressEvent = this.#currentPeriodProgressHistory.at(-1)?.eventArgs;
|
|
69
|
+
const isHealthy = this.determineIsHealthy(currentPeriodLastProgressEvent);
|
|
70
|
+
this.#lastProgressEventFromPreviousPeriod = currentPeriodLastProgressEvent || this.#lastProgressEventFromPreviousPeriod;
|
|
71
|
+
if (isHealthy) {
|
|
72
|
+
this.#isCurrentlyHealthy = true;
|
|
53
73
|
this.notifyHealthy();
|
|
54
|
-
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
this.#isCurrentlyHealthy = false;
|
|
55
77
|
await this.figureOutUnhealthyReasonWithNotifications();
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
this.#timeout = setTimeout(() => this.checkHealth(),
|
|
78
|
+
}
|
|
79
|
+
this.clearCurrentPeriodProgressHistory();
|
|
80
|
+
this.#timeout = setTimeout(() => this.checkHealth(), this.#healthCheckInterval);
|
|
59
81
|
};
|
|
82
|
+
clearCurrentPeriodProgressHistory() {
|
|
83
|
+
this.#currentPeriodProgressHistory = [];
|
|
84
|
+
}
|
|
60
85
|
determineIsHealthy(currentHistoryLastProgressEvent) {
|
|
61
|
-
|
|
86
|
+
const currentUploadedBytesTotalCount = currentHistoryLastProgressEvent?.uploadedBytesTotalCount ?? 0;
|
|
87
|
+
const previousPeriodUploadedBytesTotalCount = this.#lastProgressEventFromPreviousPeriod?.uploadedBytesTotalCount ?? 0;
|
|
88
|
+
const bytesSentThisPeriod = currentUploadedBytesTotalCount - previousPeriodUploadedBytesTotalCount;
|
|
89
|
+
return bytesSentThisPeriod > 0;
|
|
62
90
|
}
|
|
63
91
|
async figureOutUnhealthyReasonWithNotifications() {
|
|
64
92
|
this.notifyStartedCheckingUnhealthyReason();
|
|
@@ -87,12 +115,9 @@ export default class TransferUploadHealthMonitor {
|
|
|
87
115
|
return `Unknown`;
|
|
88
116
|
return isFileServerOnlineResult.isOnline ? `Ok` : `Error`;
|
|
89
117
|
}
|
|
90
|
-
getHealthCheckInterval(isHealthy) {
|
|
91
|
-
return isHealthy ? this.#healthCheckIntervalWhenHealthy : this.#healthCheckIntervalWhenUnhealthy;
|
|
92
|
-
}
|
|
93
118
|
notifyHealthy() {
|
|
94
119
|
const eventArgs = {
|
|
95
|
-
...this.#
|
|
120
|
+
...this.#lastProgressEventFromPreviousPeriod,
|
|
96
121
|
};
|
|
97
122
|
this.#transferEventsEngine.emit(TransferUploadHealthMonitorEvent.Healthy, eventArgs);
|
|
98
123
|
}
|
|
@@ -103,7 +128,7 @@ export default class TransferUploadHealthMonitor {
|
|
|
103
128
|
api: { status: `Checking` },
|
|
104
129
|
fileServer: { status: `Checking` },
|
|
105
130
|
},
|
|
106
|
-
...this.#
|
|
131
|
+
...this.#lastProgressEventFromPreviousPeriod,
|
|
107
132
|
};
|
|
108
133
|
this.#transferEventsEngine.emit(TransferUploadHealthMonitorEvent.Unhealthy, eventArgs);
|
|
109
134
|
}
|
|
@@ -114,7 +139,7 @@ export default class TransferUploadHealthMonitor {
|
|
|
114
139
|
api: { status: `Checking` },
|
|
115
140
|
fileServer: { status: `Checking` },
|
|
116
141
|
},
|
|
117
|
-
...this.#
|
|
142
|
+
...this.#lastProgressEventFromPreviousPeriod,
|
|
118
143
|
};
|
|
119
144
|
this.#transferEventsEngine.emit(TransferUploadHealthMonitorEvent.Unhealthy, eventArgs);
|
|
120
145
|
}
|
|
@@ -125,7 +150,7 @@ export default class TransferUploadHealthMonitor {
|
|
|
125
150
|
api: { status: `Unknown` },
|
|
126
151
|
fileServer: { status: `Unknown` },
|
|
127
152
|
},
|
|
128
|
-
...this.#
|
|
153
|
+
...this.#lastProgressEventFromPreviousPeriod,
|
|
129
154
|
};
|
|
130
155
|
this.#transferEventsEngine.emit(TransferUploadHealthMonitorEvent.Unhealthy, eventArgs);
|
|
131
156
|
}
|
|
@@ -136,7 +161,7 @@ export default class TransferUploadHealthMonitor {
|
|
|
136
161
|
api: apiError ? { status: `Error`, error: apiError } : { status: `Ok` },
|
|
137
162
|
fileServer: fileServerError ? { status: `Error`, error: fileServerError } : { status: fileServerStatus },
|
|
138
163
|
},
|
|
139
|
-
...this.#
|
|
164
|
+
...this.#lastProgressEventFromPreviousPeriod,
|
|
140
165
|
};
|
|
141
166
|
this.#transferEventsEngine.emit(TransferUploadHealthMonitorEvent.Unhealthy, eventArgs);
|
|
142
167
|
}
|
|
@@ -147,7 +172,7 @@ export default class TransferUploadHealthMonitor {
|
|
|
147
172
|
api: { status: `Ok` },
|
|
148
173
|
fileServer: { status: `Ok` },
|
|
149
174
|
},
|
|
150
|
-
...this.#
|
|
175
|
+
...this.#lastProgressEventFromPreviousPeriod,
|
|
151
176
|
};
|
|
152
177
|
this.#transferEventsEngine.emit(TransferUploadHealthMonitorEvent.Unhealthy, eventArgs);
|
|
153
178
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transferUploadHealthMonitor.js","sourceRoot":"","sources":["../../../../../src/client/uploader/healthMonitor/transferUploadHealthMonitor.ts"],"names":[],"mappings":"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","sourcesContent":["import TransferUploadEvent from \"../../../uploader/transferUploadEvent.js\";\r\n\r\nimport type EventsEngine from \"../../../utils/events/eventsEngine.js\";\r\nimport TransferUploadProgressedEventArgs from \"../../../uploader/eventArgs/transferUploadProgressedEventArgs.js\";\r\nimport TransferUploadHealthMonitorEvent from \"./events/transferUploadHealthMonitorEvent.js\";\r\nimport UploadHealthMonitorHealthyEventArgs from \"./events/eventArgs/uploadHealthMonitorHealthyEventArgs.js\";\r\nimport UploadHealthMonitorUnhealthyEventArgs from \"./events/eventArgs/uploadHealthMonitorUnhealthyEventArgs.js\";\r\nimport OnlineChecker, { OnlineCheckerResult } from \"./onlineChecker/onlineChecker.js\";\r\nimport { TransferMetadataDeterminedEventArgs } from \"../../../index.node.js\";\r\n\r\nexport default class TransferUploadHealthMonitor {\r\n readonly #onlineChecker: OnlineChecker;\r\n readonly #transferEventsEngine: EventsEngine;\r\n\r\n #healthCheckIntervalWhenHealthy: number;\r\n #healthCheckIntervalWhenUnhealthy: number;\r\n\r\n #timeout: NodeJS.Timeout | undefined;\r\n\r\n #fileServerUrl: string | undefined;\r\n\r\n #progressHistory: { time: number, eventArgs: TransferUploadProgressedEventArgs }[] = [];\r\n\r\n #lastProgressEvent: TransferUploadProgressedEventArgs | undefined;\r\n\r\n constructor(onlineChecker: OnlineChecker, transferEventsEngine: EventsEngine, healthCheckIntervalWhenHealthy = 15_000, healthCheckIntervalWhenUnhealthy = 5_000) {\r\n if (!onlineChecker)\r\n throw new Error(`Online checker can't be empty`);\r\n if (!transferEventsEngine)\r\n throw new Error(`Events engine can't be empty`);\r\n\r\n this.#onlineChecker = onlineChecker;\r\n this.#transferEventsEngine = transferEventsEngine;\r\n\r\n this.#healthCheckIntervalWhenHealthy = healthCheckIntervalWhenHealthy;\r\n this.#healthCheckIntervalWhenUnhealthy = healthCheckIntervalWhenUnhealthy;\r\n }\r\n\r\n start() {\r\n this.resetState();\r\n\r\n this.subscribeToTransferRunningEvents();\r\n\r\n this.#timeout = setTimeout(() => this.checkHealth(), this.#healthCheckIntervalWhenHealthy);\r\n }\r\n\r\n private resetState() {\r\n this.#progressHistory = [];\r\n }\r\n\r\n stop() {\r\n clearTimeout(this.#timeout);\r\n\r\n this.unsubscribeFromTransferRunningEvents();\r\n }\r\n\r\n private subscribeToTransferRunningEvents() {\r\n this.#transferEventsEngine.addEventListener(TransferUploadEvent.TransferMetadataDetermined, this.transferMetadataDetermined);\r\n this.#transferEventsEngine.addEventListener(TransferUploadEvent.TransferProgressed, this.transferProgressed);\r\n }\r\n\r\n private unsubscribeFromTransferRunningEvents() {\r\n this.#transferEventsEngine.removeEventListener(TransferUploadEvent.TransferMetadataDetermined, this.transferMetadataDetermined);\r\n this.#transferEventsEngine.removeEventListener(TransferUploadEvent.TransferProgressed, this.transferProgressed);\r\n }\r\n\r\n private transferMetadataDetermined = (eventArgs: TransferMetadataDeterminedEventArgs) => {\r\n this.#fileServerUrl = eventArgs.fileServerUrl;\r\n };\r\n\r\n private transferProgressed = (eventArgs: TransferUploadProgressedEventArgs) => {\r\n this.#progressHistory.push({ time: Date.now(), eventArgs });\r\n };\r\n\r\n private checkHealth = async (): Promise<void> => {\r\n const currentHistoryLastProgressEvent = this.#progressHistory.at(-1)?.eventArgs;\r\n\r\n this.#lastProgressEvent = currentHistoryLastProgressEvent || this.#lastProgressEvent;\r\n\r\n const isHealthy = this.determineIsHealthy(currentHistoryLastProgressEvent);\r\n\r\n if (isHealthy)\r\n this.notifyHealthy();\r\n else\r\n await this.figureOutUnhealthyReasonWithNotifications();\r\n\r\n this.resetState();\r\n\r\n const nextHealthCheck = this.getHealthCheckInterval(isHealthy);\r\n\r\n this.#timeout = setTimeout(() => this.checkHealth(), nextHealthCheck);\r\n };\r\n\r\n private determineIsHealthy(currentHistoryLastProgressEvent: TransferUploadProgressedEventArgs | undefined) {\r\n return currentHistoryLastProgressEvent !== undefined && currentHistoryLastProgressEvent.currentSpeedInBytesPerSecond > 0;\r\n }\r\n\r\n private async figureOutUnhealthyReasonWithNotifications(): Promise<void> {\r\n this.notifyStartedCheckingUnhealthyReason();\r\n\r\n const { isOnline: isInternetOnline, error: internetOnlineError } = await this.#onlineChecker.isInternetOnline();\r\n\r\n if (isInternetOnline)\r\n this.notifyUnhealthyInternetOkRestCheckingReason();\r\n else {\r\n this.notifyUnhealthyNoInternetReason(internetOnlineError);\r\n return;\r\n }\r\n\r\n const isApiOnlinePromise = this.#onlineChecker.isApiReachable();\r\n\r\n const isFileServerOnlinePromise = this.#fileServerUrl\r\n ? this.#onlineChecker.isFileServerReachable(this.#fileServerUrl)\r\n : Promise.resolve(undefined);\r\n\r\n const { isOnline: isApiOnline, error: apiOnlineError } = await isApiOnlinePromise;\r\n const isFileServerOnlineResult = await isFileServerOnlinePromise;\r\n\r\n if (isApiOnline && isFileServerOnlineResult?.isOnline === true)\r\n this.notifyUnhealthyAllOkReason();\r\n else {\r\n const fileServerStatus = this.isOnlineResultToStatus(isFileServerOnlineResult);\r\n\r\n this.notifyUnhealthyApiOrFileServerErrorReason(fileServerStatus, isFileServerOnlineResult?.error, apiOnlineError);\r\n }\r\n }\r\n\r\n private isOnlineResultToStatus(isFileServerOnlineResult: OnlineCheckerResult | undefined): `Ok` | `Error` | `Unknown` {\r\n if (!isFileServerOnlineResult)\r\n return `Unknown`;\r\n\r\n return isFileServerOnlineResult.isOnline ? `Ok` : `Error`;\r\n }\r\n\r\n private getHealthCheckInterval(isHealthy: boolean): number {\r\n return isHealthy ? this.#healthCheckIntervalWhenHealthy : this.#healthCheckIntervalWhenUnhealthy;\r\n }\r\n\r\n private notifyHealthy() {\r\n const eventArgs: UploadHealthMonitorHealthyEventArgs = {\r\n ...this.#lastProgressEvent,\r\n };\r\n\r\n this.#transferEventsEngine.emit(TransferUploadHealthMonitorEvent.Healthy, eventArgs);\r\n }\r\n\r\n private notifyStartedCheckingUnhealthyReason() {\r\n const eventArgs: UploadHealthMonitorUnhealthyEventArgs = {\r\n reason: {\r\n internet: { status: `Checking` },\r\n api: { status: `Checking` },\r\n fileServer: { status: `Checking` },\r\n },\r\n ...this.#lastProgressEvent,\r\n };\r\n\r\n this.#transferEventsEngine.emit(TransferUploadHealthMonitorEvent.Unhealthy, eventArgs);\r\n }\r\n\r\n private notifyUnhealthyInternetOkRestCheckingReason() {\r\n const eventArgs: UploadHealthMonitorUnhealthyEventArgs = {\r\n reason: {\r\n internet: { status: `Ok` },\r\n api: { status: `Checking` },\r\n fileServer: { status: `Checking` },\r\n },\r\n ...this.#lastProgressEvent,\r\n };\r\n\r\n this.#transferEventsEngine.emit(TransferUploadHealthMonitorEvent.Unhealthy, eventArgs);\r\n }\r\n\r\n private notifyUnhealthyNoInternetReason(error?: Error) {\r\n const eventArgs: UploadHealthMonitorUnhealthyEventArgs = {\r\n reason: {\r\n internet: { status: `Error`, error },\r\n api: { status: `Unknown` },\r\n fileServer: { status: `Unknown` },\r\n },\r\n ...this.#lastProgressEvent,\r\n };\r\n\r\n this.#transferEventsEngine.emit(TransferUploadHealthMonitorEvent.Unhealthy, eventArgs);\r\n }\r\n\r\n private notifyUnhealthyApiOrFileServerErrorReason(fileServerStatus: `Ok` | `Error` | `Unknown`, fileServerError: Error | undefined, apiError: Error | undefined) {\r\n const eventArgs: UploadHealthMonitorUnhealthyEventArgs = {\r\n reason: {\r\n internet: { status: `Ok` },\r\n api: apiError ? { status: `Error`, error: apiError } : { status: `Ok` },\r\n fileServer: fileServerError ? { status: `Error`, error: fileServerError } : { status: fileServerStatus },\r\n },\r\n ...this.#lastProgressEvent,\r\n };\r\n\r\n this.#transferEventsEngine.emit(TransferUploadHealthMonitorEvent.Unhealthy, eventArgs);\r\n }\r\n\r\n private notifyUnhealthyAllOkReason() {\r\n const eventArgs: UploadHealthMonitorUnhealthyEventArgs = {\r\n reason: {\r\n internet: { status: `Ok` },\r\n api: { status: `Ok` },\r\n fileServer: { status: `Ok` },\r\n },\r\n ...this.#lastProgressEvent,\r\n };\r\n\r\n this.#transferEventsEngine.emit(TransferUploadHealthMonitorEvent.Unhealthy, eventArgs);\r\n }\r\n\r\n addEventListener(eventName: TransferUploadHealthMonitorEvent.Healthy, handler: (event: UploadHealthMonitorHealthyEventArgs) => void): void\r\n addEventListener(eventName: TransferUploadHealthMonitorEvent.Unhealthy, handler: (event: UploadHealthMonitorUnhealthyEventArgs) => void): void\r\n addEventListener(eventName: string, handler: (arg?: any) => void): void {\r\n this.#transferEventsEngine.addEventListener(eventName, handler);\r\n }\r\n}"]}
|
|
1
|
+
{"version":3,"file":"transferUploadHealthMonitor.js","sourceRoot":"","sources":["../../../../../src/client/uploader/healthMonitor/transferUploadHealthMonitor.ts"],"names":[],"mappings":"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","sourcesContent":["import TransferUploadEvent from \"../../../uploader/transferUploadEvent.js\";\r\n\r\nimport type EventsEngine from \"../../../utils/events/eventsEngine.js\";\r\nimport TransferUploadProgressedEventArgs from \"../../../uploader/eventArgs/transferUploadProgressedEventArgs.js\";\r\nimport TransferUploadHealthMonitorEvent from \"./events/transferUploadHealthMonitorEvent.js\";\r\nimport UploadHealthMonitorHealthyEventArgs from \"./events/eventArgs/uploadHealthMonitorHealthyEventArgs.js\";\r\nimport UploadHealthMonitorUnhealthyEventArgs from \"./events/eventArgs/uploadHealthMonitorUnhealthyEventArgs.js\";\r\nimport OnlineChecker, { OnlineCheckerResult } from \"./onlineChecker/onlineChecker.js\";\r\nimport { TransferMetadataDeterminedEventArgs } from \"../../../index.node.js\";\r\n\r\nexport default class TransferUploadHealthMonitor {\r\n readonly #onlineChecker: OnlineChecker;\r\n readonly #transferEventsEngine: EventsEngine;\r\n\r\n #healthCheckInterval: number;\r\n\r\n #timeout: NodeJS.Timeout | undefined;\r\n\r\n #fileServerUrl: string | undefined;\r\n\r\n #currentPeriodProgressHistory: { time: number, eventArgs: TransferUploadProgressedEventArgs }[] = [];\r\n\r\n #lastProgressEventFromPreviousPeriod: TransferUploadProgressedEventArgs | undefined;\r\n\r\n #isCurrentlyHealthy = true;\r\n\r\n constructor(onlineChecker: OnlineChecker, transferEventsEngine: EventsEngine, healthCheckInterval = 15_000) {\r\n if (!onlineChecker)\r\n throw new Error(`Online checker can't be empty`);\r\n if (!transferEventsEngine)\r\n throw new Error(`Events engine can't be empty`);\r\n\r\n this.#onlineChecker = onlineChecker;\r\n this.#transferEventsEngine = transferEventsEngine;\r\n\r\n this.#healthCheckInterval = healthCheckInterval;\r\n }\r\n\r\n start() {\r\n if (this.#timeout)\r\n throw new Error(`Health Monitor is already running`);\r\n\r\n this.resetState();\r\n\r\n this.subscribeToTransferRunningEvents();\r\n\r\n this.#timeout = setTimeout(() => this.checkHealth(), this.#healthCheckInterval);\r\n }\r\n\r\n private resetState() {\r\n this.#currentPeriodProgressHistory = [];\r\n this.#lastProgressEventFromPreviousPeriod = undefined;\r\n this.#timeout = undefined;\r\n this.#isCurrentlyHealthy = true;\r\n }\r\n\r\n stop() {\r\n clearTimeout(this.#timeout);\r\n\r\n this.#timeout = undefined;\r\n\r\n this.unsubscribeFromTransferRunningEvents();\r\n }\r\n\r\n private subscribeToTransferRunningEvents() {\r\n this.#transferEventsEngine.addEventListener(TransferUploadEvent.TransferMetadataDetermined, this.transferMetadataDetermined);\r\n this.#transferEventsEngine.addEventListener(TransferUploadEvent.TransferProgressed, this.transferProgressed);\r\n }\r\n\r\n private unsubscribeFromTransferRunningEvents() {\r\n this.#transferEventsEngine.removeEventListener(TransferUploadEvent.TransferMetadataDetermined, this.transferMetadataDetermined);\r\n this.#transferEventsEngine.removeEventListener(TransferUploadEvent.TransferProgressed, this.transferProgressed);\r\n }\r\n\r\n private transferMetadataDetermined = (eventArgs: TransferMetadataDeterminedEventArgs) => {\r\n this.#fileServerUrl = eventArgs.fileServerUrl;\r\n };\r\n\r\n private transferProgressed = (eventArgs: TransferUploadProgressedEventArgs) => {\r\n this.#currentPeriodProgressHistory.push({ time: Date.now(), eventArgs });\r\n\r\n if (this.#isCurrentlyHealthy)\r\n return;\r\n\r\n const isHealthy = this.determineIsHealthy(eventArgs);\r\n\r\n if (!isHealthy)\r\n return;\r\n\r\n this.notifyHealthy();\r\n this.restartHealthCheck(eventArgs);\r\n };\r\n\r\n private restartHealthCheck(currentProgressEvent: TransferUploadProgressedEventArgs) {\r\n this.#currentPeriodProgressHistory = [];\r\n this.#lastProgressEventFromPreviousPeriod = currentProgressEvent;\r\n\r\n this.#isCurrentlyHealthy = true;\r\n\r\n clearTimeout(this.#timeout);\r\n this.#timeout = setTimeout(() => this.checkHealth(), this.#healthCheckInterval);\r\n }\r\n\r\n private checkHealth = async (): Promise<void> => {\r\n const currentPeriodLastProgressEvent = this.#currentPeriodProgressHistory.at(-1)?.eventArgs;\r\n\r\n const isHealthy = this.determineIsHealthy(currentPeriodLastProgressEvent);\r\n\r\n this.#lastProgressEventFromPreviousPeriod = currentPeriodLastProgressEvent || this.#lastProgressEventFromPreviousPeriod;\r\n\r\n if (isHealthy) {\r\n this.#isCurrentlyHealthy = true;\r\n this.notifyHealthy();\r\n }\r\n else {\r\n this.#isCurrentlyHealthy = false;\r\n await this.figureOutUnhealthyReasonWithNotifications();\r\n }\r\n\r\n this.clearCurrentPeriodProgressHistory();\r\n\r\n this.#timeout = setTimeout(() => this.checkHealth(), this.#healthCheckInterval);\r\n };\r\n\r\n private clearCurrentPeriodProgressHistory() {\r\n this.#currentPeriodProgressHistory = [];\r\n }\r\n\r\n private determineIsHealthy(currentHistoryLastProgressEvent: TransferUploadProgressedEventArgs | undefined) {\r\n const currentUploadedBytesTotalCount = currentHistoryLastProgressEvent?.uploadedBytesTotalCount ?? 0;\r\n const previousPeriodUploadedBytesTotalCount = this.#lastProgressEventFromPreviousPeriod?.uploadedBytesTotalCount ?? 0;\r\n\r\n const bytesSentThisPeriod = currentUploadedBytesTotalCount - previousPeriodUploadedBytesTotalCount;\r\n\r\n return bytesSentThisPeriod > 0;\r\n }\r\n\r\n private async figureOutUnhealthyReasonWithNotifications(): Promise<void> {\r\n this.notifyStartedCheckingUnhealthyReason();\r\n\r\n const { isOnline: isInternetOnline, error: internetOnlineError } = await this.#onlineChecker.isInternetOnline();\r\n\r\n if (isInternetOnline)\r\n this.notifyUnhealthyInternetOkRestCheckingReason();\r\n else {\r\n this.notifyUnhealthyNoInternetReason(internetOnlineError);\r\n return;\r\n }\r\n\r\n const isApiOnlinePromise = this.#onlineChecker.isApiReachable();\r\n\r\n const isFileServerOnlinePromise = this.#fileServerUrl\r\n ? this.#onlineChecker.isFileServerReachable(this.#fileServerUrl)\r\n : Promise.resolve(undefined);\r\n\r\n const { isOnline: isApiOnline, error: apiOnlineError } = await isApiOnlinePromise;\r\n const isFileServerOnlineResult = await isFileServerOnlinePromise;\r\n\r\n if (isApiOnline && isFileServerOnlineResult?.isOnline === true)\r\n this.notifyUnhealthyAllOkReason();\r\n else {\r\n const fileServerStatus = this.isOnlineResultToStatus(isFileServerOnlineResult);\r\n\r\n this.notifyUnhealthyApiOrFileServerErrorReason(fileServerStatus, isFileServerOnlineResult?.error, apiOnlineError);\r\n }\r\n }\r\n\r\n private isOnlineResultToStatus(isFileServerOnlineResult: OnlineCheckerResult | undefined): `Ok` | `Error` | `Unknown` {\r\n if (!isFileServerOnlineResult)\r\n return `Unknown`;\r\n\r\n return isFileServerOnlineResult.isOnline ? `Ok` : `Error`;\r\n }\r\n\r\n private notifyHealthy() {\r\n const eventArgs: UploadHealthMonitorHealthyEventArgs = {\r\n ...this.#lastProgressEventFromPreviousPeriod,\r\n };\r\n\r\n this.#transferEventsEngine.emit(TransferUploadHealthMonitorEvent.Healthy, eventArgs);\r\n }\r\n\r\n private notifyStartedCheckingUnhealthyReason() {\r\n const eventArgs: UploadHealthMonitorUnhealthyEventArgs = {\r\n reason: {\r\n internet: { status: `Checking` },\r\n api: { status: `Checking` },\r\n fileServer: { status: `Checking` },\r\n },\r\n ...this.#lastProgressEventFromPreviousPeriod,\r\n };\r\n\r\n this.#transferEventsEngine.emit(TransferUploadHealthMonitorEvent.Unhealthy, eventArgs);\r\n }\r\n\r\n private notifyUnhealthyInternetOkRestCheckingReason() {\r\n const eventArgs: UploadHealthMonitorUnhealthyEventArgs = {\r\n reason: {\r\n internet: { status: `Ok` },\r\n api: { status: `Checking` },\r\n fileServer: { status: `Checking` },\r\n },\r\n ...this.#lastProgressEventFromPreviousPeriod,\r\n };\r\n\r\n this.#transferEventsEngine.emit(TransferUploadHealthMonitorEvent.Unhealthy, eventArgs);\r\n }\r\n\r\n private notifyUnhealthyNoInternetReason(error?: Error) {\r\n const eventArgs: UploadHealthMonitorUnhealthyEventArgs = {\r\n reason: {\r\n internet: { status: `Error`, error },\r\n api: { status: `Unknown` },\r\n fileServer: { status: `Unknown` },\r\n },\r\n ...this.#lastProgressEventFromPreviousPeriod,\r\n };\r\n\r\n this.#transferEventsEngine.emit(TransferUploadHealthMonitorEvent.Unhealthy, eventArgs);\r\n }\r\n\r\n private notifyUnhealthyApiOrFileServerErrorReason(fileServerStatus: `Ok` | `Error` | `Unknown`, fileServerError: Error | undefined, apiError: Error | undefined) {\r\n const eventArgs: UploadHealthMonitorUnhealthyEventArgs = {\r\n reason: {\r\n internet: { status: `Ok` },\r\n api: apiError ? { status: `Error`, error: apiError } : { status: `Ok` },\r\n fileServer: fileServerError ? { status: `Error`, error: fileServerError } : { status: fileServerStatus },\r\n },\r\n ...this.#lastProgressEventFromPreviousPeriod,\r\n };\r\n\r\n this.#transferEventsEngine.emit(TransferUploadHealthMonitorEvent.Unhealthy, eventArgs);\r\n }\r\n\r\n private notifyUnhealthyAllOkReason() {\r\n const eventArgs: UploadHealthMonitorUnhealthyEventArgs = {\r\n reason: {\r\n internet: { status: `Ok` },\r\n api: { status: `Ok` },\r\n fileServer: { status: `Ok` },\r\n },\r\n ...this.#lastProgressEventFromPreviousPeriod,\r\n };\r\n\r\n this.#transferEventsEngine.emit(TransferUploadHealthMonitorEvent.Unhealthy, eventArgs);\r\n }\r\n\r\n addEventListener(eventName: TransferUploadHealthMonitorEvent.Healthy, handler: (event: UploadHealthMonitorHealthyEventArgs) => void): void\r\n addEventListener(eventName: TransferUploadHealthMonitorEvent.Unhealthy, handler: (event: UploadHealthMonitorUnhealthyEventArgs) => void): void\r\n addEventListener(eventName: string, handler: (arg?: any) => void): void {\r\n this.#transferEventsEngine.addEventListener(eventName, handler);\r\n }\r\n}"]}
|