filemail-sdk 9.0.8 → 9.1.1

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.
@@ -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, healthCheckIntervalWhenHealthy?: number, healthCheckIntervalWhenUnhealthy?: number);
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;;gBAehC,aAAa,EAAE,aAAa,EAAE,oBAAoB,EAAE,YAAY,EAAE,8BAA8B,SAAS,EAAE,gCAAgC,SAAQ;IAa/J,KAAK;IAQL,OAAO,CAAC,UAAU;IAIlB,IAAI;IAMJ,OAAO,CAAC,gCAAgC;IAKxC,OAAO,CAAC,oCAAoC;IAK5C,OAAO,CAAC,0BAA0B,CAEhC;IAEF,OAAO,CAAC,kBAAkB,CAExB;IAEF,OAAO,CAAC,WAAW,CAiBjB;IAEF,OAAO,CAAC,kBAAkB;YAIZ,yCAAyC;IA8BvD,OAAO,CAAC,sBAAsB;IAO9B,OAAO,CAAC,sBAAsB;IAI9B,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"}
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
- #healthCheckIntervalWhenHealthy;
7
- #healthCheckIntervalWhenUnhealthy;
6
+ #healthCheckInterval;
8
7
  #timeout;
9
8
  #fileServerUrl;
10
- #progressHistory = [];
11
- #lastProgressEvent;
12
- constructor(onlineChecker, transferEventsEngine, healthCheckIntervalWhenHealthy = 15_000, healthCheckIntervalWhenUnhealthy = 5_000) {
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.#healthCheckIntervalWhenHealthy = healthCheckIntervalWhenHealthy;
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.#healthCheckIntervalWhenHealthy);
26
+ this.#timeout = setTimeout(() => this.checkHealth(), this.#healthCheckInterval);
26
27
  }
27
28
  resetState() {
28
- this.#progressHistory = [];
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.#progressHistory.push({ time: Date.now(), eventArgs });
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 currentHistoryLastProgressEvent = this.#progressHistory.at(-1)?.eventArgs;
50
- this.#lastProgressEvent = currentHistoryLastProgressEvent || this.#lastProgressEvent;
51
- const isHealthy = this.determineIsHealthy(currentHistoryLastProgressEvent);
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
- else
74
+ }
75
+ else {
76
+ this.#isCurrentlyHealthy = false;
55
77
  await this.figureOutUnhealthyReasonWithNotifications();
56
- this.resetState();
57
- const nextHealthCheck = this.getHealthCheckInterval(isHealthy);
58
- this.#timeout = setTimeout(() => this.checkHealth(), nextHealthCheck);
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
- return currentHistoryLastProgressEvent !== undefined && currentHistoryLastProgressEvent.currentSpeedInBytesPerSecond > 0;
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.#lastProgressEvent,
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.#lastProgressEvent,
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.#lastProgressEvent,
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.#lastProgressEvent,
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.#lastProgressEvent,
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.#lastProgressEvent,
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}"]}
@@ -18,7 +18,11 @@ export default abstract class TransferUploaderBase<T extends NodeFileDetails | W
18
18
  start(): Promise<void>;
19
19
  private setFailedReasonFromError;
20
20
  private tryGetApiFilemailError;
21
+ private addHealthMonitorEventListeners;
21
22
  private addTransferEventListeners;
23
+ private logHealthyStatus;
24
+ private makeEventSerializable;
25
+ private makeReasonValueSerializable;
22
26
  private logTrace;
23
27
  private logDebug;
24
28
  private logInfo;
@@ -1 +1 @@
1
- {"version":3,"file":"transferUploaderBase.d.ts","sourceRoot":"","sources":["../../../../src/client/uploader/transferUploaderBase.ts"],"names":[],"mappings":"AAGA,OAAO,cAAc,MAAM,kCAAkC,CAAC;AAS9D,OAAO,KAAK,eAAe,MAAM,gDAAgD,CAAC;AAClF,OAAO,KAAK,MAAM,MAAM,sBAAsB,CAAC;AAC/C,OAAO,KAAK,oBAAoB,MAAM,4BAA4B,CAAC;AACnE,OAAO,KAAK,gBAAgB,MAAM,uBAAuB,CAAC;AAE1D,OAAO,KAAK,sBAAsB,MAAM,6BAA6B,CAAC;AACtE,OAAO,KAAK,cAAc,MAAM,8CAA8C,CAAC;AAC/E,OAAO,2BAA2B,MAAM,gDAAgD,CAAC;AAIzF,MAAM,CAAC,OAAO,CAAC,QAAQ,OAAO,oBAAoB,CAAC,CAAC,SAAS,eAAe,GAAG,cAAc,CAAE,YAAW,gBAAgB,CAAC,CAAC,CAAC;;gBAqB7G,QAAQ,EAAE,cAAc,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,sBAAsB,EAAE,SAAS,EAAE,oBAAoB,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,EAAE,2BAA2B,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM;IAcnN,IAAI,QAAQ,IAAI,cAAc,CAAC,CAAC,CAAC,CAEhC;IAED,IAAI,aAAa,IAAI,2BAA2B,CAE/C;IAED,IAAI,YAAY,IAAI,MAAM,GAAG,SAAS,CAErC;IAEM,KAAK;IAWL,IAAI;IAWE,MAAM,CAAC,WAAW,CAAC,EAAE,WAAW;IAMvC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IA8C5B,OAAO,CAAC,wBAAwB;IAgBhC,OAAO,CAAC,sBAAsB;IAU9B,OAAO,CAAC,yBAAyB;IA4DjC,OAAO,CAAC,QAAQ;IAKhB,OAAO,CAAC,QAAQ;IAKhB,OAAO,CAAC,OAAO;IAKf,OAAO,CAAC,UAAU;IAKlB,OAAO,CAAC,QAAQ;IAKhB,OAAO,CAAC,mBAAmB;IAO3B,OAAO,CAAC,yBAAyB;IAYjC,OAAO,CAAC,iBAAiB;CAG5B"}
1
+ {"version":3,"file":"transferUploaderBase.d.ts","sourceRoot":"","sources":["../../../../src/client/uploader/transferUploaderBase.ts"],"names":[],"mappings":"AAIA,OAAO,cAAc,MAAM,kCAAkC,CAAC;AAS9D,OAAO,KAAK,eAAe,MAAM,gDAAgD,CAAC;AAClF,OAAO,KAAK,MAAM,MAAM,sBAAsB,CAAC;AAC/C,OAAO,KAAK,oBAAoB,MAAM,4BAA4B,CAAC;AACnE,OAAO,KAAK,gBAAgB,MAAM,uBAAuB,CAAC;AAE1D,OAAO,KAAK,sBAAsB,MAAM,6BAA6B,CAAC;AACtE,OAAO,KAAK,cAAc,MAAM,8CAA8C,CAAC;AAC/E,OAAO,2BAA2B,MAAM,gDAAgD,CAAC;AAOzF,MAAM,CAAC,OAAO,CAAC,QAAQ,OAAO,oBAAoB,CAAC,CAAC,SAAS,eAAe,GAAG,cAAc,CAAE,YAAW,gBAAgB,CAAC,CAAC,CAAC;;gBAwB7G,QAAQ,EAAE,cAAc,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,sBAAsB,EAAE,SAAS,EAAE,oBAAoB,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,EAAE,2BAA2B,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM;IAiBnN,IAAI,QAAQ,IAAI,cAAc,CAAC,CAAC,CAAC,CAEhC;IAED,IAAI,aAAa,IAAI,2BAA2B,CAE/C;IAED,IAAI,YAAY,IAAI,MAAM,GAAG,SAAS,CAErC;IAEM,KAAK;IAWL,IAAI;IAWE,MAAM,CAAC,WAAW,CAAC,EAAE,WAAW;IAMvC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IA+C5B,OAAO,CAAC,wBAAwB;IAgBhC,OAAO,CAAC,sBAAsB;IAU9B,OAAO,CAAC,8BAA8B;IAuBtC,OAAO,CAAC,yBAAyB;IA4DjC,OAAO,CAAC,gBAAgB;IAQxB,OAAO,CAAC,qBAAqB;IAiB7B,OAAO,CAAC,2BAA2B;IAUnC,OAAO,CAAC,QAAQ;IAKhB,OAAO,CAAC,QAAQ;IAKhB,OAAO,CAAC,OAAO;IAKf,OAAO,CAAC,UAAU;IAKlB,OAAO,CAAC,QAAQ;IAKhB,OAAO,CAAC,mBAAmB;IAO3B,OAAO,CAAC,yBAAyB;IAYjC,OAAO,CAAC,iBAAiB;CAG5B"}
@@ -1,5 +1,6 @@
1
1
  /* eslint-disable @typescript-eslint/ban-ts-comment */
2
2
  import sleep from "abortable-sleep";
3
+ import throttle from "lodash.throttle";
3
4
  import PauseController from "../../uploader/pauseController.js";
4
5
  import TransferStatus from "../../utils/types/transferStatus.js";
5
6
  import TransferUploadEvent from "../../uploader/transferUploadEvent.js";
@@ -7,6 +8,7 @@ import FsError from "../../utils/fileSystem/fsError.js";
7
8
  import TransferUploadError from "../../uploader/transferUploadError.js";
8
9
  import logEventPropertyName from "../../utils/logging/logEventPropertyNames.js";
9
10
  import ApiFilemailError from "../../utils/api/apiFilemailError.js";
11
+ import TransferUploadHealthMonitorEvent from "./healthMonitor/events/transferUploadHealthMonitorEvent.js";
10
12
  const TransferFailedSleepInMs = 500;
11
13
  export default class TransferUploaderBase {
12
14
  #logger;
@@ -21,6 +23,8 @@ export default class TransferUploaderBase {
21
23
  #isShuttingDown = false;
22
24
  #failedReason;
23
25
  #isUdp;
26
+ #isHealthy = true;
27
+ #logHealthyStatusThrottled;
24
28
  constructor(transfer, fileDetails, config, envValues, logger, healthMonitor, trackingId) {
25
29
  this.#logger = logger;
26
30
  this.#trackingId = trackingId;
@@ -29,6 +33,8 @@ export default class TransferUploaderBase {
29
33
  this.#fileDetails = fileDetails;
30
34
  this.#transfer = transfer;
31
35
  this.#healthMonitor = healthMonitor;
36
+ this.#logHealthyStatusThrottled = throttle(this.logHealthyStatus, 20_000);
37
+ this.addHealthMonitorEventListeners();
32
38
  this.addTransferEventListeners();
33
39
  }
34
40
  get transfer() {
@@ -89,6 +95,7 @@ export default class TransferUploaderBase {
89
95
  }
90
96
  } while (this.#transfer.progressInPercentage < 100 && !this.#isShuttingDown);
91
97
  this.#healthMonitor.stop();
98
+ this.#logHealthyStatusThrottled.cancel();
92
99
  this.logInfo(`Upload finished in status ${TransferStatus[this.#transfer.status]} having ${this.#transfer.progressInPercentage}% completed`);
93
100
  }
94
101
  setFailedReasonFromError(error) {
@@ -110,6 +117,22 @@ export default class TransferUploaderBase {
110
117
  return this.tryGetApiFilemailError(error.cause);
111
118
  return null;
112
119
  }
120
+ addHealthMonitorEventListeners() {
121
+ this.#healthMonitor.addEventListener(TransferUploadHealthMonitorEvent.Healthy, eventArgs => {
122
+ this.#logHealthyStatusThrottled(true, eventArgs);
123
+ if (!this.#isHealthy)
124
+ this.logHealthyStatus(true, eventArgs);
125
+ this.#isHealthy = true;
126
+ });
127
+ this.#healthMonitor.addEventListener(TransferUploadHealthMonitorEvent.Unhealthy, eventArgs => {
128
+ if (eventArgs.reason.api.status === `Checking` || eventArgs.reason.fileServer.status === `Checking` || eventArgs.reason.internet.status === `Checking`)
129
+ return;
130
+ this.#logHealthyStatusThrottled(false, eventArgs);
131
+ if (this.#isHealthy)
132
+ this.logHealthyStatus(false, eventArgs);
133
+ this.#isHealthy = false;
134
+ });
135
+ }
113
136
  addTransferEventListeners() {
114
137
  this.#transfer.addEventListener(TransferUploadEvent.TransferUploadModeChosen, eventArgs => {
115
138
  this.#isUdp = eventArgs.isUdpMode;
@@ -157,6 +180,34 @@ export default class TransferUploaderBase {
157
180
  this.#transfer.addEventListener(TransferUploadEvent.FileChunkUploadCompleted, eventArgs => this.logTrace(`File ${eventArgs.fileStatus.fileName} having external id = ${eventArgs.fileStatus.externalId}, chunk starting at ${eventArgs.chunkStartPosition} having size ${eventArgs.chunkSizeInBytes} - upload completed`));
158
181
  this.#transfer.addEventListener(TransferUploadEvent.FileChunkUploadCompletedPartially, eventArgs => this.logWarning(`File ${eventArgs.fileStatus.fileName} having external id = ${eventArgs.fileStatus.externalId}, chunk starting at ${eventArgs.chunkStartPosition} having size ${eventArgs.chunkSizeInBytes} - uploaded partially - only ${eventArgs.uploadedBytesCount} bytes uploaded`));
159
182
  }
183
+ logHealthyStatus(isHealthy, event) {
184
+ const logEntryMetadata = this.getLogEntryMetadata();
185
+ const serializableEvent = this.makeEventSerializable(isHealthy, event);
186
+ this.#logger.logInfo(`Transfer health status`, { isHealthy, event: serializableEvent, ...logEntryMetadata });
187
+ }
188
+ makeEventSerializable(isHealthy, event) {
189
+ if (isHealthy)
190
+ return event;
191
+ const unhealthyEvent = event;
192
+ return {
193
+ ...unhealthyEvent,
194
+ reason: {
195
+ ...unhealthyEvent.reason,
196
+ internet: this.makeReasonValueSerializable(unhealthyEvent.reason.internet),
197
+ api: this.makeReasonValueSerializable(unhealthyEvent.reason.api),
198
+ fileServer: this.makeReasonValueSerializable(unhealthyEvent.reason.fileServer),
199
+ },
200
+ };
201
+ }
202
+ makeReasonValueSerializable(value) {
203
+ return {
204
+ ...value,
205
+ error: value.error === undefined ? undefined : {
206
+ name: value.error.name,
207
+ message: value.error.message,
208
+ },
209
+ };
210
+ }
160
211
  logTrace(message) {
161
212
  const logEntryMetadata = this.getLogEntryMetadata();
162
213
  this.#logger.logTrace(message, logEntryMetadata);
@@ -1 +1 @@
1
- {"version":3,"file":"transferUploaderBase.js","sourceRoot":"","sources":["../../../../src/client/uploader/transferUploaderBase.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable @typescript-eslint/ban-ts-comment */\r\nimport sleep from \"abortable-sleep\";\r\n\r\nimport TransferUpload from \"../../uploader/transferUpload.js\";\r\nimport PauseController from \"../../uploader/pauseController.js\";\r\nimport TransferStatus from \"../../utils/types/transferStatus.js\";\r\nimport TransferUploadEvent from \"../../uploader/transferUploadEvent.js\";\r\nimport FsError from \"../../utils/fileSystem/fsError.js\";\r\nimport TransferUploadError from \"../../uploader/transferUploadError.js\";\r\nimport logEventPropertyName from \"../../utils/logging/logEventPropertyNames.js\";\r\nimport ApiFilemailError from \"../../utils/api/apiFilemailError.js\";\r\n\r\nimport type NodeFileDetails from \"../../utils/fileSystem/node/nodeFileDetails.js\";\r\nimport type Logger from \"../loggers/logger.js\";\r\nimport type EnvironmentVariables from \"../environmentVariables.js\";\r\nimport type TransferUploader from \"./transferUploader.js\";\r\nimport type ReadonlyTransferUploadStateFile from \"../../uploader/state/readonlyTransferUploadStateFile.js\";\r\nimport type TransferUploaderConfig from \"./transferUploaderConfig.js\";\r\nimport type WebFileDetails from \"../../utils/fileSystem/web/webFileDetails.js\";\r\nimport TransferUploadHealthMonitor from \"./healthMonitor/transferUploadHealthMonitor.js\";\r\n\r\nconst TransferFailedSleepInMs = 500;\r\n\r\nexport default abstract class TransferUploaderBase<T extends NodeFileDetails | WebFileDetails> implements TransferUploader<T> {\r\n #logger: Logger;\r\n #trackingId: number | string;\r\n\r\n #fileDetails: T[];\r\n\r\n #config: TransferUploaderConfig;\r\n #envValues: EnvironmentVariables;\r\n\r\n #pauseController?: PauseController;\r\n #abortController?: AbortController;\r\n\r\n #transfer: TransferUpload<T>;\r\n #healthMonitor: TransferUploadHealthMonitor;\r\n\r\n #isShuttingDown = false;\r\n\r\n #failedReason?: string;\r\n\r\n #isUdp?: boolean;\r\n\r\n constructor(transfer: TransferUpload<T>, fileDetails: T[], config: TransferUploaderConfig, envValues: EnvironmentVariables, logger: Logger, healthMonitor: TransferUploadHealthMonitor, trackingId: number | string) {\r\n this.#logger = logger;\r\n this.#trackingId = trackingId;\r\n\r\n this.#config = config;\r\n this.#envValues = envValues;\r\n\r\n this.#fileDetails = fileDetails;\r\n this.#transfer = transfer;\r\n this.#healthMonitor = healthMonitor;\r\n\r\n this.addTransferEventListeners();\r\n }\r\n\r\n get transfer(): TransferUpload<T> {\r\n return this.#transfer;\r\n }\r\n\r\n get healthMonitor(): TransferUploadHealthMonitor {\r\n return this.#healthMonitor;\r\n }\r\n\r\n get failedReason(): string | undefined {\r\n return this.#failedReason;\r\n }\r\n\r\n public pause() {\r\n this.logInfo(`Pause called`);\r\n\r\n if (!this.#pauseController)\r\n throw new TransferUploadError(`Can't pause not started transfer`);\r\n\r\n this.#isShuttingDown = true;\r\n\r\n this.#pauseController.pause();\r\n }\r\n\r\n public stop() {\r\n this.logInfo(`Stop called`);\r\n\r\n if (!this.#abortController)\r\n throw new TransferUploadError(`Can't stop not started transfer`);\r\n\r\n this.#isShuttingDown = true;\r\n\r\n this.#abortController.abort();\r\n }\r\n\r\n public async cancel(abortSignal?: AbortSignal) {\r\n this.logInfo(`Cancel called`);\r\n\r\n await this.#transfer.cancel(abortSignal);\r\n }\r\n\r\n async start(): Promise<void> {\r\n if (this.#transfer.status !== TransferStatus.Failed && this.#transfer.status !== TransferStatus.Aborted && this.#transfer.status !== TransferStatus.Initialized && this.#transfer.status !== TransferStatus.Paused)\r\n throw new TransferUploadError(`Transfer is in ${TransferStatus[this.#transfer.status]} state and cannot be run`);\r\n\r\n this.logInfo(`Starting upload. Already uploaded bytes: ${this.transfer.uploadedBytesCount}/${this.#transfer.totalSizeInBytes}B, completed files: ${this.transfer.completedFilesCount}.`);\r\n\r\n const logMessageEntries = this.#transfer.files.map(f => `'Sending ${f.fileName}' with id = ${f.externalId}. It will be put into '${f.fileDestinationPathInTransfer}' folder.`);\r\n this.logInfo(`Transfer file details:\\n${logMessageEntries.join(`\\n`)}`);\r\n\r\n this.#failedReason = undefined;\r\n this.#isShuttingDown = false;\r\n\r\n this.#pauseController = new PauseController();\r\n this.#abortController = new AbortController();\r\n\r\n this.#healthMonitor.start();\r\n\r\n do {\r\n /* eslint-disable no-await-in-loop */\r\n try {\r\n await this.#transfer.run(this.#pauseController.signal, this.#abortController.signal);\r\n }\r\n catch (error) {\r\n this.logError(error as TransferUploadError, `Transfer upload run method exception`);\r\n\r\n this.setFailedReasonFromError(error as TransferUploadError);\r\n this.#isShuttingDown = true;\r\n\r\n break;\r\n }\r\n finally {\r\n // @ts-ignore Typescript's brainfart\r\n if (this.#transfer.status !== TransferStatus.Completed && !this.#isShuttingDown) {\r\n this.logWarning(`Retrying transfer in ${TransferFailedSleepInMs}ms.`);\r\n\r\n await sleep(TransferFailedSleepInMs);\r\n }\r\n }\r\n }\r\n while (this.#transfer.progressInPercentage < 100 && !this.#isShuttingDown);\r\n\r\n this.#healthMonitor.stop();\r\n\r\n this.logInfo(`Upload finished in status ${TransferStatus[this.#transfer.status]} having ${this.#transfer.progressInPercentage}% completed`);\r\n }\r\n\r\n private setFailedReasonFromError(error: TransferUploadError) {\r\n const apiFilemailError = this.tryGetApiFilemailError(error);\r\n\r\n if (apiFilemailError) {\r\n this.#failedReason = apiFilemailError.reason;\r\n return;\r\n }\r\n\r\n if (error.message.startsWith(`Unhandled error occured`) && error.cause) {\r\n this.#failedReason = error.cause.message;\r\n return;\r\n }\r\n\r\n this.#failedReason = error.message;\r\n }\r\n\r\n private tryGetApiFilemailError(error: Error): ApiFilemailError | null {\r\n if (error instanceof ApiFilemailError)\r\n return error;\r\n\r\n if (error.cause)\r\n return this.tryGetApiFilemailError(error.cause);\r\n\r\n return null;\r\n }\r\n\r\n private addTransferEventListeners() {\r\n this.#transfer.addEventListener(TransferUploadEvent.TransferUploadModeChosen, eventArgs => {\r\n this.#isUdp = eventArgs.isUdpMode;\r\n });\r\n\r\n this.#transfer.addEventListener(TransferUploadEvent.FileChunkUploadFailed, eventArgs => {\r\n const isTimeoutError = eventArgs.error.message.includes(`Timeout`);\r\n const errorMessage = `File ${eventArgs.fileStatus.externalId} chunk starting at ${eventArgs.chunkStartPosition} having size ${eventArgs.chunkSizeInBytes} upload failed: ${eventArgs.reason}`;\r\n\r\n if (this.#isUdp && isTimeoutError)\r\n this.logDebug(errorMessage);\r\n else\r\n this.logError(eventArgs.error, errorMessage);\r\n\r\n const isFileAccessError = eventArgs.error.cause instanceof FsError;\r\n const fullFilePathOrName = this.getFullFilePathOrFileName(eventArgs.fileStatus);\r\n\r\n if (isFileAccessError && !this.#isShuttingDown) {\r\n this.#failedReason = `Can't read ${fullFilePathOrName} anymore`;\r\n\r\n this.logWarning(`${this.#failedReason}. Aborting...`);\r\n this.stop();\r\n }\r\n\r\n if (!this.#config.infiniteRetries && !this.#isShuttingDown) {\r\n this.#failedReason = `Uploading ${fullFilePathOrName} failed after ${this.#config.chunkUploadRetryLimit} retries`;\r\n\r\n this.logWarning(`${this.#failedReason}. Aborting...`);\r\n this.stop();\r\n }\r\n });\r\n\r\n this.#transfer.addEventListener(TransferUploadEvent.FileUploadFailed, eventArgs => {\r\n const isTimeoutError = eventArgs.reason?.includes(`Timeout`);\r\n const errorMessage = `File ${eventArgs.fileStatus.fileName} having external id = ${eventArgs.fileStatus.externalId} - upload failed: ${eventArgs.reason}`;\r\n\r\n if (this.#isUdp && isTimeoutError)\r\n this.logWarning(errorMessage);\r\n else\r\n this.logError(new Error(errorMessage));\r\n });\r\n\r\n this.#transfer.addEventListener(TransferUploadEvent.TransferRun, () => this.logInfo(`Transfer run.`));\r\n this.#transfer.addEventListener(TransferUploadEvent.TransferAbortRequested, () => this.logInfo(`Transfer abort requested`));\r\n this.#transfer.addEventListener(TransferUploadEvent.TransferAborted, async () => this.logInfo(`Transfer aborted.`));\r\n this.#transfer.addEventListener(TransferUploadEvent.TransferCancelRequested, () => this.logInfo(`Transfer cancel requested.`));\r\n this.#transfer.addEventListener(TransferUploadEvent.TransferCanceled, () => this.logInfo(`Transfer canceled.`));\r\n this.#transfer.addEventListener(TransferUploadEvent.TransferFailed, () => this.logError(new Error(`Transfer failed.`)));\r\n this.#transfer.addEventListener(TransferUploadEvent.TransferUploadModeChosen, eventArgs => this.logInfo(`Transfer upload mode chosen. Is UDP: ${eventArgs.isUdpMode}; Latency: ${eventArgs.latency ?? `<unkown>`}; Error: ${eventArgs.error ?? `<none>`}`));\r\n\r\n this.#transfer.addEventListener(TransferUploadEvent.TransferCompleted, eventArgs => this.logInfo(`Transfer completed successfully. ID: ${eventArgs.transferId}, URL: ${eventArgs.transferDownloadUrl}`));\r\n this.#transfer.addEventListener(TransferUploadEvent.FileChunkUploadProgressed, eventArgs => this.logTrace(`File ${eventArgs.fileStatus.fileName} having external id = ${eventArgs.fileStatus.externalId}, chunk starting at ${eventArgs.chunkStartPosition} having size ${eventArgs.chunkSizeInBytes} progressed: ${eventArgs.transferredBytesSinceLastEvent} bytes sinc last event. Total progress: ${this.#transfer?.progressInPercentage}%.`));\r\n\r\n this.#transfer.addEventListener(TransferUploadEvent.FileUploadStarted, eventArgs => this.logDebug(`File ${eventArgs.fileStatus.fileName} having external id = ${eventArgs.fileStatus.externalId} - upload started.`));\r\n this.#transfer.addEventListener(TransferUploadEvent.FileUploadCompleted, eventArgs => this.logDebug(`File ${eventArgs.fileStatus.fileName} having external id = ${eventArgs.fileStatus.externalId} - upload completed.`));\r\n this.#transfer.addEventListener(TransferUploadEvent.FileChunkUploadStarted, eventArgs => this.logTrace(`File ${eventArgs.fileStatus.fileName} having external id = ${eventArgs.fileStatus.externalId}, chunk starting at ${eventArgs.chunkStartPosition} having size ${eventArgs.chunkSizeInBytes} - upload started`));\r\n this.#transfer.addEventListener(TransferUploadEvent.FileChunkUploadCompleted, eventArgs => this.logTrace(`File ${eventArgs.fileStatus.fileName} having external id = ${eventArgs.fileStatus.externalId}, chunk starting at ${eventArgs.chunkStartPosition} having size ${eventArgs.chunkSizeInBytes} - upload completed`));\r\n this.#transfer.addEventListener(TransferUploadEvent.FileChunkUploadCompletedPartially, eventArgs => this.logWarning(`File ${eventArgs.fileStatus.fileName} having external id = ${eventArgs.fileStatus.externalId}, chunk starting at ${eventArgs.chunkStartPosition} having size ${eventArgs.chunkSizeInBytes} - uploaded partially - only ${eventArgs.uploadedBytesCount} bytes uploaded`));\r\n }\r\n\r\n private logTrace(message: string) {\r\n const logEntryMetadata = this.getLogEntryMetadata();\r\n this.#logger.logTrace(message, logEntryMetadata);\r\n }\r\n\r\n private logDebug(message: string) {\r\n const logEntryMetadata = this.getLogEntryMetadata();\r\n this.#logger.logDebug(message, logEntryMetadata);\r\n }\r\n\r\n private logInfo(message: string) {\r\n const logEntryMetadata = this.getLogEntryMetadata();\r\n this.#logger.logInfo(message, logEntryMetadata);\r\n }\r\n\r\n private logWarning(message: string) {\r\n const logEntryMetadata = this.getLogEntryMetadata();\r\n this.#logger.logWarning(message, logEntryMetadata);\r\n }\r\n\r\n private logError(error: Error, message?: string) {\r\n const logEntryMetadata = this.getLogEntryMetadata();\r\n this.#logger.logError(error, message, logEntryMetadata);\r\n }\r\n\r\n private getLogEntryMetadata() {\r\n return {\r\n [logEventPropertyName.TrackingIdPropertyName]: this.#trackingId,\r\n [logEventPropertyName.TransferIdPropertyName]: this.#transfer.transferId,\r\n };\r\n }\r\n\r\n private getFullFilePathOrFileName(fileStatus: ReadonlyTransferUploadStateFile): string {\r\n const fileDetails = this.#fileDetails.find(f => f.externalId === fileStatus.externalId);\r\n\r\n if (!fileDetails)\r\n return fileStatus.fileName;\r\n\r\n if (this.isNodeFileDetails(fileDetails))\r\n return fileDetails.fileFullPath;\r\n\r\n return fileDetails.file.name;\r\n }\r\n\r\n private isNodeFileDetails(fileDetails: NodeFileDetails | WebFileDetails): fileDetails is NodeFileDetails {\r\n return typeof (fileDetails as NodeFileDetails).fileFullPath === `string`;\r\n }\r\n}"]}
1
+ {"version":3,"file":"transferUploaderBase.js","sourceRoot":"","sources":["../../../../src/client/uploader/transferUploaderBase.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable @typescript-eslint/ban-ts-comment */\r\nimport sleep from \"abortable-sleep\";\r\nimport throttle from \"lodash.throttle\";\r\n\r\nimport TransferUpload from \"../../uploader/transferUpload.js\";\r\nimport PauseController from \"../../uploader/pauseController.js\";\r\nimport TransferStatus from \"../../utils/types/transferStatus.js\";\r\nimport TransferUploadEvent from \"../../uploader/transferUploadEvent.js\";\r\nimport FsError from \"../../utils/fileSystem/fsError.js\";\r\nimport TransferUploadError from \"../../uploader/transferUploadError.js\";\r\nimport logEventPropertyName from \"../../utils/logging/logEventPropertyNames.js\";\r\nimport ApiFilemailError from \"../../utils/api/apiFilemailError.js\";\r\n\r\nimport type NodeFileDetails from \"../../utils/fileSystem/node/nodeFileDetails.js\";\r\nimport type Logger from \"../loggers/logger.js\";\r\nimport type EnvironmentVariables from \"../environmentVariables.js\";\r\nimport type TransferUploader from \"./transferUploader.js\";\r\nimport type ReadonlyTransferUploadStateFile from \"../../uploader/state/readonlyTransferUploadStateFile.js\";\r\nimport type TransferUploaderConfig from \"./transferUploaderConfig.js\";\r\nimport type WebFileDetails from \"../../utils/fileSystem/web/webFileDetails.js\";\r\nimport TransferUploadHealthMonitor from \"./healthMonitor/transferUploadHealthMonitor.js\";\r\nimport TransferUploadHealthMonitorEvent from \"./healthMonitor/events/transferUploadHealthMonitorEvent.js\";\r\nimport UploadHealthMonitorUnhealthyEventArgs, { UploadHealthMonitorUnhealthyEventArgsReasonValue } from \"./healthMonitor/events/eventArgs/uploadHealthMonitorUnhealthyEventArgs.js\";\r\nimport UploadHealthMonitorHealthyEventArgs from \"./healthMonitor/events/eventArgs/uploadHealthMonitorHealthyEventArgs.js\";\r\n\r\nconst TransferFailedSleepInMs = 500;\r\n\r\nexport default abstract class TransferUploaderBase<T extends NodeFileDetails | WebFileDetails> implements TransferUploader<T> {\r\n #logger: Logger;\r\n #trackingId: number | string;\r\n\r\n #fileDetails: T[];\r\n\r\n #config: TransferUploaderConfig;\r\n #envValues: EnvironmentVariables;\r\n\r\n #pauseController?: PauseController;\r\n #abortController?: AbortController;\r\n\r\n #transfer: TransferUpload<T>;\r\n #healthMonitor: TransferUploadHealthMonitor;\r\n\r\n #isShuttingDown = false;\r\n\r\n #failedReason?: string;\r\n\r\n #isUdp?: boolean;\r\n\r\n #isHealthy = true;\r\n #logHealthyStatusThrottled: ReturnType<typeof throttle<TransferUploaderBase<T>[`logHealthyStatus`]>>;\r\n\r\n constructor(transfer: TransferUpload<T>, fileDetails: T[], config: TransferUploaderConfig, envValues: EnvironmentVariables, logger: Logger, healthMonitor: TransferUploadHealthMonitor, trackingId: number | string) {\r\n this.#logger = logger;\r\n this.#trackingId = trackingId;\r\n\r\n this.#config = config;\r\n this.#envValues = envValues;\r\n\r\n this.#fileDetails = fileDetails;\r\n this.#transfer = transfer;\r\n this.#healthMonitor = healthMonitor;\r\n\r\n this.#logHealthyStatusThrottled = throttle(this.logHealthyStatus, 20_000);\r\n\r\n this.addHealthMonitorEventListeners();\r\n this.addTransferEventListeners();\r\n }\r\n\r\n get transfer(): TransferUpload<T> {\r\n return this.#transfer;\r\n }\r\n\r\n get healthMonitor(): TransferUploadHealthMonitor {\r\n return this.#healthMonitor;\r\n }\r\n\r\n get failedReason(): string | undefined {\r\n return this.#failedReason;\r\n }\r\n\r\n public pause() {\r\n this.logInfo(`Pause called`);\r\n\r\n if (!this.#pauseController)\r\n throw new TransferUploadError(`Can't pause not started transfer`);\r\n\r\n this.#isShuttingDown = true;\r\n\r\n this.#pauseController.pause();\r\n }\r\n\r\n public stop() {\r\n this.logInfo(`Stop called`);\r\n\r\n if (!this.#abortController)\r\n throw new TransferUploadError(`Can't stop not started transfer`);\r\n\r\n this.#isShuttingDown = true;\r\n\r\n this.#abortController.abort();\r\n }\r\n\r\n public async cancel(abortSignal?: AbortSignal) {\r\n this.logInfo(`Cancel called`);\r\n\r\n await this.#transfer.cancel(abortSignal);\r\n }\r\n\r\n async start(): Promise<void> {\r\n if (this.#transfer.status !== TransferStatus.Failed && this.#transfer.status !== TransferStatus.Aborted && this.#transfer.status !== TransferStatus.Initialized && this.#transfer.status !== TransferStatus.Paused)\r\n throw new TransferUploadError(`Transfer is in ${TransferStatus[this.#transfer.status]} state and cannot be run`);\r\n\r\n this.logInfo(`Starting upload. Already uploaded bytes: ${this.transfer.uploadedBytesCount}/${this.#transfer.totalSizeInBytes}B, completed files: ${this.transfer.completedFilesCount}.`);\r\n\r\n const logMessageEntries = this.#transfer.files.map(f => `'Sending ${f.fileName}' with id = ${f.externalId}. It will be put into '${f.fileDestinationPathInTransfer}' folder.`);\r\n this.logInfo(`Transfer file details:\\n${logMessageEntries.join(`\\n`)}`);\r\n\r\n this.#failedReason = undefined;\r\n this.#isShuttingDown = false;\r\n\r\n this.#pauseController = new PauseController();\r\n this.#abortController = new AbortController();\r\n\r\n this.#healthMonitor.start();\r\n\r\n do {\r\n /* eslint-disable no-await-in-loop */\r\n try {\r\n await this.#transfer.run(this.#pauseController.signal, this.#abortController.signal);\r\n }\r\n catch (error) {\r\n this.logError(error as TransferUploadError, `Transfer upload run method exception`);\r\n\r\n this.setFailedReasonFromError(error as TransferUploadError);\r\n this.#isShuttingDown = true;\r\n\r\n break;\r\n }\r\n finally {\r\n // @ts-ignore Typescript's brainfart\r\n if (this.#transfer.status !== TransferStatus.Completed && !this.#isShuttingDown) {\r\n this.logWarning(`Retrying transfer in ${TransferFailedSleepInMs}ms.`);\r\n\r\n await sleep(TransferFailedSleepInMs);\r\n }\r\n }\r\n }\r\n while (this.#transfer.progressInPercentage < 100 && !this.#isShuttingDown);\r\n\r\n this.#healthMonitor.stop();\r\n this.#logHealthyStatusThrottled.cancel();\r\n\r\n this.logInfo(`Upload finished in status ${TransferStatus[this.#transfer.status]} having ${this.#transfer.progressInPercentage}% completed`);\r\n }\r\n\r\n private setFailedReasonFromError(error: TransferUploadError) {\r\n const apiFilemailError = this.tryGetApiFilemailError(error);\r\n\r\n if (apiFilemailError) {\r\n this.#failedReason = apiFilemailError.reason;\r\n return;\r\n }\r\n\r\n if (error.message.startsWith(`Unhandled error occured`) && error.cause) {\r\n this.#failedReason = error.cause.message;\r\n return;\r\n }\r\n\r\n this.#failedReason = error.message;\r\n }\r\n\r\n private tryGetApiFilemailError(error: Error): ApiFilemailError | null {\r\n if (error instanceof ApiFilemailError)\r\n return error;\r\n\r\n if (error.cause)\r\n return this.tryGetApiFilemailError(error.cause);\r\n\r\n return null;\r\n }\r\n\r\n private addHealthMonitorEventListeners() {\r\n this.#healthMonitor.addEventListener(TransferUploadHealthMonitorEvent.Healthy, eventArgs => {\r\n this.#logHealthyStatusThrottled(true, eventArgs);\r\n\r\n if (!this.#isHealthy)\r\n this.logHealthyStatus(true, eventArgs);\r\n\r\n this.#isHealthy = true;\r\n });\r\n\r\n this.#healthMonitor.addEventListener(TransferUploadHealthMonitorEvent.Unhealthy, eventArgs => {\r\n if (eventArgs.reason.api.status === `Checking` || eventArgs.reason.fileServer.status === `Checking` || eventArgs.reason.internet.status === `Checking`)\r\n return;\r\n\r\n this.#logHealthyStatusThrottled(false, eventArgs);\r\n\r\n if (this.#isHealthy)\r\n this.logHealthyStatus(false, eventArgs);\r\n\r\n this.#isHealthy = false;\r\n });\r\n }\r\n\r\n private addTransferEventListeners() {\r\n this.#transfer.addEventListener(TransferUploadEvent.TransferUploadModeChosen, eventArgs => {\r\n this.#isUdp = eventArgs.isUdpMode;\r\n });\r\n\r\n this.#transfer.addEventListener(TransferUploadEvent.FileChunkUploadFailed, eventArgs => {\r\n const isTimeoutError = eventArgs.error.message.includes(`Timeout`);\r\n const errorMessage = `File ${eventArgs.fileStatus.externalId} chunk starting at ${eventArgs.chunkStartPosition} having size ${eventArgs.chunkSizeInBytes} upload failed: ${eventArgs.reason}`;\r\n\r\n if (this.#isUdp && isTimeoutError)\r\n this.logDebug(errorMessage);\r\n else\r\n this.logError(eventArgs.error, errorMessage);\r\n\r\n const isFileAccessError = eventArgs.error.cause instanceof FsError;\r\n const fullFilePathOrName = this.getFullFilePathOrFileName(eventArgs.fileStatus);\r\n\r\n if (isFileAccessError && !this.#isShuttingDown) {\r\n this.#failedReason = `Can't read ${fullFilePathOrName} anymore`;\r\n\r\n this.logWarning(`${this.#failedReason}. Aborting...`);\r\n this.stop();\r\n }\r\n\r\n if (!this.#config.infiniteRetries && !this.#isShuttingDown) {\r\n this.#failedReason = `Uploading ${fullFilePathOrName} failed after ${this.#config.chunkUploadRetryLimit} retries`;\r\n\r\n this.logWarning(`${this.#failedReason}. Aborting...`);\r\n this.stop();\r\n }\r\n });\r\n\r\n this.#transfer.addEventListener(TransferUploadEvent.FileUploadFailed, eventArgs => {\r\n const isTimeoutError = eventArgs.reason?.includes(`Timeout`);\r\n const errorMessage = `File ${eventArgs.fileStatus.fileName} having external id = ${eventArgs.fileStatus.externalId} - upload failed: ${eventArgs.reason}`;\r\n\r\n if (this.#isUdp && isTimeoutError)\r\n this.logWarning(errorMessage);\r\n else\r\n this.logError(new Error(errorMessage));\r\n });\r\n\r\n this.#transfer.addEventListener(TransferUploadEvent.TransferRun, () => this.logInfo(`Transfer run.`));\r\n this.#transfer.addEventListener(TransferUploadEvent.TransferAbortRequested, () => this.logInfo(`Transfer abort requested`));\r\n this.#transfer.addEventListener(TransferUploadEvent.TransferAborted, async () => this.logInfo(`Transfer aborted.`));\r\n this.#transfer.addEventListener(TransferUploadEvent.TransferCancelRequested, () => this.logInfo(`Transfer cancel requested.`));\r\n this.#transfer.addEventListener(TransferUploadEvent.TransferCanceled, () => this.logInfo(`Transfer canceled.`));\r\n this.#transfer.addEventListener(TransferUploadEvent.TransferFailed, () => this.logError(new Error(`Transfer failed.`)));\r\n this.#transfer.addEventListener(TransferUploadEvent.TransferUploadModeChosen, eventArgs => this.logInfo(`Transfer upload mode chosen. Is UDP: ${eventArgs.isUdpMode}; Latency: ${eventArgs.latency ?? `<unkown>`}; Error: ${eventArgs.error ?? `<none>`}`));\r\n\r\n this.#transfer.addEventListener(TransferUploadEvent.TransferCompleted, eventArgs => this.logInfo(`Transfer completed successfully. ID: ${eventArgs.transferId}, URL: ${eventArgs.transferDownloadUrl}`));\r\n this.#transfer.addEventListener(TransferUploadEvent.FileChunkUploadProgressed, eventArgs => this.logTrace(`File ${eventArgs.fileStatus.fileName} having external id = ${eventArgs.fileStatus.externalId}, chunk starting at ${eventArgs.chunkStartPosition} having size ${eventArgs.chunkSizeInBytes} progressed: ${eventArgs.transferredBytesSinceLastEvent} bytes sinc last event. Total progress: ${this.#transfer?.progressInPercentage}%.`));\r\n\r\n this.#transfer.addEventListener(TransferUploadEvent.FileUploadStarted, eventArgs => this.logDebug(`File ${eventArgs.fileStatus.fileName} having external id = ${eventArgs.fileStatus.externalId} - upload started.`));\r\n this.#transfer.addEventListener(TransferUploadEvent.FileUploadCompleted, eventArgs => this.logDebug(`File ${eventArgs.fileStatus.fileName} having external id = ${eventArgs.fileStatus.externalId} - upload completed.`));\r\n this.#transfer.addEventListener(TransferUploadEvent.FileChunkUploadStarted, eventArgs => this.logTrace(`File ${eventArgs.fileStatus.fileName} having external id = ${eventArgs.fileStatus.externalId}, chunk starting at ${eventArgs.chunkStartPosition} having size ${eventArgs.chunkSizeInBytes} - upload started`));\r\n this.#transfer.addEventListener(TransferUploadEvent.FileChunkUploadCompleted, eventArgs => this.logTrace(`File ${eventArgs.fileStatus.fileName} having external id = ${eventArgs.fileStatus.externalId}, chunk starting at ${eventArgs.chunkStartPosition} having size ${eventArgs.chunkSizeInBytes} - upload completed`));\r\n this.#transfer.addEventListener(TransferUploadEvent.FileChunkUploadCompletedPartially, eventArgs => this.logWarning(`File ${eventArgs.fileStatus.fileName} having external id = ${eventArgs.fileStatus.externalId}, chunk starting at ${eventArgs.chunkStartPosition} having size ${eventArgs.chunkSizeInBytes} - uploaded partially - only ${eventArgs.uploadedBytesCount} bytes uploaded`));\r\n }\r\n\r\n private logHealthyStatus(isHealthy: boolean, event: UploadHealthMonitorHealthyEventArgs | UploadHealthMonitorUnhealthyEventArgs) {\r\n const logEntryMetadata = this.getLogEntryMetadata();\r\n\r\n const serializableEvent = this.makeEventSerializable(isHealthy, event);\r\n\r\n this.#logger.logInfo(`Transfer health status`, { isHealthy, event: serializableEvent, ...logEntryMetadata });\r\n }\r\n\r\n private makeEventSerializable(isHealthy: boolean, event: UploadHealthMonitorHealthyEventArgs | UploadHealthMonitorUnhealthyEventArgs): UploadHealthMonitorHealthyEventArgs | UploadHealthMonitorUnhealthyEventArgs {\r\n if (isHealthy)\r\n return event;\r\n\r\n const unhealthyEvent = event as UploadHealthMonitorUnhealthyEventArgs;\r\n\r\n return {\r\n ...unhealthyEvent,\r\n reason: {\r\n ...unhealthyEvent.reason,\r\n internet: this.makeReasonValueSerializable(unhealthyEvent.reason.internet),\r\n api: this.makeReasonValueSerializable(unhealthyEvent.reason.api),\r\n fileServer: this.makeReasonValueSerializable(unhealthyEvent.reason.fileServer),\r\n },\r\n };\r\n }\r\n\r\n private makeReasonValueSerializable(value: UploadHealthMonitorUnhealthyEventArgsReasonValue): UploadHealthMonitorUnhealthyEventArgsReasonValue {\r\n return {\r\n ...value,\r\n error: value.error === undefined ? undefined : {\r\n name: value.error.name,\r\n message: value.error.message,\r\n },\r\n };\r\n }\r\n\r\n private logTrace(message: string) {\r\n const logEntryMetadata = this.getLogEntryMetadata();\r\n this.#logger.logTrace(message, logEntryMetadata);\r\n }\r\n\r\n private logDebug(message: string) {\r\n const logEntryMetadata = this.getLogEntryMetadata();\r\n this.#logger.logDebug(message, logEntryMetadata);\r\n }\r\n\r\n private logInfo(message: string) {\r\n const logEntryMetadata = this.getLogEntryMetadata();\r\n this.#logger.logInfo(message, logEntryMetadata);\r\n }\r\n\r\n private logWarning(message: string) {\r\n const logEntryMetadata = this.getLogEntryMetadata();\r\n this.#logger.logWarning(message, logEntryMetadata);\r\n }\r\n\r\n private logError(error: Error, message?: string) {\r\n const logEntryMetadata = this.getLogEntryMetadata();\r\n this.#logger.logError(error, message, logEntryMetadata);\r\n }\r\n\r\n private getLogEntryMetadata() {\r\n return {\r\n [logEventPropertyName.TrackingIdPropertyName]: this.#trackingId,\r\n [logEventPropertyName.TransferIdPropertyName]: this.#transfer.transferId,\r\n };\r\n }\r\n\r\n private getFullFilePathOrFileName(fileStatus: ReadonlyTransferUploadStateFile): string {\r\n const fileDetails = this.#fileDetails.find(f => f.externalId === fileStatus.externalId);\r\n\r\n if (!fileDetails)\r\n return fileStatus.fileName;\r\n\r\n if (this.isNodeFileDetails(fileDetails))\r\n return fileDetails.fileFullPath;\r\n\r\n return fileDetails.file.name;\r\n }\r\n\r\n private isNodeFileDetails(fileDetails: NodeFileDetails | WebFileDetails): fileDetails is NodeFileDetails {\r\n return typeof (fileDetails as NodeFileDetails).fileFullPath === `string`;\r\n }\r\n}"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "filemail-sdk",
3
- "version": "9.0.8",
3
+ "version": "9.1.1",
4
4
  "description": "Library for transferring files to and from Filemail.com",
5
5
  "author": "Filemail AS",
6
6
  "license": "BSD-3-Clause",