filemail-sdk 9.4.2 → 9.4.3
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/uploader/chunksIterator/chunksIterator.d.ts +1 -0
- package/dist/src/uploader/chunksIterator/chunksIterator.d.ts.map +1 -1
- package/dist/src/uploader/chunksIterator/chunksIterator.js +12 -5
- package/dist/src/uploader/chunksIterator/chunksIterator.js.map +1 -1
- package/dist/src/uploader/optimizer/transferUploadOptimizer.d.ts +1 -0
- package/dist/src/uploader/optimizer/transferUploadOptimizer.d.ts.map +1 -1
- package/dist/src/uploader/optimizer/transferUploadOptimizer.js +11 -0
- package/dist/src/uploader/optimizer/transferUploadOptimizer.js.map +1 -1
- package/dist/src/uploader/transferUpload.d.ts.map +1 -1
- package/dist/src/uploader/transferUpload.js +7 -4
- package/dist/src/uploader/transferUpload.js.map +1 -1
- package/dist/src/utils/fileSystem/node/nodeChunkStreamProvider.d.ts +2 -0
- package/dist/src/utils/fileSystem/node/nodeChunkStreamProvider.d.ts.map +1 -1
- package/dist/src/utils/fileSystem/node/nodeChunkStreamProvider.js +23 -5
- package/dist/src/utils/fileSystem/node/nodeChunkStreamProvider.js.map +1 -1
- package/package.json +1 -1
|
@@ -6,6 +6,7 @@ export default class ChunksIterator {
|
|
|
6
6
|
});
|
|
7
7
|
private sanitizeChunks;
|
|
8
8
|
private removeZeroByteChunks;
|
|
9
|
+
private createChunksByStartPositionMap;
|
|
9
10
|
getChunksIterator(): IterableIterator<ContinuousChunk>;
|
|
10
11
|
private isZeroBytesFilesCase;
|
|
11
12
|
private getNextIteratorValueForZeroBytesFile;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chunksIterator.d.ts","sourceRoot":"","sources":["../../../../src/uploader/chunksIterator/chunksIterator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wCAAwC,CAAC;AAE9E,MAAM,CAAC,OAAO,OAAO,cAAc;;
|
|
1
|
+
{"version":3,"file":"chunksIterator.d.ts","sourceRoot":"","sources":["../../../../src/uploader/chunksIterator/chunksIterator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wCAAwC,CAAC;AAE9E,MAAM,CAAC,OAAO,OAAO,cAAc;;gBAUnB,iBAAiB,EAAE,SAAS,QAAQ,CAAC,eAAe,CAAC,EAAE,EAAE,eAAe,EAAE,MAAM,EAAE,wBAAwB,EAAE;QAAE,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAA;KAAE;IAQ7J,OAAO,CAAC,cAAc;IAItB,OAAO,CAAC,oBAAoB;IAI5B,OAAO,CAAC,8BAA8B;IAItC,iBAAiB,IAAI,gBAAgB,CAAC,eAAe,CAAC;IActD,OAAO,CAAC,oBAAoB;IAI5B,OAAO,CAAC,oCAAoC;IAS5C,OAAO,CAAC,oBAAoB;IAa5B,OAAO,CAAC,qBAAqB;IAa7B,OAAO,CAAC,mBAAmB;CAgB9B"}
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
export default class ChunksIterator {
|
|
2
2
|
#alreadySentChunks;
|
|
3
|
+
#alreadySentChunksByStartPosition;
|
|
3
4
|
#fileSizeInBytes;
|
|
4
5
|
#currentChunkSizeProvider;
|
|
5
6
|
#nextChunkStartPosition = 0;
|
|
6
7
|
#isValueAlreadyReturnedForZeroBytesFile = false;
|
|
7
8
|
constructor(alreadySentChunks, fileSizeInBytes, currentChunkSizeProvider) {
|
|
8
9
|
this.#alreadySentChunks = this.sanitizeChunks(alreadySentChunks);
|
|
10
|
+
this.#alreadySentChunksByStartPosition = this.createChunksByStartPositionMap(this.#alreadySentChunks);
|
|
9
11
|
this.#fileSizeInBytes = fileSizeInBytes;
|
|
10
12
|
this.#currentChunkSizeProvider = currentChunkSizeProvider;
|
|
11
13
|
}
|
|
@@ -16,6 +18,9 @@ export default class ChunksIterator {
|
|
|
16
18
|
removeZeroByteChunks(alreadySentChunks) {
|
|
17
19
|
return alreadySentChunks.filter(c => c.sizeInBytes > 0);
|
|
18
20
|
}
|
|
21
|
+
createChunksByStartPositionMap(alreadySentChunks) {
|
|
22
|
+
return new Map(alreadySentChunks.map(chunk => [chunk.startPosition, chunk.sizeInBytes]));
|
|
23
|
+
}
|
|
19
24
|
getChunksIterator() {
|
|
20
25
|
return {
|
|
21
26
|
[Symbol.iterator]() {
|
|
@@ -46,11 +51,13 @@ export default class ChunksIterator {
|
|
|
46
51
|
return { value: { startPosition, sizeInBytes }, done: false };
|
|
47
52
|
}
|
|
48
53
|
getChunkStartPosition(nextChunkStartPosition) {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
+
let chunkStartPosition = nextChunkStartPosition;
|
|
55
|
+
while (true) {
|
|
56
|
+
const alreadySentChunkSize = this.#alreadySentChunksByStartPosition.get(chunkStartPosition);
|
|
57
|
+
if (!alreadySentChunkSize)
|
|
58
|
+
return chunkStartPosition;
|
|
59
|
+
chunkStartPosition += alreadySentChunkSize;
|
|
60
|
+
}
|
|
54
61
|
}
|
|
55
62
|
getChunkSizeInBytes(newChunkStartPosition) {
|
|
56
63
|
const currentMaxChunkSize = this.#currentChunkSizeProvider.currentChunkSize;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chunksIterator.js","sourceRoot":"","sources":["../../../../src/uploader/chunksIterator/chunksIterator.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,OAAO,OAAO,cAAc;IAC/B,kBAAkB,CAAuC;IACzD,gBAAgB,CAAS;IACzB,yBAAyB,CAAwC;IAEjE,uBAAuB,GAAG,CAAC,CAAC;IAE5B,uCAAuC,GAAG,KAAK,CAAC;IAEhD,YAAY,iBAAuD,EAAE,eAAuB,EAAE,wBAA+D;QACzJ,IAAI,CAAC,kBAAkB,GAAG,IAAI,CAAC,cAAc,CAAC,iBAAiB,CAAC,CAAC;QACjE,IAAI,CAAC,gBAAgB,GAAG,eAAe,CAAC;QACxC,IAAI,CAAC,yBAAyB,GAAG,wBAAwB,CAAC;IAC9D,CAAC;IAED,mGAAmG;IAC3F,cAAc,CAAC,iBAAuD;QAC1E,OAAO,IAAI,CAAC,oBAAoB,CAAC,iBAAiB,CAAC,CAAC;IACxD,CAAC;IAEO,oBAAoB,CAAC,iBAAuD;QAChF,OAAO,iBAAiB,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,WAAW,GAAG,CAAC,CAAC,CAAC;IAC5D,CAAC;IAED,iBAAiB;QACb,OAAO;YACH,CAAC,MAAM,CAAC,QAAQ,CAAC;gBACb,OAAO,IAAI,CAAC;YAChB,CAAC;YACD,IAAI,EAAE,GAAoC,EAAE;gBACxC,IAAI,IAAI,CAAC,oBAAoB,EAAE;oBAC3B,OAAO,IAAI,CAAC,oCAAoC,EAAE,CAAC;gBAEvD,OAAO,IAAI,CAAC,oBAAoB,EAAE,CAAC;YACvC,CAAC;SACJ,CAAC;IACN,CAAC;IAEO,oBAAoB;QACxB,OAAO,IAAI,CAAC,gBAAgB,KAAK,CAAC,CAAC;IACvC,CAAC;IAEO,oCAAoC;QACxC,IAAI,IAAI,CAAC,uCAAuC;YAC5C,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;QAEvC,IAAI,CAAC,uCAAuC,GAAG,IAAI,CAAC;QAEpD,OAAO,EAAE,KAAK,EAAE,EAAE,aAAa,EAAE,CAAC,EAAE,WAAW,EAAE,CAAC,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;IACxE,CAAC;IAEO,oBAAoB;QACxB,MAAM,aAAa,GAAG,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC;QAE/E,IAAI,aAAa,KAAK,IAAI,CAAC,gBAAgB;YACvC,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;QAEvC,MAAM,WAAW,GAAG,IAAI,CAAC,mBAAmB,CAAC,aAAa,CAAC,CAAC;QAE5D,IAAI,CAAC,uBAAuB,GAAG,aAAa,GAAG,WAAW,CAAC;QAE3D,OAAO,EAAE,KAAK,EAAE,EAAE,aAAa,EAAE,WAAW,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;IAClE,CAAC;IAEO,qBAAqB,CAAC,sBAA8B;QACxD,
|
|
1
|
+
{"version":3,"file":"chunksIterator.js","sourceRoot":"","sources":["../../../../src/uploader/chunksIterator/chunksIterator.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ContinuousChunk } from \"../state/continuousChunksCalculator.js\";\n\nexport default class ChunksIterator {\n #alreadySentChunks: readonly Readonly<ContinuousChunk>[];\n #alreadySentChunksByStartPosition: ReadonlyMap<number, number>;\n #fileSizeInBytes: number;\n #currentChunkSizeProvider: { readonly currentChunkSize: number };\n\n #nextChunkStartPosition = 0;\n\n #isValueAlreadyReturnedForZeroBytesFile = false;\n\n constructor(alreadySentChunks: readonly Readonly<ContinuousChunk>[], fileSizeInBytes: number, currentChunkSizeProvider: { readonly currentChunkSize: number }) {\n this.#alreadySentChunks = this.sanitizeChunks(alreadySentChunks);\n this.#alreadySentChunksByStartPosition = this.createChunksByStartPositionMap(this.#alreadySentChunks);\n this.#fileSizeInBytes = fileSizeInBytes;\n this.#currentChunkSizeProvider = currentChunkSizeProvider;\n }\n\n // This is an anti corruption layer that can be removed after everybody migrates to desktop > 4.8.2\n private sanitizeChunks(alreadySentChunks: readonly Readonly<ContinuousChunk>[]): readonly Readonly<ContinuousChunk>[] {\n return this.removeZeroByteChunks(alreadySentChunks);\n }\n\n private removeZeroByteChunks(alreadySentChunks: readonly Readonly<ContinuousChunk>[]): readonly Readonly<ContinuousChunk>[] {\n return alreadySentChunks.filter(c => c.sizeInBytes > 0);\n }\n\n private createChunksByStartPositionMap(alreadySentChunks: readonly Readonly<ContinuousChunk>[]): ReadonlyMap<number, number> {\n return new Map(alreadySentChunks.map(chunk => [chunk.startPosition, chunk.sizeInBytes]));\n }\n\n getChunksIterator(): IterableIterator<ContinuousChunk> {\n return {\n [Symbol.iterator](): IterableIterator<ContinuousChunk> {\n return this;\n },\n next: (): IteratorResult<ContinuousChunk> => {\n if (this.isZeroBytesFilesCase())\n return this.getNextIteratorValueForZeroBytesFile();\n\n return this.getNextIteratorValue();\n },\n };\n }\n\n private isZeroBytesFilesCase(): boolean {\n return this.#fileSizeInBytes === 0;\n }\n\n private getNextIteratorValueForZeroBytesFile(): IteratorResult<ContinuousChunk> {\n if (this.#isValueAlreadyReturnedForZeroBytesFile)\n return { value: null, done: true };\n\n this.#isValueAlreadyReturnedForZeroBytesFile = true;\n\n return { value: { startPosition: 0, sizeInBytes: 0 }, done: false };\n }\n\n private getNextIteratorValue(): IteratorResult<ContinuousChunk> {\n const startPosition = this.getChunkStartPosition(this.#nextChunkStartPosition);\n\n if (startPosition === this.#fileSizeInBytes)\n return { value: null, done: true };\n\n const sizeInBytes = this.getChunkSizeInBytes(startPosition);\n\n this.#nextChunkStartPosition = startPosition + sizeInBytes;\n\n return { value: { startPosition, sizeInBytes }, done: false };\n }\n\n private getChunkStartPosition(nextChunkStartPosition: number): number {\n let chunkStartPosition = nextChunkStartPosition;\n\n while (true) {\n const alreadySentChunkSize = this.#alreadySentChunksByStartPosition.get(chunkStartPosition);\n\n if (!alreadySentChunkSize)\n return chunkStartPosition;\n\n chunkStartPosition += alreadySentChunkSize;\n }\n }\n\n private getChunkSizeInBytes(newChunkStartPosition: number) {\n const currentMaxChunkSize = this.#currentChunkSizeProvider.currentChunkSize;\n const newChunkEndPosition = newChunkStartPosition + currentMaxChunkSize - 1;\n\n const alreadySentChunkStartingInTheMiddle = this.#alreadySentChunks.find(c => newChunkStartPosition < c.startPosition && c.startPosition <= newChunkEndPosition);\n\n if (alreadySentChunkStartingInTheMiddle)\n return alreadySentChunkStartingInTheMiddle.startPosition - newChunkStartPosition;\n\n const chunkEndsBeyondFile = newChunkEndPosition >= this.#fileSizeInBytes;\n\n if (chunkEndsBeyondFile)\n return this.#fileSizeInBytes - newChunkStartPosition;\n\n return currentMaxChunkSize;\n }\n}"]}
|
|
@@ -21,6 +21,7 @@ export default class TransferUploadOptimizer implements UploadOptimizer {
|
|
|
21
21
|
private isMsgSizeError;
|
|
22
22
|
private isNoBufsError;
|
|
23
23
|
private isErrorContainingErrorCode;
|
|
24
|
+
private trimHistoryArrayToMaxEntries;
|
|
24
25
|
private optimize;
|
|
25
26
|
}
|
|
26
27
|
//# sourceMappingURL=transferUploadOptimizer.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transferUploadOptimizer.d.ts","sourceRoot":"","sources":["../../../../src/uploader/optimizer/transferUploadOptimizer.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,mBAAmB,MAAM,0DAA0D,CAAC;AAChG,OAAO,KAAK,eAAe,MAAM,sBAAsB,CAAC;AACxD,OAAO,KAAK,YAAY,MAAM,oCAAoC,CAAC;AAInE,OAAO,KAAK,kCAAkC,MAAM,yCAAyC,CAAC;
|
|
1
|
+
{"version":3,"file":"transferUploadOptimizer.d.ts","sourceRoot":"","sources":["../../../../src/uploader/optimizer/transferUploadOptimizer.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,mBAAmB,MAAM,0DAA0D,CAAC;AAChG,OAAO,KAAK,eAAe,MAAM,sBAAsB,CAAC;AACxD,OAAO,KAAK,YAAY,MAAM,oCAAoC,CAAC;AAInE,OAAO,KAAK,kCAAkC,MAAM,yCAAyC,CAAC;AAK9F,MAAM,CAAC,OAAO,OAAO,uBAAwB,YAAW,eAAe;;gBAoCvD,YAAY,EAAE,MAAM,EAAE,yBAAyB,EAAE,MAAM,EAAE,oBAAoB,EAAE,YAAY,EAAE,uBAAuB,EAAE,kCAAkC;IAOpK,IAAI,gBAAgB,IAAI,MAAM,CAI7B;IAED,IAAI,yBAAyB,IAAI,MAAM,CAItC;IAED,IAAI,oBAAoB,IAAI,MAAM,CAyBjC;IAEK,gBAAgB,IAAI,OAAO,CAAC,mBAAmB,CAAC;IAMtD,OAAO,CAAC,iBAAiB;IAKzB,KAAK,CAAC,KAAK,EAAE,OAAO,EAAE,iBAAiB,EAAE,MAAM;IA8B/C,IAAI;IASJ,OAAO,CAAC,yBAAyB;IAOjC,OAAO,CAAC,6BAA6B;IAOrC,OAAO,CAAC,kBAAkB,CAGxB;IAEF,OAAO,CAAC,oBAAoB,CAG1B;IAEF,OAAO,CAAC,6BAA6B,CAGnC;IAEF,OAAO,CAAC,iBAAiB,CAkBvB;IAEF,OAAO,CAAC,cAAc;IAItB,OAAO,CAAC,aAAa;IAIrB,OAAO,CAAC,0BAA0B;IAUlC,OAAO,CAAC,4BAA4B;IAOpC,OAAO,CAAC,QAAQ,CAed;CACL"}
|
|
@@ -2,6 +2,8 @@ import throttle from "lodash.throttle";
|
|
|
2
2
|
import TransferConcurrencyController from "../../utils/concurrencyController/transferConcurrencyController.js";
|
|
3
3
|
import TransferUploadEvent from "../transferUploadEvent.js";
|
|
4
4
|
import FsError from "../../utils/fileSystem/fsError.js";
|
|
5
|
+
const MAX_OPTIMIZER_HISTORY_ENTRIES = 10_000;
|
|
6
|
+
const OPTIMIZER_HISTORY_TRIM_THRESHOLD = 12_000;
|
|
5
7
|
export default class TransferUploadOptimizer {
|
|
6
8
|
#tcpChunkSize;
|
|
7
9
|
#tcpChunksUploadInParallel;
|
|
@@ -109,12 +111,15 @@ export default class TransferUploadOptimizer {
|
|
|
109
111
|
}
|
|
110
112
|
chunkUploadStarted = () => {
|
|
111
113
|
this.#startedChunksTimeHistory.push(Date.now());
|
|
114
|
+
this.#startedChunksTimeHistory = this.trimHistoryArrayToMaxEntries(this.#startedChunksTimeHistory);
|
|
112
115
|
};
|
|
113
116
|
chunkUploadSucceeded = (eventArgs) => {
|
|
114
117
|
this.#ackedChunksHistory.push({ time: Date.now(), latencyInMs: eventArgs.latencyInMsIfUdp });
|
|
118
|
+
this.#ackedChunksHistory = this.trimHistoryArrayToMaxEntries(this.#ackedChunksHistory);
|
|
115
119
|
};
|
|
116
120
|
chunkUploadSucceededPartially = (eventArgs) => {
|
|
117
121
|
this.#ackedChunksHistory.push({ time: Date.now(), latencyInMs: eventArgs.latencyInMsIfUdp });
|
|
122
|
+
this.#ackedChunksHistory = this.trimHistoryArrayToMaxEntries(this.#ackedChunksHistory);
|
|
118
123
|
};
|
|
119
124
|
chunkUploadFailed = (eventArgs) => {
|
|
120
125
|
const isFileAccessError = eventArgs.error.cause instanceof FsError;
|
|
@@ -129,6 +134,7 @@ export default class TransferUploadOptimizer {
|
|
|
129
134
|
return;
|
|
130
135
|
}
|
|
131
136
|
this.#failedChunksTimeHistory.push(Date.now());
|
|
137
|
+
this.#failedChunksTimeHistory = this.trimHistoryArrayToMaxEntries(this.#failedChunksTimeHistory);
|
|
132
138
|
};
|
|
133
139
|
isMsgSizeError(error) {
|
|
134
140
|
return this.isErrorContainingErrorCode(error, `EMSGSIZE`);
|
|
@@ -143,6 +149,11 @@ export default class TransferUploadOptimizer {
|
|
|
143
149
|
return this.isErrorContainingErrorCode(error.cause, errorCode);
|
|
144
150
|
return false;
|
|
145
151
|
}
|
|
152
|
+
trimHistoryArrayToMaxEntries(history) {
|
|
153
|
+
if (history.length <= OPTIMIZER_HISTORY_TRIM_THRESHOLD)
|
|
154
|
+
return history;
|
|
155
|
+
return history.slice(history.length - MAX_OPTIMIZER_HISTORY_ENTRIES);
|
|
156
|
+
}
|
|
146
157
|
optimize = async () => {
|
|
147
158
|
const optimizationResult = this.#udpOptimizationStrategy.getOptimizedValues(this.#startedChunksTimeHistory, this.#ackedChunksHistory, this.#failedChunksTimeHistory, this.#currentOptimizationValues);
|
|
148
159
|
this.#currentOptimizationValues = optimizationResult.optimizedValues;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transferUploadOptimizer.js","sourceRoot":"","sources":["../../../../src/uploader/optimizer/transferUploadOptimizer.ts"],"names":[],"mappings":"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","sourcesContent":["import throttle from \"lodash.throttle\";\n\nimport TransferConcurrencyController from \"../../utils/concurrencyController/transferConcurrencyController.js\";\nimport TransferUploadEvent from \"../transferUploadEvent.js\";\nimport FsError from \"../../utils/fileSystem/fsError.js\";\n\nimport type OptimizationValues from \"./optimizationValues.js\";\nimport type ConcurrencyController from \"../../utils/concurrencyController/concurrencyController.js\";\nimport type ConcurrencyReleaser from \"../../utils/concurrencyController/concurrencyReleaser.js\";\nimport type UploadOptimizer from \"./uploadOptimizer.js\";\nimport type EventsEngine from \"../../utils/events/eventsEngine.js\";\nimport type FileChunkUploadFailedEventArgs from \"../eventArgs/fileChunkUploadFailedEventArgs.js\";\nimport type FileChunkUploadCompletedEventArgs from \"../eventArgs/fileChunkUploadCompletedEventArgs.js\";\nimport type FileChunkUploadCompletedPartiallyEventArgs from \"../eventArgs/fileChunkUploadCompletedPartiallyEventArgs.js\";\nimport type TransferUploadOptimizationStrategy from \"./transferUploadOptimizationStrategy.js\";\n\nexport default class TransferUploadOptimizer implements UploadOptimizer {\n readonly #tcpChunkSize: number;\n readonly #tcpChunksUploadInParallel: number;\n readonly #transferEventsEngine: EventsEngine;\n readonly #udpOptimizationStrategy: TransferUploadOptimizationStrategy;\n\n #concurrencyController: ConcurrencyController | undefined;\n\n #isUdp: boolean | undefined;\n\n #initialOptimizationValues: OptimizationValues | undefined;\n #currentOptimizationValues: OptimizationValues | undefined;\n\n #timeout: NodeJS.Timeout | undefined;\n\n #startedChunksTimeHistory: number[] = [];\n #ackedChunksHistory: { time: number, latencyInMs: number }[] = [];\n #failedChunksTimeHistory: number[] = [];\n\n #chunksStartedInThisMs = 0;\n\n #noBufsErrorHandler = throttle(() => {\n const result = this.#udpOptimizationStrategy.noBufsErrorHandler(this.#currentOptimizationValues!);\n\n this.#currentOptimizationValues!.maxParallelChunksAmount = result.maxParallelChunksAmount;\n this.#currentOptimizationValues!.minTimeBetweenChunksStartInMs = result.minTimeBetweenChunksStartInMs;\n\n this.#concurrencyController!.maxConcurrency = this.#currentOptimizationValues!.maxParallelChunksAmount;\n }, 500, { leading: true, trailing: false });\n\n #msgSizeErrorHandler = throttle(() => {\n const result = this.#udpOptimizationStrategy.msgSizeErrorHandler(this.#currentOptimizationValues!);\n\n this.#currentOptimizationValues!.chunkSize = result.chunkSize;\n }, 500, { leading: true, trailing: false });\n\n constructor(tcpChunkSize: number, tcpChunksUploadInParallel: number, transferEventsEngine: EventsEngine, udpOptimizationStrategy: TransferUploadOptimizationStrategy) {\n this.#tcpChunkSize = tcpChunkSize;\n this.#tcpChunksUploadInParallel = tcpChunksUploadInParallel;\n this.#transferEventsEngine = transferEventsEngine;\n this.#udpOptimizationStrategy = udpOptimizationStrategy;\n }\n\n get currentChunkSize(): number {\n this.throwIfNotStarted();\n\n return this.#currentOptimizationValues!.chunkSize;\n }\n\n get currentRequestTimeoutInMs(): number {\n this.throwIfNotStarted();\n\n return this.#currentOptimizationValues!.requestTimeoutInMs;\n }\n\n get currentSleepTimeInMs(): number {\n this.throwIfNotStarted();\n\n if (this.#startedChunksTimeHistory.length === 0)\n return 0;\n\n if (this.#currentOptimizationValues!.minTimeBetweenChunksStartInMs < 1) {\n const chunksToStartPerMs = Math.ceil(1 / this.#currentOptimizationValues!.minTimeBetweenChunksStartInMs);\n\n if (this.#chunksStartedInThisMs < chunksToStartPerMs) {\n this.#chunksStartedInThisMs += 1;\n return 0;\n }\n\n this.#chunksStartedInThisMs = 0;\n return 1;\n }\n\n const lastChunkStartTime = this.#startedChunksTimeHistory[this.#startedChunksTimeHistory.length - 1]!;\n const timeSinceLastStart = new Date().getTime() - lastChunkStartTime;\n\n if (timeSinceLastStart < this.#currentOptimizationValues!.minTimeBetweenChunksStartInMs)\n return this.#currentOptimizationValues!.minTimeBetweenChunksStartInMs - timeSinceLastStart;\n\n return 0;\n }\n\n async semaphoreAcquire(): Promise<ConcurrencyReleaser> {\n this.throwIfNotStarted();\n\n return await this.#concurrencyController!.acquire();\n }\n\n private throwIfNotStarted() {\n if (this.#isUdp === undefined)\n throw new Error(`Optimizer hasn't been started`);\n }\n\n start(isUdp: boolean, serverLatencyInMs: number) {\n this.#isUdp = isUdp;\n\n if (isUdp) {\n this.#initialOptimizationValues = this.#udpOptimizationStrategy.getInitialValues(serverLatencyInMs);\n this.#currentOptimizationValues = this.#initialOptimizationValues;\n\n this.#concurrencyController = new TransferConcurrencyController(this.#initialOptimizationValues.maxParallelChunksAmount);\n\n this.subscribeToTransferEvents();\n\n this.#timeout = setTimeout(() => this.optimize(), this.#initialOptimizationValues.optimizationIntervalInMs);\n }\n else {\n this.#timeout = undefined;\n\n this.#initialOptimizationValues = {\n chunkSize: this.#tcpChunkSize,\n maxParallelChunksAmount: this.#tcpChunksUploadInParallel,\n minTimeBetweenChunksStartInMs: 0,\n optimizationIntervalInMs: 0,\n requestTimeoutInMs: 0,\n };\n\n this.#currentOptimizationValues = this.#initialOptimizationValues;\n\n this.#concurrencyController = new TransferConcurrencyController(this.#tcpChunksUploadInParallel);\n }\n }\n\n stop() {\n if (!this.#isUdp)\n return;\n\n clearTimeout(this.#timeout);\n\n this.unsubscribeFromTransferEvents();\n }\n\n private subscribeToTransferEvents() {\n this.#transferEventsEngine.addEventListener(TransferUploadEvent.FileChunkUploadStarted, this.chunkUploadStarted);\n this.#transferEventsEngine.addEventListener(TransferUploadEvent.FileChunkUploadCompleted, this.chunkUploadSucceeded);\n this.#transferEventsEngine.addEventListener(TransferUploadEvent.FileChunkUploadCompletedPartially, this.chunkUploadSucceededPartially);\n this.#transferEventsEngine.addEventListener(TransferUploadEvent.FileChunkUploadFailed, this.chunkUploadFailed);\n }\n\n private unsubscribeFromTransferEvents() {\n this.#transferEventsEngine.removeEventListener(TransferUploadEvent.FileChunkUploadStarted, this.chunkUploadStarted);\n this.#transferEventsEngine.removeEventListener(TransferUploadEvent.FileChunkUploadCompleted, this.chunkUploadSucceeded);\n this.#transferEventsEngine.removeEventListener(TransferUploadEvent.FileChunkUploadCompletedPartially, this.chunkUploadSucceededPartially);\n this.#transferEventsEngine.removeEventListener(TransferUploadEvent.FileChunkUploadFailed, this.chunkUploadFailed);\n }\n\n private chunkUploadStarted = () => {\n this.#startedChunksTimeHistory.push(Date.now());\n };\n\n private chunkUploadSucceeded = (eventArgs: FileChunkUploadCompletedEventArgs) => {\n this.#ackedChunksHistory.push({ time: Date.now(), latencyInMs: eventArgs.latencyInMsIfUdp! });\n };\n\n private chunkUploadSucceededPartially = (eventArgs: FileChunkUploadCompletedPartiallyEventArgs) => {\n this.#ackedChunksHistory.push({ time: Date.now(), latencyInMs: eventArgs.latencyInMsIfUdp! });\n };\n\n private chunkUploadFailed = (eventArgs: FileChunkUploadFailedEventArgs) => {\n const isFileAccessError = eventArgs.error.cause instanceof FsError;\n\n if (isFileAccessError)\n return;\n\n if (this.isMsgSizeError(eventArgs.error)) {\n this.#msgSizeErrorHandler();\n return;\n }\n\n if (this.isNoBufsError(eventArgs.error)) {\n this.#noBufsErrorHandler();\n return;\n }\n\n this.#failedChunksTimeHistory.push(Date.now());\n };\n\n private isMsgSizeError(error: Error) {\n return this.isErrorContainingErrorCode(error, `EMSGSIZE`);\n }\n\n private isNoBufsError(error: Error) {\n return this.isErrorContainingErrorCode(error, `ENOBUFS`);\n }\n\n private isErrorContainingErrorCode(error: Error, errorCode: string): boolean {\n if (error.message.includes(errorCode))\n return true;\n\n if (error.cause)\n return this.isErrorContainingErrorCode(error.cause, errorCode);\n\n return false;\n }\n\n private optimize = async (): Promise<void> => {\n const optimizationResult = this.#udpOptimizationStrategy.getOptimizedValues(this.#startedChunksTimeHistory, this.#ackedChunksHistory, this.#failedChunksTimeHistory, this.#currentOptimizationValues!);\n\n this.#currentOptimizationValues = optimizationResult.optimizedValues;\n\n this.#concurrencyController!.maxConcurrency = this.#currentOptimizationValues.maxParallelChunksAmount;\n\n this.#timeout = setTimeout(() => this.optimize(), optimizationResult.optimizedValues.optimizationIntervalInMs);\n\n if (optimizationResult.clearChunksHistory === false)\n return;\n\n this.#startedChunksTimeHistory = [];\n this.#ackedChunksHistory = [];\n this.#failedChunksTimeHistory = [];\n };\n}"]}
|
|
1
|
+
{"version":3,"file":"transferUploadOptimizer.js","sourceRoot":"","sources":["../../../../src/uploader/optimizer/transferUploadOptimizer.ts"],"names":[],"mappings":"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","sourcesContent":["import throttle from \"lodash.throttle\";\n\nimport TransferConcurrencyController from \"../../utils/concurrencyController/transferConcurrencyController.js\";\nimport TransferUploadEvent from \"../transferUploadEvent.js\";\nimport FsError from \"../../utils/fileSystem/fsError.js\";\n\nimport type OptimizationValues from \"./optimizationValues.js\";\nimport type ConcurrencyController from \"../../utils/concurrencyController/concurrencyController.js\";\nimport type ConcurrencyReleaser from \"../../utils/concurrencyController/concurrencyReleaser.js\";\nimport type UploadOptimizer from \"./uploadOptimizer.js\";\nimport type EventsEngine from \"../../utils/events/eventsEngine.js\";\nimport type FileChunkUploadFailedEventArgs from \"../eventArgs/fileChunkUploadFailedEventArgs.js\";\nimport type FileChunkUploadCompletedEventArgs from \"../eventArgs/fileChunkUploadCompletedEventArgs.js\";\nimport type FileChunkUploadCompletedPartiallyEventArgs from \"../eventArgs/fileChunkUploadCompletedPartiallyEventArgs.js\";\nimport type TransferUploadOptimizationStrategy from \"./transferUploadOptimizationStrategy.js\";\n\nconst MAX_OPTIMIZER_HISTORY_ENTRIES = 10_000;\nconst OPTIMIZER_HISTORY_TRIM_THRESHOLD = 12_000;\n\nexport default class TransferUploadOptimizer implements UploadOptimizer {\n readonly #tcpChunkSize: number;\n readonly #tcpChunksUploadInParallel: number;\n readonly #transferEventsEngine: EventsEngine;\n readonly #udpOptimizationStrategy: TransferUploadOptimizationStrategy;\n\n #concurrencyController: ConcurrencyController | undefined;\n\n #isUdp: boolean | undefined;\n\n #initialOptimizationValues: OptimizationValues | undefined;\n #currentOptimizationValues: OptimizationValues | undefined;\n\n #timeout: NodeJS.Timeout | undefined;\n\n #startedChunksTimeHistory: number[] = [];\n #ackedChunksHistory: { time: number, latencyInMs: number }[] = [];\n #failedChunksTimeHistory: number[] = [];\n\n #chunksStartedInThisMs = 0;\n\n #noBufsErrorHandler = throttle(() => {\n const result = this.#udpOptimizationStrategy.noBufsErrorHandler(this.#currentOptimizationValues!);\n\n this.#currentOptimizationValues!.maxParallelChunksAmount = result.maxParallelChunksAmount;\n this.#currentOptimizationValues!.minTimeBetweenChunksStartInMs = result.minTimeBetweenChunksStartInMs;\n\n this.#concurrencyController!.maxConcurrency = this.#currentOptimizationValues!.maxParallelChunksAmount;\n }, 500, { leading: true, trailing: false });\n\n #msgSizeErrorHandler = throttle(() => {\n const result = this.#udpOptimizationStrategy.msgSizeErrorHandler(this.#currentOptimizationValues!);\n\n this.#currentOptimizationValues!.chunkSize = result.chunkSize;\n }, 500, { leading: true, trailing: false });\n\n constructor(tcpChunkSize: number, tcpChunksUploadInParallel: number, transferEventsEngine: EventsEngine, udpOptimizationStrategy: TransferUploadOptimizationStrategy) {\n this.#tcpChunkSize = tcpChunkSize;\n this.#tcpChunksUploadInParallel = tcpChunksUploadInParallel;\n this.#transferEventsEngine = transferEventsEngine;\n this.#udpOptimizationStrategy = udpOptimizationStrategy;\n }\n\n get currentChunkSize(): number {\n this.throwIfNotStarted();\n\n return this.#currentOptimizationValues!.chunkSize;\n }\n\n get currentRequestTimeoutInMs(): number {\n this.throwIfNotStarted();\n\n return this.#currentOptimizationValues!.requestTimeoutInMs;\n }\n\n get currentSleepTimeInMs(): number {\n this.throwIfNotStarted();\n\n if (this.#startedChunksTimeHistory.length === 0)\n return 0;\n\n if (this.#currentOptimizationValues!.minTimeBetweenChunksStartInMs < 1) {\n const chunksToStartPerMs = Math.ceil(1 / this.#currentOptimizationValues!.minTimeBetweenChunksStartInMs);\n\n if (this.#chunksStartedInThisMs < chunksToStartPerMs) {\n this.#chunksStartedInThisMs += 1;\n return 0;\n }\n\n this.#chunksStartedInThisMs = 0;\n return 1;\n }\n\n const lastChunkStartTime = this.#startedChunksTimeHistory[this.#startedChunksTimeHistory.length - 1]!;\n const timeSinceLastStart = new Date().getTime() - lastChunkStartTime;\n\n if (timeSinceLastStart < this.#currentOptimizationValues!.minTimeBetweenChunksStartInMs)\n return this.#currentOptimizationValues!.minTimeBetweenChunksStartInMs - timeSinceLastStart;\n\n return 0;\n }\n\n async semaphoreAcquire(): Promise<ConcurrencyReleaser> {\n this.throwIfNotStarted();\n\n return await this.#concurrencyController!.acquire();\n }\n\n private throwIfNotStarted() {\n if (this.#isUdp === undefined)\n throw new Error(`Optimizer hasn't been started`);\n }\n\n start(isUdp: boolean, serverLatencyInMs: number) {\n this.#isUdp = isUdp;\n\n if (isUdp) {\n this.#initialOptimizationValues = this.#udpOptimizationStrategy.getInitialValues(serverLatencyInMs);\n this.#currentOptimizationValues = this.#initialOptimizationValues;\n\n this.#concurrencyController = new TransferConcurrencyController(this.#initialOptimizationValues.maxParallelChunksAmount);\n\n this.subscribeToTransferEvents();\n\n this.#timeout = setTimeout(() => this.optimize(), this.#initialOptimizationValues.optimizationIntervalInMs);\n }\n else {\n this.#timeout = undefined;\n\n this.#initialOptimizationValues = {\n chunkSize: this.#tcpChunkSize,\n maxParallelChunksAmount: this.#tcpChunksUploadInParallel,\n minTimeBetweenChunksStartInMs: 0,\n optimizationIntervalInMs: 0,\n requestTimeoutInMs: 0,\n };\n\n this.#currentOptimizationValues = this.#initialOptimizationValues;\n\n this.#concurrencyController = new TransferConcurrencyController(this.#tcpChunksUploadInParallel);\n }\n }\n\n stop() {\n if (!this.#isUdp)\n return;\n\n clearTimeout(this.#timeout);\n\n this.unsubscribeFromTransferEvents();\n }\n\n private subscribeToTransferEvents() {\n this.#transferEventsEngine.addEventListener(TransferUploadEvent.FileChunkUploadStarted, this.chunkUploadStarted);\n this.#transferEventsEngine.addEventListener(TransferUploadEvent.FileChunkUploadCompleted, this.chunkUploadSucceeded);\n this.#transferEventsEngine.addEventListener(TransferUploadEvent.FileChunkUploadCompletedPartially, this.chunkUploadSucceededPartially);\n this.#transferEventsEngine.addEventListener(TransferUploadEvent.FileChunkUploadFailed, this.chunkUploadFailed);\n }\n\n private unsubscribeFromTransferEvents() {\n this.#transferEventsEngine.removeEventListener(TransferUploadEvent.FileChunkUploadStarted, this.chunkUploadStarted);\n this.#transferEventsEngine.removeEventListener(TransferUploadEvent.FileChunkUploadCompleted, this.chunkUploadSucceeded);\n this.#transferEventsEngine.removeEventListener(TransferUploadEvent.FileChunkUploadCompletedPartially, this.chunkUploadSucceededPartially);\n this.#transferEventsEngine.removeEventListener(TransferUploadEvent.FileChunkUploadFailed, this.chunkUploadFailed);\n }\n\n private chunkUploadStarted = () => {\n this.#startedChunksTimeHistory.push(Date.now());\n this.#startedChunksTimeHistory = this.trimHistoryArrayToMaxEntries(this.#startedChunksTimeHistory);\n };\n\n private chunkUploadSucceeded = (eventArgs: FileChunkUploadCompletedEventArgs) => {\n this.#ackedChunksHistory.push({ time: Date.now(), latencyInMs: eventArgs.latencyInMsIfUdp! });\n this.#ackedChunksHistory = this.trimHistoryArrayToMaxEntries(this.#ackedChunksHistory);\n };\n\n private chunkUploadSucceededPartially = (eventArgs: FileChunkUploadCompletedPartiallyEventArgs) => {\n this.#ackedChunksHistory.push({ time: Date.now(), latencyInMs: eventArgs.latencyInMsIfUdp! });\n this.#ackedChunksHistory = this.trimHistoryArrayToMaxEntries(this.#ackedChunksHistory);\n };\n\n private chunkUploadFailed = (eventArgs: FileChunkUploadFailedEventArgs) => {\n const isFileAccessError = eventArgs.error.cause instanceof FsError;\n\n if (isFileAccessError)\n return;\n\n if (this.isMsgSizeError(eventArgs.error)) {\n this.#msgSizeErrorHandler();\n return;\n }\n\n if (this.isNoBufsError(eventArgs.error)) {\n this.#noBufsErrorHandler();\n return;\n }\n\n this.#failedChunksTimeHistory.push(Date.now());\n this.#failedChunksTimeHistory = this.trimHistoryArrayToMaxEntries(this.#failedChunksTimeHistory);\n };\n\n private isMsgSizeError(error: Error) {\n return this.isErrorContainingErrorCode(error, `EMSGSIZE`);\n }\n\n private isNoBufsError(error: Error) {\n return this.isErrorContainingErrorCode(error, `ENOBUFS`);\n }\n\n private isErrorContainingErrorCode(error: Error, errorCode: string): boolean {\n if (error.message.includes(errorCode))\n return true;\n\n if (error.cause)\n return this.isErrorContainingErrorCode(error.cause, errorCode);\n\n return false;\n }\n\n private trimHistoryArrayToMaxEntries<T>(history: T[]): T[] {\n if (history.length <= OPTIMIZER_HISTORY_TRIM_THRESHOLD)\n return history;\n\n return history.slice(history.length - MAX_OPTIMIZER_HISTORY_ENTRIES);\n }\n\n private optimize = async (): Promise<void> => {\n const optimizationResult = this.#udpOptimizationStrategy.getOptimizedValues(this.#startedChunksTimeHistory, this.#ackedChunksHistory, this.#failedChunksTimeHistory, this.#currentOptimizationValues!);\n\n this.#currentOptimizationValues = optimizationResult.optimizedValues;\n\n this.#concurrencyController!.maxConcurrency = this.#currentOptimizationValues.maxParallelChunksAmount;\n\n this.#timeout = setTimeout(() => this.optimize(), optimizationResult.optimizedValues.optimizationIntervalInMs);\n\n if (optimizationResult.clearChunksHistory === false)\n return;\n\n this.#startedChunksTimeHistory = [];\n this.#ackedChunksHistory = [];\n this.#failedChunksTimeHistory = [];\n };\n}"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transferUpload.d.ts","sourceRoot":"","sources":["../../../src/uploader/transferUpload.ts"],"names":[],"mappings":"AAMA,OAAO,cAAc,MAAM,kCAAkC,CAAC;AAC9D,OAAO,mBAAmB,MAAM,0BAA0B,CAAC;AAO3D,OAAO,KAAK,SAAS,MAAM,2BAA2B,CAAC;AAGvD,OAAO,KAAK,uBAAuB,MAAM,yCAAyC,CAAC;AACnF,OAAO,KAAK,WAAW,MAAM,oCAAoC,CAAC;AAElE,OAAO,KAAK,kBAAkB,MAAM,iCAAiC,CAAC;AACtE,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,uCAAuC,CAAC;AAEtF,OAAO,KAAK,YAAY,MAAM,iCAAiC,CAAC;AAChE,OAAO,KAAK,wBAAwB,MAAM,yCAAyC,CAAC;AACpF,OAAO,KAAK,8BAA8B,MAAM,+CAA+C,CAAC;AAGhG,OAAO,KAAK,mBAAmB,MAAM,oCAAoC,CAAC;AAC1E,OAAO,KAAK,gCAAgC,MAAM,iDAAiD,CAAC;AAGpG,OAAO,KAAK,yBAAyB,MAAM,0CAA0C,CAAC;AACtF,OAAO,KAAK,iCAAiC,MAAM,kDAAkD,CAAC;AACtG,OAAO,KAAK,kCAAkC,MAAM,mDAAmD,CAAC;AACxG,OAAO,KAAK,kCAAkC,MAAM,oEAAoE,CAAC;AACzH,OAAO,KAAK,oBAAoB,MAAM,mCAAmC,CAAC;AAC1E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAGxD,OAAO,KAAK,iCAAiC,MAAM,kDAAkD,CAAC;AAItG,OAAO,KAAK,eAAe,MAAM,gCAAgC,CAAC;AAClE,OAAO,KAAK,0CAA0C,MAAM,2DAA2D,CAAC;AACxH,OAAO,KAAK,iCAAiC,MAAM,kDAAkD,CAAC;AACtG,OAAO,KAAK,mCAAmC,MAAM,oDAAoD,CAAC;AAC1G,OAAO,KAAK,oBAAoB,MAAM,yCAAyC,CAAC;AAChF,OAAO,KAAK,EAAE,wBAAwB,EAAoC,MAAM,sCAAsC,CAAC;AAEvH,MAAM,CAAC,OAAO,OAAO,cAAc,CAAC,CAAC,SAAS,WAAW;;IAoBrD,kBAAkB,EAAE,CAAC,MAAM,IAAI,CAAC,GAAG,SAAS,CAAC;IAC7C,kBAAkB,EAAE,CAAC,MAAM,IAAI,CAAC,GAAG,SAAS,CAAC;IAO7C,IAAI,MAAM,IAAI,cAAc,CAE3B;IAED,IAAI,mBAAmB,IAAI,MAAM,CAEhC;IAED,IAAI,gBAAgB,IAAI,MAAM,CAE7B;IAED,IAAI,kBAAkB,IAAI,MAAM,CAE/B;IAED,IAAI,gBAAgB,IAAI,MAAM,CAE7B;IAED,IAAI,oBAAoB,IAAI,MAAM,CAKjC;IAED,IAAI,KAAK,IAAI,SAAS,QAAQ,CAAC,CAAC,CAAC,EAAE,CAElC;IAED,IAAI,gBAAgB,IAAI,MAAM,CAE7B;IAED,IAAI,UAAU,IAAI,MAAM,GAAG,SAAS,CAEnC;gBAEW,0BAA0B,EAAE,kCAAkC,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,SAAS,EAAE,uBAAuB,EAAE,uBAAuB,EAAE,YAAY,EAAE,YAAY,EAAE,IAAI,EAAE,kBAAkB,CAAC,CAAC,CAAC,GAAG,wBAAwB,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,oBAAoB,EAAE,SAAS,EAAE,eAAe,EAAE,YAAY,EAAE,oBAAoB;IAoB1U,OAAO,CAAC,cAAc;IAItB,OAAO,CAAC,kBAAkB;IAI1B,OAAO,CAAC,8BAA8B;IAehC,GAAG,CAAC,mBAAmB,EAAE,WAAW,EAAE,mBAAmB,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"transferUpload.d.ts","sourceRoot":"","sources":["../../../src/uploader/transferUpload.ts"],"names":[],"mappings":"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"}
|
|
@@ -114,7 +114,7 @@ export default class TransferUpload {
|
|
|
114
114
|
if (this.#isUdpUploadMode && !this.#transferMetadata.udpData.handshakeData)
|
|
115
115
|
await this.serverUdpHandshake();
|
|
116
116
|
this.#optimizer.start(this.#isUdpUploadMode, this.#serverLatencyInMs);
|
|
117
|
-
const ongoingChunkUploads =
|
|
117
|
+
const ongoingChunkUploads = new Set();
|
|
118
118
|
for (const file of this.files) {
|
|
119
119
|
const fileStatus = this.#transferState.getFile(file.externalId);
|
|
120
120
|
if (fileStatus.isCompleted)
|
|
@@ -131,15 +131,18 @@ export default class TransferUpload {
|
|
|
131
131
|
releaseSemaphore();
|
|
132
132
|
break;
|
|
133
133
|
}
|
|
134
|
-
const
|
|
135
|
-
|
|
134
|
+
const chunkUploadPromise = this.sendChunkAndKeepUpdatingState(file, chunk.startPosition, chunk.sizeInBytes, releaseSemaphore);
|
|
135
|
+
const trackedChunkUploadPromise = chunkUploadPromise.finally(() => {
|
|
136
|
+
ongoingChunkUploads.delete(trackedChunkUploadPromise);
|
|
137
|
+
});
|
|
138
|
+
ongoingChunkUploads.add(trackedChunkUploadPromise);
|
|
136
139
|
if (this.#transferState.status !== TransferStatus.Running)
|
|
137
140
|
break;
|
|
138
141
|
}
|
|
139
142
|
if (this.#transferState.status !== TransferStatus.Running)
|
|
140
143
|
break;
|
|
141
144
|
}
|
|
142
|
-
await promiseAllSettled(ongoingChunkUploads);
|
|
145
|
+
await promiseAllSettled(Array.from(ongoingChunkUploads));
|
|
143
146
|
this.#optimizer.stop();
|
|
144
147
|
if (this.#transferState.status === TransferStatus.Pausing)
|
|
145
148
|
this.#transferState.transferPaused();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transferUpload.js","sourceRoot":"","sources":["../../../src/uploader/transferUpload.ts"],"names":[],"mappings":"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","sourcesContent":["import sleep from 'abortable-sleep';\n\nimport ApiError from '../utils/api/apiError.js';\nimport FsError from '../utils/fileSystem/fsError.js';\nimport TransferUploadState from \"./state/transferUploadState.js\";\nimport TransferUploadError from \"./transferUploadError.js\";\nimport TransferStatus from \"../utils/types/transferStatus.js\";\nimport TransferUploadEvent from './transferUploadEvent.js';\nimport ChunksIterator from './chunksIterator/chunksIterator.js';\nimport mergeAbortAndPauseSignals from '../utils/mergeAbortAndPauseSignals.js';\nimport ApiFilemail449Error from '../utils/api/apiFilemail449Error.js';\nimport { promiseAllSettled } from '../utils/promiseAll.js';\nimport { concatUint8Arrays, hexToUint8Array, uint8ArrayToHex } from '../utils/uint8ArrayUtils.js';\n\nimport type ApiClient from \"../utils/api/apiClient.js\";\nimport type { InitializeTransferRequest } from \"../utils/api/dtos/initializeTransferRequest.js\";\nimport type SendFileChunkRequest from '../utils/api/dtos/sendFileChunkRequest.js';\nimport type FileServerClientFactory from '../utils/api/fileServerClientFactory.js';\nimport type FileDetails from \"../utils/fileSystem/fileDetails.js\";\nimport type TransferUploadMetadata from \"./export/transferUploadMetadata.js\";\nimport type TransferUploadInfo from \"./options/transferUploadInfo.js\";\nimport type { TransferUploadAppendInfo } from './options/transferUploadAppendInfo.js';\nimport type ResetTransferRequest from '../utils/api/dtos/resetTransferRequest.js';\nimport type EventsEngine from '../utils/events/eventsEngine.js';\nimport type FileChunkUploadEventArgs from './eventArgs/fileChunkUploadEventArgs.js';\nimport type FileChunkUploadFailedEventArgs from './eventArgs/fileChunkUploadFailedEventArgs.js';\nimport type ChunkProgressEvent from '../utils/events/chunkProgressEvent.js';\nimport type FinalizeTransferRequest from '../utils/api/dtos/finalizeTransferRequest.js';\nimport type FileUploadEventArgs from './eventArgs/fileUploadEventArgs.js';\nimport type TransferUploadCompletedEventArgs from './eventArgs/transferUploadCompletedEventArgs.js';\nimport type CancelTransferRequest from '../utils/api/dtos/cancelTransferRequest.js';\nimport type ConcurrencyReleaser from \"../utils/concurrencyController/concurrencyReleaser.js\";\nimport type FileUploadFailedEventArgs from './eventArgs/fileUploadFailedEventArgs.js';\nimport type TransferUploadProgressedEventArgs from './eventArgs/transferUploadProgressedEventArgs.js';\nimport type FileChunkUploadProgressedEventArgs from './eventArgs/fileChunkUploadProgressedEventArgs.js';\nimport type UploaderChunkStreamProviderFactory from './chunkStreamProviderFactory/uploaderChunkStreamProviderFactory.js';\nimport type TransferUploadConfig from './options/transferUploadConfig.js';\nimport type { PauseSignal } from './pauseController.js';\nimport type InitializeTransferResponse from '../utils/api/dtos/initializeTransferResponse.js';\nimport type { InitializeTransferResponseUdpData } from '../utils/api/dtos/initializeTransferResponse.js';\nimport type TransferUploadModeChosenEventArgs from './eventArgs/transferUploadModeChosenEventArgs.js';\nimport type HandshakeRequest from './api/dtos/handshakeRequest.js';\nimport type ChunkStreamProvider from '../utils/fileSystem/chunkStreamProvider.js';\nimport type SendChunkRequest from './api/dtos/sendChunkRequest.js';\nimport type UploadOptimizer from './optimizer/uploadOptimizer.js';\nimport type FileChunkUploadCompletedPartiallyEventArgs from './eventArgs/fileChunkUploadCompletedPartiallyEventArgs.js';\nimport type FileChunkUploadCompletedEventArgs from './eventArgs/fileChunkUploadCompletedEventArgs.js';\nimport type TransferMetadataDeterminedEventArgs from './eventArgs/transferMetadataDeterminedEventArgs.js';\nimport type CryptographyProvider from '../utils/crypto/cryptographyProvider.js';\nimport type { TransferUploadExportData, TransferUploadExportDataMetadata } from './export/transferUploadExportData.js';\n\nexport default class TransferUpload<T extends FileDetails> {\n #totalSizeInBytes: number;\n\n #chunkStreamProviderFactory: UploaderChunkStreamProviderFactory<T>;\n #apiClient: ApiClient;\n #fileServerClientFactory: FileServerClientFactory;\n #eventsEngine: EventsEngine;\n #info: TransferUploadInfo<T> | TransferUploadAppendInfo<T>;\n #config: TransferUploadConfig;\n #optimizer: UploadOptimizer;\n #cryptography: CryptographyProvider;\n\n #transferState?: TransferUploadState;\n #transferMetadata?: TransferUploadMetadata;\n #transferDownloadUrl?: string;\n\n #pauseSignal: PauseSignal | undefined;\n #abortSignal: AbortSignal | undefined;\n #mergedPauseAndAbortSignal: AbortSignal | undefined;\n\n pauseEventListener: (() => void) | undefined;\n abortEventListener: (() => void) | undefined;\n\n #isUdpUploadMode: boolean;\n #serverLatencyInMs: number | undefined;\n\n #isRunMethodRunning = false;\n\n get status(): TransferStatus {\n return this.#transferState?.status ?? TransferStatus.Initialized;\n }\n\n get completedFilesCount(): number {\n return this.#transferState?.completedFilesCount ?? 0;\n }\n\n get failedFilesCount(): number {\n return this.#transferState?.failedFilesCount ?? 0;\n }\n\n get uploadedBytesCount(): number {\n return this.#transferState?.uploadedBytesCount ?? 0;\n }\n\n get failedBytesCount(): number {\n return this.#transferState?.failedBytesCount ?? 0;\n }\n\n get progressInPercentage(): number {\n if (this.totalSizeInBytes === 0)\n return 0;\n\n return (this.uploadedBytesCount * 100) / this.totalSizeInBytes;\n }\n\n get files(): readonly Readonly<T>[] {\n return this.#info.files;\n }\n\n get totalSizeInBytes(): number {\n return this.#totalSizeInBytes;\n }\n\n get transferId(): string | undefined {\n return this.#transferMetadata?.transferId;\n }\n\n constructor(chunkStreamProviderFactory: UploaderChunkStreamProviderFactory<T>, apiClient: ApiClient, fileServerClientFactory: FileServerClientFactory, eventsEngine: EventsEngine, info: TransferUploadInfo<T> | TransferUploadAppendInfo<T>, config: TransferUploadConfig, optimizer: UploadOptimizer, cryptography: CryptographyProvider) {\n if (info.files.length === 0)\n throw new TransferUploadError(`Files can't be empty`);\n\n this.#totalSizeInBytes = info.files.reduce((partialSum, file) => partialSum + file.fileSizeInBytes, 0);\n this.#isUdpUploadMode = false;\n\n this.#chunkStreamProviderFactory = chunkStreamProviderFactory;\n this.#apiClient = apiClient;\n this.#fileServerClientFactory = fileServerClientFactory;\n this.#eventsEngine = eventsEngine;\n this.#info = info;\n this.#config = config;\n this.#optimizer = optimizer;\n this.#cryptography = cryptography;\n\n if (this.isUploadAppendInfo(this.#info))\n this.createTransferMetadataFromInfo(this.#info);\n }\n\n private isUploadAppend(): boolean {\n return this.isUploadAppendInfo(this.#info);\n }\n\n private isUploadAppendInfo(info: TransferUploadInfo<T> | TransferUploadAppendInfo<T>): info is TransferUploadAppendInfo<T> {\n return (info as TransferUploadAppendInfo<T>).transferKey !== undefined;\n }\n\n private createTransferMetadataFromInfo(info: TransferUploadAppendInfo<T>) {\n if (!this.isUploadAppendInfo(info))\n throw new TransferUploadError(`Options are not TransferUploadAppendOptions`);\n\n this.#transferDownloadUrl = info.transferDownloadUrl;\n\n this.#transferMetadata = {\n transferId: info.transferId,\n transferKey: info.transferKey,\n transferFileServerUrl: info.transferFileServerUrl,\n transferRegion: info.transferRegion,\n encryptionData: info.e2eeData,\n };\n }\n\n async run(transferPauseSignal: PauseSignal, transferAbortSignal: AbortSignal): Promise<void> {\n this.throwIfNotPossibleToRun(transferPauseSignal, transferAbortSignal);\n\n this.#isRunMethodRunning = true;\n\n try {\n this.#pauseSignal = transferPauseSignal;\n this.#abortSignal = transferAbortSignal;\n this.#mergedPauseAndAbortSignal = mergeAbortAndPauseSignals(transferPauseSignal, transferAbortSignal);\n\n if (!this.#transferState)\n this.#transferState = new TransferUploadState(this.files, this.#eventsEngine, this.#config.currentRatesTimespanInMs, this.#config.progressEventThrottlingInMs);\n else\n this.#transferState.recover();\n\n this.#transferState.transferRun();\n\n this.addPauseAndStopListeners();\n\n if (!this.#transferMetadata)\n await this.startApiTransferAndCreateMetadata();\n\n this.notifyMetadataDetermined();\n\n await this.pingServerAndChooseUploadMode();\n\n if (this.#isUdpUploadMode && !this.#transferMetadata!.udpData!.handshakeData)\n await this.serverUdpHandshake();\n\n this.#optimizer.start(this.#isUdpUploadMode, this.#serverLatencyInMs!);\n\n const ongoingChunkUploads: Promise<void>[] = [];\n\n for (const file of this.files) {\n const fileStatus = this.#transferState.getFile(file.externalId);\n\n if (fileStatus.isCompleted)\n continue;\n\n const alreadySentChunks = this.#transferState.getChunksForFile(file.externalId);\n const chunksIterator = new ChunksIterator(alreadySentChunks, file.fileSizeInBytes, this.#optimizer);\n\n for (const chunk of chunksIterator.getChunksIterator()) {\n // eslint-disable-next-line no-await-in-loop\n const releaseSemaphore = await this.#optimizer.semaphoreAcquire();\n\n if (this.#optimizer.currentSleepTimeInMs >= 1)\n // eslint-disable-next-line no-await-in-loop\n await sleep(this.#optimizer.currentSleepTimeInMs, this.#mergedPauseAndAbortSignal);\n\n if (this.#transferState!.status !== TransferStatus.Running) {\n releaseSemaphore();\n break;\n }\n\n const promise: Promise<void> = this.sendChunkAndKeepUpdatingState(file, chunk.startPosition, chunk.sizeInBytes, releaseSemaphore);\n\n ongoingChunkUploads.push(promise);\n\n if (this.#transferState!.status !== TransferStatus.Running)\n break;\n }\n\n if (this.#transferState!.status !== TransferStatus.Running)\n break;\n }\n\n await promiseAllSettled(ongoingChunkUploads);\n\n this.#optimizer.stop();\n\n if (this.#transferState.status === TransferStatus.Pausing)\n this.#transferState.transferPaused();\n else if (this.#transferState.status === TransferStatus.Aborting)\n this.#transferState.transferAborted();\n else if (this.uploadedBytesCount !== this.totalSizeInBytes)\n this.#transferState.transferFailed();\n else {\n await this.finalizeTransfer();\n this.#transferState.transferCompleted(this.#transferMetadata!, this.#transferDownloadUrl!);\n }\n }\n catch (error) {\n // We can get here with pausing or aborting status if any API call fails (e.g., finalizeTransfer) so we need to check the status again\n if (!this.#transferState)\n this.#eventsEngine.emit(TransferUploadEvent.TransferFailed);\n else if (this.#transferState.status === TransferStatus.Pausing) {\n this.#transferState.transferPaused();\n return;\n }\n else if (this.#transferState.status === TransferStatus.Aborting) {\n this.#transferState.transferAborted();\n return;\n }\n else\n this.#transferState.transferFailed();\n\n if (error instanceof TransferUploadError)\n throw error;\n else\n throw new TransferUploadError(`Unhandled error occured. See 'cause' for more details`, { cause: error as Error });\n }\n finally {\n this.removePauseAndStopListeners();\n this.#optimizer.stop();\n this.#isRunMethodRunning = false;\n }\n }\n\n private notifyMetadataDetermined() {\n if (!this.#transferMetadata)\n return;\n\n const eventArgs: TransferMetadataDeterminedEventArgs = {\n transferId: this.#transferMetadata.transferId,\n fileServerUrl: this.#transferMetadata.transferFileServerUrl,\n region: this.#transferMetadata.transferRegion,\n };\n\n this.#eventsEngine.emit(TransferUploadEvent.TransferMetadataDetermined, eventArgs);\n }\n\n private async pingServerAndChooseUploadMode(): Promise<void> {\n try {\n if (this.#config.turnOffUdp)\n throw new Error(`UDP is turned off`);\n\n const udpData = this.#transferMetadata?.udpData;\n\n if (!udpData)\n throw new Error(`No UDP data is available`);\n\n const requestTimeout = this.#config.forceUdp ? 3 * 1000 : this.getPingTimeout(udpData.threshold);\n const retryDelay = 1000;\n\n const udpClient = this.#fileServerClientFactory.createFileServerUdpUploadClient(udpData.ip, udpData.port, requestTimeout, this.#mergedPauseAndAbortSignal, undefined, retryDelay);\n\n await udpClient.connect();\n\n const pingResult = await udpClient.ping();\n\n udpClient.close().catch(() => { /* discard */ });\n\n this.#serverLatencyInMs = pingResult.latencyInMs;\n this.#isUdpUploadMode = pingResult.latencyInMs >= udpData.threshold;\n\n const eventArgs: TransferUploadModeChosenEventArgs = { isUdpMode: this.#isUdpUploadMode, latency: pingResult.latencyInMs };\n this.#eventsEngine.emit(TransferUploadEvent.TransferUploadModeChosen, eventArgs);\n }\n catch (error) {\n this.#isUdpUploadMode = false;\n\n const eventArgs: TransferUploadModeChosenEventArgs = { isUdpMode: this.#isUdpUploadMode, error: error as Error };\n this.#eventsEngine.emit(TransferUploadEvent.TransferUploadModeChosen, eventArgs);\n }\n }\n\n private getPingTimeout(udpPingThreshold: number) {\n const pingTimeout = Math.min(3 * 1000, udpPingThreshold * 20);\n return Math.max(500, pingTimeout);\n }\n\n private async serverUdpHandshake(): Promise<void> {\n const transferMetadata = this.#transferMetadata!;\n const udpData = transferMetadata.udpData!;\n\n const requestTimeout = this.getHandshakeTimeout();\n const retryDelay = 1000;\n\n const udpClient = this.#fileServerClientFactory.createFileServerUdpUploadClient(udpData.ip, udpData.port, requestTimeout, this.#mergedPauseAndAbortSignal, undefined, retryDelay);\n\n await udpClient.connect();\n\n const handshakeRequest: HandshakeRequest = { transferId: transferMetadata.transferId, transferKey: transferMetadata.transferKey };\n const handshakeResponse = await udpClient.handshake(handshakeRequest);\n\n udpClient.close().catch(() => { /* discard */ });\n\n this.#transferMetadata!.udpData!.handshakeData = handshakeResponse;\n }\n\n private getHandshakeTimeout() {\n const timeout = Math.min(this.#serverLatencyInMs! * 30, 30 * 1000);\n return Math.max(2000, timeout);\n }\n\n private async sendChunkAndKeepUpdatingState(file: T, chunkStartPosition: number, chunkSizeInBytes: number, releaseSemaphore: ConcurrencyReleaser): Promise<void> {\n let uploadedBytesCount = 0;\n\n try {\n this.#transferState!.chunkUploadStarted(file.externalId, chunkStartPosition, chunkSizeInBytes);\n\n const chunkStreamProvider = this.#chunkStreamProviderFactory.createChunkStreamProvider(file, chunkStartPosition, chunkSizeInBytes, this.#transferMetadata?.encryptionData);\n\n const progressEventHandler = (eventArgs: ChunkProgressEvent) => {\n uploadedBytesCount += eventArgs.transferredBytesSinceLastEvent;\n this.#transferState!.chunkUploadProgressed(file.externalId, chunkStartPosition, chunkSizeInBytes, eventArgs);\n };\n\n const response = await this.sendChunk(file, chunkStreamProvider, progressEventHandler);\n\n const latencyInMsIfUdp = this.#isUdpUploadMode ? (response as { latencyInMs: number }).latencyInMs : undefined;\n\n if (uploadedBytesCount === chunkSizeInBytes)\n this.#transferState!.chunkUploadCompleted(file.externalId, chunkStartPosition, chunkSizeInBytes, latencyInMsIfUdp);\n else\n this.#transferState!.chunkUploadCompletedPartially(file.externalId, chunkStartPosition, chunkSizeInBytes, uploadedBytesCount, this.#pauseSignal!.paused, latencyInMsIfUdp);\n }\n catch (error) {\n const chunkError = error as Error;\n\n const isTcpPausingError = chunkError.cause !== undefined\n && chunkError.cause instanceof ApiFilemail449Error\n && chunkError.cause.message === `Wrong md5 hash`\n && this.#pauseSignal?.paused === true;\n\n if (isTcpPausingError)\n this.#transferState!.chunkUploadCompletedPartially(file.externalId, chunkStartPosition, chunkSizeInBytes, uploadedBytesCount, this.#pauseSignal!.paused);\n else {\n const failedReason = this.getChunkFailedReason(error);\n this.#transferState!.chunkUploadFailed(file.externalId, chunkStartPosition, chunkSizeInBytes, uploadedBytesCount, failedReason, error as Error);\n }\n }\n finally {\n releaseSemaphore();\n }\n }\n\n private async sendChunk(file: T, chunkStreamProvider: ChunkStreamProvider, progressEventHandler: (eventArgs: ChunkProgressEvent) => void): Promise<{ latencyInMs: number } | void> {\n if (this.#isUdpUploadMode)\n return await this.sendChunkUsingUdp(file, chunkStreamProvider, progressEventHandler);\n\n return await this.sendChunkUsingTcp(file, chunkStreamProvider, progressEventHandler);\n }\n\n private async sendChunkUsingUdp(file: T, chunkStreamProvider: ChunkStreamProvider, progressEventHandler: (eventArgs: ChunkProgressEvent) => void): Promise<{ latencyInMs: number }> {\n const transferMetadata = this.#transferMetadata!;\n const udpData = transferMetadata.udpData!;\n\n const udpClient = this.#fileServerClientFactory.createFileServerUdpUploadClient(udpData.ip, udpData.port, this.#optimizer.currentRequestTimeoutInMs, this.#mergedPauseAndAbortSignal, 0);\n\n const sendChunkRequest: SendChunkRequest = {\n sessionGuid: this.#transferMetadata!.udpData!.handshakeData!.sessionGuid,\n aesKey: this.#transferMetadata!.udpData!.handshakeData!.aesKey,\n chunkStartPosition: chunkStreamProvider.chunkStartPosition,\n fileSizeInBytes: file.fileSizeInBytes,\n fileDestinationPathInTransfer: file.fileDestinationPathInTransfer,\n fileName: file.fileName,\n };\n\n await udpClient.connect();\n\n const result = await udpClient.sendChunk(sendChunkRequest, chunkStreamProvider);\n\n udpClient.close().catch(() => { /* discard */ });\n\n const chunkProgressEventArgs: ChunkProgressEvent = { transferredBytesTotal: chunkStreamProvider.chunkLengthInBytes, transferredBytesSinceLastEvent: chunkStreamProvider.chunkLengthInBytes };\n progressEventHandler(chunkProgressEventArgs);\n\n return result;\n }\n\n private async sendChunkUsingTcp(file: T, chunkStreamProvider: ChunkStreamProvider, progressEventHandler: (eventArgs: ChunkProgressEvent) => void): Promise<void> {\n const request: SendFileChunkRequest = {\n chunkLengthInBytes: chunkStreamProvider.chunkLengthInBytes,\n chunkStartPosition: chunkStreamProvider.chunkStartPosition,\n };\n\n const fileServerClient = this.#fileServerClientFactory.createFileServerTcpUploadClient(this.#transferMetadata!.transferFileServerUrl, this.#transferMetadata!.transferId, this.#transferMetadata!.transferKey, file.fileName, file.fileDestinationPathInTransfer, file.fileSizeInBytes);\n\n const ongoingRequestPromise = fileServerClient.sendFileChunk(request, chunkStreamProvider, this.#pauseSignal!, this.#abortSignal!);\n\n fileServerClient.addEventListener(`progress`, progressEventHandler);\n\n await ongoingRequestPromise;\n }\n\n private getChunkFailedReason(error: unknown) {\n if (error instanceof FsError)\n return `Can't read file. ${error.message}`;\n\n if (error instanceof ApiError)\n return error.cause?.message ? `${error.message}. ${error.cause.message}` : error.message;\n\n return (error as Error)?.message;\n }\n\n private throwIfNotPossibleToRun(pauseSignal: PauseSignal, abortSignal: AbortSignal) {\n if (this.#isRunMethodRunning)\n throw new TransferUploadError(`This transfer is running and cannot be run`);\n\n if (this.#transferState\n && this.#transferState.status !== TransferStatus.Failed\n && this.#transferState.status !== TransferStatus.Aborted\n && this.#transferState.status !== TransferStatus.Initialized\n && this.#transferState.status !== TransferStatus.Paused)\n throw new TransferUploadError(`Transfer is in ${TransferStatus[this.#transferState!.status]} state and cannot be run`);\n\n if (this.files.length === 0)\n throw new TransferUploadError(`There are no files passed to the transfer`);\n\n if (pauseSignal.paused)\n throw new TransferUploadError(`Can't run transfer with already paused PauseController`);\n\n if (abortSignal.aborted)\n throw new TransferUploadError(`Can't run transfer with already aborted AbortController`);\n }\n\n private addPauseAndStopListeners() {\n this.pauseEventListener = () => {\n if (this.#transferState!.status !== TransferStatus.Running)\n throw new TransferUploadError(`Transfer is in ${TransferStatus[this.#transferState!.status]} state and cannot be paused`);\n\n this.#transferState!.transferPauseRequested();\n };\n\n this.abortEventListener = () => {\n if (this.#transferState!.status !== TransferStatus.Running)\n throw new TransferUploadError(`Transfer is in ${TransferStatus[this.#transferState!.status]} state and cannot be stopped`);\n\n this.#transferState!.transferAbortRequested();\n };\n\n this.#pauseSignal!.addEventListener(`pause`, this.pauseEventListener);\n this.#abortSignal!.addEventListener(`abort`, this.abortEventListener);\n }\n\n private removePauseAndStopListeners() {\n this.#pauseSignal!.removeEventListener(`pause`, this.pauseEventListener!);\n this.#abortSignal!.removeEventListener(`abort`, this.abortEventListener!);\n }\n\n private async startApiTransferAndCreateMetadata() {\n if (this.isUploadAppendInfo(this.#info))\n throw new TransferUploadError(`Options are not TransferUploadOptions`);\n\n try {\n const encryptionDataAndIvSaltHex = await this.generateEncryptionDataAndIvSaltHmacHex(this.#info.e2eeKey);\n\n const request: InitializeTransferRequest = {\n e2ee: Boolean(encryptionDataAndIvSaltHex),\n e2ee_keyhash: encryptionDataAndIvSaltHex?.ivSaltHmacHex,\n transfersize: this.totalSizeInBytes,\n to: this.#info.to,\n from: this.#info.from,\n subject: this.#info.subject,\n message: this.#info.message,\n notify: this.#info.notify,\n confirmation: this.#info.confirmation,\n days: this.#info.days,\n password: this.#info.uploadPassword,\n companyid: this.#info.companyId,\n incominglogintoken: this.#info.incomingLoginToken,\n incomingpageid: this.#info.incomingPageId,\n filerequestid: this.#info.fileRequestId,\n filerequestshareid: this.#info.fileRequestShareId,\n customfields: this.#info.customFields,\n };\n\n const response = await this.#apiClient.initializeTransfer(request, this.#mergedPauseAndAbortSignal);\n\n this.#transferMetadata = {\n transferId: response.transferId,\n transferKey: response.transferKey,\n transferFileServerUrl: response.transferUrl,\n transferRegion: response.transferRegion,\n encryptionData: encryptionDataAndIvSaltHex?.encryptionData,\n udpData: this.getResponseOrForcedUdpData(response),\n };\n }\n catch (error) {\n throw new TransferUploadError(`Error initializing transfer through the API`, { cause: error as Error });\n }\n }\n\n private async generateEncryptionDataAndIvSaltHmacHex(e2eeKey?: string): Promise<{ encryptionData: { iv: Uint8Array, key: Uint8Array }, ivSaltHmacHex: string, salt: Uint8Array, hmac: Uint8Array } | undefined> {\n if (!e2eeKey)\n return undefined;\n\n const salt = this.#cryptography.generateRandomBytes(16);\n const key = await this.#cryptography.deriveKey(e2eeKey, salt);\n const hmac = await this.#cryptography.generateHmac(key);\n const iv = this.#cryptography.generateRandomBytes(16);\n\n const ivSaltHmac = concatUint8Arrays([iv, salt, hmac]);\n const ivSaltHmacHex = uint8ArrayToHex(ivSaltHmac);\n\n return {\n encryptionData: { iv, key },\n hmac,\n salt,\n ivSaltHmacHex,\n };\n }\n\n private getResponseOrForcedUdpData(response: InitializeTransferResponse): InitializeTransferResponseUdpData | undefined {\n if (!this.#config.forceUdp || !response.udp)\n return response.udp;\n\n return {\n ...response.udp,\n threshold: 0,\n };\n }\n\n private async finalizeTransfer(): Promise<void> {\n this.#eventsEngine.emit(TransferUploadEvent.TransferFinalizing);\n\n if (this.isUploadAppend())\n await this.resetApiTransfer();\n else\n await this.finalizeApiTransfer();\n }\n\n private async resetApiTransfer(): Promise<void> {\n try {\n const request: ResetTransferRequest = {\n transferid: this.#transferMetadata!.transferId,\n };\n\n await this.#apiClient.resetTransfer(request, this.#mergedPauseAndAbortSignal);\n }\n catch (error) {\n throw new TransferUploadError(`Error resetting transfer through the API`, { cause: error as Error });\n }\n }\n\n private async finalizeApiTransfer(): Promise<void> {\n try {\n const request: FinalizeTransferRequest = {\n transferid: this.#transferMetadata!.transferId,\n transferkey: this.#transferMetadata!.transferKey,\n protocol: this.#isUdpUploadMode ? `udp` : `tcp`,\n };\n\n const response = await this.#apiClient.finalizeTransfer(request, this.#mergedPauseAndAbortSignal);\n\n this.#transferDownloadUrl = response.downloadUrl;\n }\n catch (error) {\n throw new TransferUploadError(`Error finalizing transfer through the API`, { cause: error as Error });\n }\n }\n\n async cancel(abortSignal?: AbortSignal): Promise<void> {\n try {\n const isTransferApiInitialized = Boolean(this.#transferState) && Boolean(this.#transferMetadata);\n\n if (!isTransferApiInitialized) {\n this.emitCancelEvents();\n return;\n }\n\n this.throwIfInWrongStateToCancel();\n\n this.#transferState!.transferCancelRequested();\n\n if (this.isUploadAppend()) {\n // There is no possibility to cancel transfer upload append on API for now\n }\n else {\n try {\n await this.cancelApiTransfer(abortSignal);\n }\n catch {\n // If API cancel fails we still finalize local transfer state as canceled to avoid hanging in Canceling.\n }\n }\n\n this.#transferState!.transferCanceled();\n }\n catch (error) {\n if (error instanceof TransferUploadError)\n throw error;\n else\n throw new TransferUploadError(`Unhandled error occured. See 'cause' for more details`, { cause: error as Error });\n }\n }\n\n private emitCancelEvents() {\n this.#eventsEngine.emit(TransferUploadEvent.TransferCancelRequested);\n this.#eventsEngine.emit(TransferUploadEvent.TransferCanceled);\n }\n\n private throwIfInWrongStateToCancel() {\n if (!this.#transferState)\n return;\n\n if (this.#transferState.status !== TransferStatus.Failed\n && this.#transferState.status !== TransferStatus.Aborted\n && this.#transferState.status !== TransferStatus.Initialized\n && this.#transferState.status !== TransferStatus.Paused)\n throw new TransferUploadError(`Transfer is in ${TransferStatus[this.#transferState!.status]} state and cannot be canceled`);\n }\n\n private async cancelApiTransfer(abortSignal?: AbortSignal): Promise<void> {\n try {\n const request: CancelTransferRequest = {\n transferid: this.#transferMetadata!.transferId,\n transferkey: this.#transferMetadata!.transferKey,\n };\n\n await this.#apiClient.cancelTransfer(request, abortSignal);\n }\n catch (error) {\n throw new TransferUploadError(`Error canceling transfer through the API`, { cause: error as Error });\n }\n }\n\n addEventListener(eventName: TransferUploadEvent.TransferRun | TransferUploadEvent.TransferPauseRequested | TransferUploadEvent.TransferPaused | TransferUploadEvent.TransferAbortRequested | TransferUploadEvent.TransferAborted | TransferUploadEvent.TransferCancelRequested | TransferUploadEvent.TransferCanceled | TransferUploadEvent.TransferFailed, handler: () => void): void\n addEventListener(eventName: TransferUploadEvent.FileUploadStarted | TransferUploadEvent.FileUploadCompleted, handler: (event: FileUploadEventArgs) => void): void\n addEventListener(eventName: TransferUploadEvent.FileUploadFailed, handler: (event: FileUploadFailedEventArgs) => void): void\n addEventListener(eventName: TransferUploadEvent.FileChunkUploadProgressed, handler: (event: FileChunkUploadProgressedEventArgs) => void): void\n addEventListener(eventName: TransferUploadEvent.FileChunkUploadStarted, handler: (event: FileChunkUploadEventArgs) => void): void\n addEventListener(eventName: TransferUploadEvent.FileChunkUploadCompleted, handler: (event: FileChunkUploadCompletedEventArgs) => void): void\n addEventListener(eventName: TransferUploadEvent.FileChunkUploadCompletedPartially, handler: (event: FileChunkUploadCompletedPartiallyEventArgs) => void): void\n addEventListener(eventName: TransferUploadEvent.FileChunkUploadFailed, handler: (event: FileChunkUploadFailedEventArgs) => void): void\n addEventListener(eventName: TransferUploadEvent.TransferProgressed, handler: (event: TransferUploadProgressedEventArgs) => void): void\n addEventListener(eventName: TransferUploadEvent.TransferCompleted, handler: (event: TransferUploadCompletedEventArgs) => void): void\n addEventListener(eventName: TransferUploadEvent.TransferUploadModeChosen, handler: (event: TransferUploadModeChosenEventArgs) => void): void\n addEventListener(eventName: TransferUploadEvent.TransferMetadataDetermined, handler: (event: TransferMetadataDeterminedEventArgs) => void): void\n addEventListener(eventName: string, handler: (arg?: any) => void): void\n addEventListener(eventName: string, handler: (arg?: any) => void): void {\n this.#eventsEngine.addEventListener(eventName, handler);\n }\n\n exportAsString(): string {\n const exportData = this.export();\n return JSON.stringify(exportData);\n }\n\n export(): TransferUploadExportData<T> {\n if (!this.#transferState?.files)\n throw new TransferUploadError(`Can't export not started Transfer`); // fileStatuses are not created yet and it really doesn't make any sens to export not started transfer\n\n return {\n transferMetadata: this.getTransferMetadataExportValue(),\n info: this.#info,\n state: this.#transferState.export(),\n };\n }\n\n private getTransferMetadataExportValue(): TransferUploadExportDataMetadata | undefined {\n if (!this.#transferMetadata)\n return undefined;\n\n const { encryptionData, ...rest } = this.#transferMetadata;\n\n return {\n ...rest,\n encryptionData: !encryptionData ? undefined : {\n ivHex: uint8ArrayToHex(encryptionData.iv),\n keyHex: uint8ArrayToHex(encryptionData.key),\n },\n };\n }\n\n static recreate<T extends FileDetails>(transferExportData: TransferUploadExportData<T>, config: TransferUploadConfig, chunkStreamProviderFactory: UploaderChunkStreamProviderFactory<T>, apiClient: ApiClient, fileServerClientFactory: FileServerClientFactory, eventsEngine: EventsEngine, optimizer: UploadOptimizer, cryptography: CryptographyProvider): TransferUpload<T> {\n try {\n TransferUpload.validateRecreateParams(transferExportData);\n\n const transfer = new TransferUpload<T>(chunkStreamProviderFactory, apiClient, fileServerClientFactory, eventsEngine, transferExportData.info, config, optimizer, cryptography);\n\n transfer.#transferMetadata = this.recreateTransferMetadata(transferExportData.transferMetadata);\n transfer.#transferState = new TransferUploadState(transferExportData.info.files, eventsEngine, config.currentRatesTimespanInMs, config.progressEventThrottlingInMs, transferExportData.state);\n\n return transfer;\n }\n catch (error) {\n if (error instanceof TransferUploadError)\n throw error;\n else\n throw new TransferUploadError(`Unhandled error occured. See 'cause' for more details`, { cause: error as Error });\n }\n }\n\n private static recreateTransferMetadata(transferMetadata?: TransferUploadExportDataMetadata): TransferUploadMetadata | undefined {\n if (!transferMetadata)\n return undefined;\n\n const { encryptionData, ...rest } = transferMetadata;\n\n return {\n ...rest,\n encryptionData: !encryptionData ? undefined : {\n iv: hexToUint8Array(encryptionData.ivHex),\n key: hexToUint8Array(encryptionData.keyHex),\n },\n };\n }\n\n private static validateRecreateParams<T extends FileDetails>(transferExportData: TransferUploadExportData<T>) {\n if (!transferExportData.info)\n throw new TransferUploadError(`Info must be defined`);\n\n if (!transferExportData.state)\n throw new TransferUploadError(`State must be defined`);\n\n if (transferExportData.transferMetadata && (!transferExportData.transferMetadata.transferId || !transferExportData.transferMetadata.transferKey || !transferExportData.transferMetadata.transferFileServerUrl))\n throw new TransferUploadError(`Not all transfer metadata properties are defined`);\n\n if (transferExportData.transferMetadata?.encryptionData) {\n if (transferExportData.transferMetadata.encryptionData.ivHex.length !== 32)\n throw new TransferUploadError(`Encryption IV must be 16 bytes long`);\n if (transferExportData.transferMetadata.encryptionData.keyHex.length !== 64)\n throw new TransferUploadError(`Encryption key must be 32 bytes long`);\n }\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"transferUpload.js","sourceRoot":"","sources":["../../../src/uploader/transferUpload.ts"],"names":[],"mappings":"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","sourcesContent":["import sleep from 'abortable-sleep';\n\nimport ApiError from '../utils/api/apiError.js';\nimport FsError from '../utils/fileSystem/fsError.js';\nimport TransferUploadState from \"./state/transferUploadState.js\";\nimport TransferUploadError from \"./transferUploadError.js\";\nimport TransferStatus from \"../utils/types/transferStatus.js\";\nimport TransferUploadEvent from './transferUploadEvent.js';\nimport ChunksIterator from './chunksIterator/chunksIterator.js';\nimport mergeAbortAndPauseSignals from '../utils/mergeAbortAndPauseSignals.js';\nimport ApiFilemail449Error from '../utils/api/apiFilemail449Error.js';\nimport { promiseAllSettled } from '../utils/promiseAll.js';\nimport { concatUint8Arrays, hexToUint8Array, uint8ArrayToHex } from '../utils/uint8ArrayUtils.js';\n\nimport type ApiClient from \"../utils/api/apiClient.js\";\nimport type { InitializeTransferRequest } from \"../utils/api/dtos/initializeTransferRequest.js\";\nimport type SendFileChunkRequest from '../utils/api/dtos/sendFileChunkRequest.js';\nimport type FileServerClientFactory from '../utils/api/fileServerClientFactory.js';\nimport type FileDetails from \"../utils/fileSystem/fileDetails.js\";\nimport type TransferUploadMetadata from \"./export/transferUploadMetadata.js\";\nimport type TransferUploadInfo from \"./options/transferUploadInfo.js\";\nimport type { TransferUploadAppendInfo } from './options/transferUploadAppendInfo.js';\nimport type ResetTransferRequest from '../utils/api/dtos/resetTransferRequest.js';\nimport type EventsEngine from '../utils/events/eventsEngine.js';\nimport type FileChunkUploadEventArgs from './eventArgs/fileChunkUploadEventArgs.js';\nimport type FileChunkUploadFailedEventArgs from './eventArgs/fileChunkUploadFailedEventArgs.js';\nimport type ChunkProgressEvent from '../utils/events/chunkProgressEvent.js';\nimport type FinalizeTransferRequest from '../utils/api/dtos/finalizeTransferRequest.js';\nimport type FileUploadEventArgs from './eventArgs/fileUploadEventArgs.js';\nimport type TransferUploadCompletedEventArgs from './eventArgs/transferUploadCompletedEventArgs.js';\nimport type CancelTransferRequest from '../utils/api/dtos/cancelTransferRequest.js';\nimport type ConcurrencyReleaser from \"../utils/concurrencyController/concurrencyReleaser.js\";\nimport type FileUploadFailedEventArgs from './eventArgs/fileUploadFailedEventArgs.js';\nimport type TransferUploadProgressedEventArgs from './eventArgs/transferUploadProgressedEventArgs.js';\nimport type FileChunkUploadProgressedEventArgs from './eventArgs/fileChunkUploadProgressedEventArgs.js';\nimport type UploaderChunkStreamProviderFactory from './chunkStreamProviderFactory/uploaderChunkStreamProviderFactory.js';\nimport type TransferUploadConfig from './options/transferUploadConfig.js';\nimport type { PauseSignal } from './pauseController.js';\nimport type InitializeTransferResponse from '../utils/api/dtos/initializeTransferResponse.js';\nimport type { InitializeTransferResponseUdpData } from '../utils/api/dtos/initializeTransferResponse.js';\nimport type TransferUploadModeChosenEventArgs from './eventArgs/transferUploadModeChosenEventArgs.js';\nimport type HandshakeRequest from './api/dtos/handshakeRequest.js';\nimport type ChunkStreamProvider from '../utils/fileSystem/chunkStreamProvider.js';\nimport type SendChunkRequest from './api/dtos/sendChunkRequest.js';\nimport type UploadOptimizer from './optimizer/uploadOptimizer.js';\nimport type FileChunkUploadCompletedPartiallyEventArgs from './eventArgs/fileChunkUploadCompletedPartiallyEventArgs.js';\nimport type FileChunkUploadCompletedEventArgs from './eventArgs/fileChunkUploadCompletedEventArgs.js';\nimport type TransferMetadataDeterminedEventArgs from './eventArgs/transferMetadataDeterminedEventArgs.js';\nimport type CryptographyProvider from '../utils/crypto/cryptographyProvider.js';\nimport type { TransferUploadExportData, TransferUploadExportDataMetadata } from './export/transferUploadExportData.js';\n\nexport default class TransferUpload<T extends FileDetails> {\n #totalSizeInBytes: number;\n\n #chunkStreamProviderFactory: UploaderChunkStreamProviderFactory<T>;\n #apiClient: ApiClient;\n #fileServerClientFactory: FileServerClientFactory;\n #eventsEngine: EventsEngine;\n #info: TransferUploadInfo<T> | TransferUploadAppendInfo<T>;\n #config: TransferUploadConfig;\n #optimizer: UploadOptimizer;\n #cryptography: CryptographyProvider;\n\n #transferState?: TransferUploadState;\n #transferMetadata?: TransferUploadMetadata;\n #transferDownloadUrl?: string;\n\n #pauseSignal: PauseSignal | undefined;\n #abortSignal: AbortSignal | undefined;\n #mergedPauseAndAbortSignal: AbortSignal | undefined;\n\n pauseEventListener: (() => void) | undefined;\n abortEventListener: (() => void) | undefined;\n\n #isUdpUploadMode: boolean;\n #serverLatencyInMs: number | undefined;\n\n #isRunMethodRunning = false;\n\n get status(): TransferStatus {\n return this.#transferState?.status ?? TransferStatus.Initialized;\n }\n\n get completedFilesCount(): number {\n return this.#transferState?.completedFilesCount ?? 0;\n }\n\n get failedFilesCount(): number {\n return this.#transferState?.failedFilesCount ?? 0;\n }\n\n get uploadedBytesCount(): number {\n return this.#transferState?.uploadedBytesCount ?? 0;\n }\n\n get failedBytesCount(): number {\n return this.#transferState?.failedBytesCount ?? 0;\n }\n\n get progressInPercentage(): number {\n if (this.totalSizeInBytes === 0)\n return 0;\n\n return (this.uploadedBytesCount * 100) / this.totalSizeInBytes;\n }\n\n get files(): readonly Readonly<T>[] {\n return this.#info.files;\n }\n\n get totalSizeInBytes(): number {\n return this.#totalSizeInBytes;\n }\n\n get transferId(): string | undefined {\n return this.#transferMetadata?.transferId;\n }\n\n constructor(chunkStreamProviderFactory: UploaderChunkStreamProviderFactory<T>, apiClient: ApiClient, fileServerClientFactory: FileServerClientFactory, eventsEngine: EventsEngine, info: TransferUploadInfo<T> | TransferUploadAppendInfo<T>, config: TransferUploadConfig, optimizer: UploadOptimizer, cryptography: CryptographyProvider) {\n if (info.files.length === 0)\n throw new TransferUploadError(`Files can't be empty`);\n\n this.#totalSizeInBytes = info.files.reduce((partialSum, file) => partialSum + file.fileSizeInBytes, 0);\n this.#isUdpUploadMode = false;\n\n this.#chunkStreamProviderFactory = chunkStreamProviderFactory;\n this.#apiClient = apiClient;\n this.#fileServerClientFactory = fileServerClientFactory;\n this.#eventsEngine = eventsEngine;\n this.#info = info;\n this.#config = config;\n this.#optimizer = optimizer;\n this.#cryptography = cryptography;\n\n if (this.isUploadAppendInfo(this.#info))\n this.createTransferMetadataFromInfo(this.#info);\n }\n\n private isUploadAppend(): boolean {\n return this.isUploadAppendInfo(this.#info);\n }\n\n private isUploadAppendInfo(info: TransferUploadInfo<T> | TransferUploadAppendInfo<T>): info is TransferUploadAppendInfo<T> {\n return (info as TransferUploadAppendInfo<T>).transferKey !== undefined;\n }\n\n private createTransferMetadataFromInfo(info: TransferUploadAppendInfo<T>) {\n if (!this.isUploadAppendInfo(info))\n throw new TransferUploadError(`Options are not TransferUploadAppendOptions`);\n\n this.#transferDownloadUrl = info.transferDownloadUrl;\n\n this.#transferMetadata = {\n transferId: info.transferId,\n transferKey: info.transferKey,\n transferFileServerUrl: info.transferFileServerUrl,\n transferRegion: info.transferRegion,\n encryptionData: info.e2eeData,\n };\n }\n\n async run(transferPauseSignal: PauseSignal, transferAbortSignal: AbortSignal): Promise<void> {\n this.throwIfNotPossibleToRun(transferPauseSignal, transferAbortSignal);\n\n this.#isRunMethodRunning = true;\n\n try {\n this.#pauseSignal = transferPauseSignal;\n this.#abortSignal = transferAbortSignal;\n this.#mergedPauseAndAbortSignal = mergeAbortAndPauseSignals(transferPauseSignal, transferAbortSignal);\n\n if (!this.#transferState)\n this.#transferState = new TransferUploadState(this.files, this.#eventsEngine, this.#config.currentRatesTimespanInMs, this.#config.progressEventThrottlingInMs);\n else\n this.#transferState.recover();\n\n this.#transferState.transferRun();\n\n this.addPauseAndStopListeners();\n\n if (!this.#transferMetadata)\n await this.startApiTransferAndCreateMetadata();\n\n this.notifyMetadataDetermined();\n\n await this.pingServerAndChooseUploadMode();\n\n if (this.#isUdpUploadMode && !this.#transferMetadata!.udpData!.handshakeData)\n await this.serverUdpHandshake();\n\n this.#optimizer.start(this.#isUdpUploadMode, this.#serverLatencyInMs!);\n\n const ongoingChunkUploads = new Set<Promise<void>>();\n\n for (const file of this.files) {\n const fileStatus = this.#transferState.getFile(file.externalId);\n\n if (fileStatus.isCompleted)\n continue;\n\n const alreadySentChunks = this.#transferState.getChunksForFile(file.externalId);\n const chunksIterator = new ChunksIterator(alreadySentChunks, file.fileSizeInBytes, this.#optimizer);\n\n for (const chunk of chunksIterator.getChunksIterator()) {\n // eslint-disable-next-line no-await-in-loop\n const releaseSemaphore = await this.#optimizer.semaphoreAcquire();\n\n if (this.#optimizer.currentSleepTimeInMs >= 1)\n // eslint-disable-next-line no-await-in-loop\n await sleep(this.#optimizer.currentSleepTimeInMs, this.#mergedPauseAndAbortSignal);\n\n if (this.#transferState!.status !== TransferStatus.Running) {\n releaseSemaphore();\n break;\n }\n\n const chunkUploadPromise = this.sendChunkAndKeepUpdatingState(file, chunk.startPosition, chunk.sizeInBytes, releaseSemaphore);\n\n const trackedChunkUploadPromise = chunkUploadPromise.finally(() => {\n ongoingChunkUploads.delete(trackedChunkUploadPromise);\n });\n\n ongoingChunkUploads.add(trackedChunkUploadPromise);\n\n if (this.#transferState!.status !== TransferStatus.Running)\n break;\n }\n\n if (this.#transferState!.status !== TransferStatus.Running)\n break;\n }\n\n await promiseAllSettled(Array.from(ongoingChunkUploads));\n\n this.#optimizer.stop();\n\n if (this.#transferState.status === TransferStatus.Pausing)\n this.#transferState.transferPaused();\n else if (this.#transferState.status === TransferStatus.Aborting)\n this.#transferState.transferAborted();\n else if (this.uploadedBytesCount !== this.totalSizeInBytes)\n this.#transferState.transferFailed();\n else {\n await this.finalizeTransfer();\n this.#transferState.transferCompleted(this.#transferMetadata!, this.#transferDownloadUrl!);\n }\n }\n catch (error) {\n // We can get here with pausing or aborting status if any API call fails (e.g., finalizeTransfer) so we need to check the status again\n if (!this.#transferState)\n this.#eventsEngine.emit(TransferUploadEvent.TransferFailed);\n else if (this.#transferState.status === TransferStatus.Pausing) {\n this.#transferState.transferPaused();\n return;\n }\n else if (this.#transferState.status === TransferStatus.Aborting) {\n this.#transferState.transferAborted();\n return;\n }\n else\n this.#transferState.transferFailed();\n\n if (error instanceof TransferUploadError)\n throw error;\n else\n throw new TransferUploadError(`Unhandled error occured. See 'cause' for more details`, { cause: error as Error });\n }\n finally {\n this.removePauseAndStopListeners();\n this.#optimizer.stop();\n this.#isRunMethodRunning = false;\n }\n }\n\n private notifyMetadataDetermined() {\n if (!this.#transferMetadata)\n return;\n\n const eventArgs: TransferMetadataDeterminedEventArgs = {\n transferId: this.#transferMetadata.transferId,\n fileServerUrl: this.#transferMetadata.transferFileServerUrl,\n region: this.#transferMetadata.transferRegion,\n };\n\n this.#eventsEngine.emit(TransferUploadEvent.TransferMetadataDetermined, eventArgs);\n }\n\n private async pingServerAndChooseUploadMode(): Promise<void> {\n try {\n if (this.#config.turnOffUdp)\n throw new Error(`UDP is turned off`);\n\n const udpData = this.#transferMetadata?.udpData;\n\n if (!udpData)\n throw new Error(`No UDP data is available`);\n\n const requestTimeout = this.#config.forceUdp ? 3 * 1000 : this.getPingTimeout(udpData.threshold);\n const retryDelay = 1000;\n\n const udpClient = this.#fileServerClientFactory.createFileServerUdpUploadClient(udpData.ip, udpData.port, requestTimeout, this.#mergedPauseAndAbortSignal, undefined, retryDelay);\n\n await udpClient.connect();\n\n const pingResult = await udpClient.ping();\n\n udpClient.close().catch(() => { /* discard */ });\n\n this.#serverLatencyInMs = pingResult.latencyInMs;\n this.#isUdpUploadMode = pingResult.latencyInMs >= udpData.threshold;\n\n const eventArgs: TransferUploadModeChosenEventArgs = { isUdpMode: this.#isUdpUploadMode, latency: pingResult.latencyInMs };\n this.#eventsEngine.emit(TransferUploadEvent.TransferUploadModeChosen, eventArgs);\n }\n catch (error) {\n this.#isUdpUploadMode = false;\n\n const eventArgs: TransferUploadModeChosenEventArgs = { isUdpMode: this.#isUdpUploadMode, error: error as Error };\n this.#eventsEngine.emit(TransferUploadEvent.TransferUploadModeChosen, eventArgs);\n }\n }\n\n private getPingTimeout(udpPingThreshold: number) {\n const pingTimeout = Math.min(3 * 1000, udpPingThreshold * 20);\n return Math.max(500, pingTimeout);\n }\n\n private async serverUdpHandshake(): Promise<void> {\n const transferMetadata = this.#transferMetadata!;\n const udpData = transferMetadata.udpData!;\n\n const requestTimeout = this.getHandshakeTimeout();\n const retryDelay = 1000;\n\n const udpClient = this.#fileServerClientFactory.createFileServerUdpUploadClient(udpData.ip, udpData.port, requestTimeout, this.#mergedPauseAndAbortSignal, undefined, retryDelay);\n\n await udpClient.connect();\n\n const handshakeRequest: HandshakeRequest = { transferId: transferMetadata.transferId, transferKey: transferMetadata.transferKey };\n const handshakeResponse = await udpClient.handshake(handshakeRequest);\n\n udpClient.close().catch(() => { /* discard */ });\n\n this.#transferMetadata!.udpData!.handshakeData = handshakeResponse;\n }\n\n private getHandshakeTimeout() {\n const timeout = Math.min(this.#serverLatencyInMs! * 30, 30 * 1000);\n return Math.max(2000, timeout);\n }\n\n private async sendChunkAndKeepUpdatingState(file: T, chunkStartPosition: number, chunkSizeInBytes: number, releaseSemaphore: ConcurrencyReleaser): Promise<void> {\n let uploadedBytesCount = 0;\n\n try {\n this.#transferState!.chunkUploadStarted(file.externalId, chunkStartPosition, chunkSizeInBytes);\n\n const chunkStreamProvider = this.#chunkStreamProviderFactory.createChunkStreamProvider(file, chunkStartPosition, chunkSizeInBytes, this.#transferMetadata?.encryptionData);\n\n const progressEventHandler = (eventArgs: ChunkProgressEvent) => {\n uploadedBytesCount += eventArgs.transferredBytesSinceLastEvent;\n this.#transferState!.chunkUploadProgressed(file.externalId, chunkStartPosition, chunkSizeInBytes, eventArgs);\n };\n\n const response = await this.sendChunk(file, chunkStreamProvider, progressEventHandler);\n\n const latencyInMsIfUdp = this.#isUdpUploadMode ? (response as { latencyInMs: number }).latencyInMs : undefined;\n\n if (uploadedBytesCount === chunkSizeInBytes)\n this.#transferState!.chunkUploadCompleted(file.externalId, chunkStartPosition, chunkSizeInBytes, latencyInMsIfUdp);\n else\n this.#transferState!.chunkUploadCompletedPartially(file.externalId, chunkStartPosition, chunkSizeInBytes, uploadedBytesCount, this.#pauseSignal!.paused, latencyInMsIfUdp);\n }\n catch (error) {\n const chunkError = error as Error;\n\n const isTcpPausingError = chunkError.cause !== undefined\n && chunkError.cause instanceof ApiFilemail449Error\n && chunkError.cause.message === `Wrong md5 hash`\n && this.#pauseSignal?.paused === true;\n\n if (isTcpPausingError)\n this.#transferState!.chunkUploadCompletedPartially(file.externalId, chunkStartPosition, chunkSizeInBytes, uploadedBytesCount, this.#pauseSignal!.paused);\n else {\n const failedReason = this.getChunkFailedReason(error);\n this.#transferState!.chunkUploadFailed(file.externalId, chunkStartPosition, chunkSizeInBytes, uploadedBytesCount, failedReason, error as Error);\n }\n }\n finally {\n releaseSemaphore();\n }\n }\n\n private async sendChunk(file: T, chunkStreamProvider: ChunkStreamProvider, progressEventHandler: (eventArgs: ChunkProgressEvent) => void): Promise<{ latencyInMs: number } | void> {\n if (this.#isUdpUploadMode)\n return await this.sendChunkUsingUdp(file, chunkStreamProvider, progressEventHandler);\n\n return await this.sendChunkUsingTcp(file, chunkStreamProvider, progressEventHandler);\n }\n\n private async sendChunkUsingUdp(file: T, chunkStreamProvider: ChunkStreamProvider, progressEventHandler: (eventArgs: ChunkProgressEvent) => void): Promise<{ latencyInMs: number }> {\n const transferMetadata = this.#transferMetadata!;\n const udpData = transferMetadata.udpData!;\n\n const udpClient = this.#fileServerClientFactory.createFileServerUdpUploadClient(udpData.ip, udpData.port, this.#optimizer.currentRequestTimeoutInMs, this.#mergedPauseAndAbortSignal, 0);\n\n const sendChunkRequest: SendChunkRequest = {\n sessionGuid: this.#transferMetadata!.udpData!.handshakeData!.sessionGuid,\n aesKey: this.#transferMetadata!.udpData!.handshakeData!.aesKey,\n chunkStartPosition: chunkStreamProvider.chunkStartPosition,\n fileSizeInBytes: file.fileSizeInBytes,\n fileDestinationPathInTransfer: file.fileDestinationPathInTransfer,\n fileName: file.fileName,\n };\n\n await udpClient.connect();\n\n const result = await udpClient.sendChunk(sendChunkRequest, chunkStreamProvider);\n\n udpClient.close().catch(() => { /* discard */ });\n\n const chunkProgressEventArgs: ChunkProgressEvent = { transferredBytesTotal: chunkStreamProvider.chunkLengthInBytes, transferredBytesSinceLastEvent: chunkStreamProvider.chunkLengthInBytes };\n progressEventHandler(chunkProgressEventArgs);\n\n return result;\n }\n\n private async sendChunkUsingTcp(file: T, chunkStreamProvider: ChunkStreamProvider, progressEventHandler: (eventArgs: ChunkProgressEvent) => void): Promise<void> {\n const request: SendFileChunkRequest = {\n chunkLengthInBytes: chunkStreamProvider.chunkLengthInBytes,\n chunkStartPosition: chunkStreamProvider.chunkStartPosition,\n };\n\n const fileServerClient = this.#fileServerClientFactory.createFileServerTcpUploadClient(this.#transferMetadata!.transferFileServerUrl, this.#transferMetadata!.transferId, this.#transferMetadata!.transferKey, file.fileName, file.fileDestinationPathInTransfer, file.fileSizeInBytes);\n\n const ongoingRequestPromise = fileServerClient.sendFileChunk(request, chunkStreamProvider, this.#pauseSignal!, this.#abortSignal!);\n\n fileServerClient.addEventListener(`progress`, progressEventHandler);\n\n await ongoingRequestPromise;\n }\n\n private getChunkFailedReason(error: unknown) {\n if (error instanceof FsError)\n return `Can't read file. ${error.message}`;\n\n if (error instanceof ApiError)\n return error.cause?.message ? `${error.message}. ${error.cause.message}` : error.message;\n\n return (error as Error)?.message;\n }\n\n private throwIfNotPossibleToRun(pauseSignal: PauseSignal, abortSignal: AbortSignal) {\n if (this.#isRunMethodRunning)\n throw new TransferUploadError(`This transfer is running and cannot be run`);\n\n if (this.#transferState\n && this.#transferState.status !== TransferStatus.Failed\n && this.#transferState.status !== TransferStatus.Aborted\n && this.#transferState.status !== TransferStatus.Initialized\n && this.#transferState.status !== TransferStatus.Paused)\n throw new TransferUploadError(`Transfer is in ${TransferStatus[this.#transferState!.status]} state and cannot be run`);\n\n if (this.files.length === 0)\n throw new TransferUploadError(`There are no files passed to the transfer`);\n\n if (pauseSignal.paused)\n throw new TransferUploadError(`Can't run transfer with already paused PauseController`);\n\n if (abortSignal.aborted)\n throw new TransferUploadError(`Can't run transfer with already aborted AbortController`);\n }\n\n private addPauseAndStopListeners() {\n this.pauseEventListener = () => {\n if (this.#transferState!.status !== TransferStatus.Running)\n throw new TransferUploadError(`Transfer is in ${TransferStatus[this.#transferState!.status]} state and cannot be paused`);\n\n this.#transferState!.transferPauseRequested();\n };\n\n this.abortEventListener = () => {\n if (this.#transferState!.status !== TransferStatus.Running)\n throw new TransferUploadError(`Transfer is in ${TransferStatus[this.#transferState!.status]} state and cannot be stopped`);\n\n this.#transferState!.transferAbortRequested();\n };\n\n this.#pauseSignal!.addEventListener(`pause`, this.pauseEventListener);\n this.#abortSignal!.addEventListener(`abort`, this.abortEventListener);\n }\n\n private removePauseAndStopListeners() {\n this.#pauseSignal!.removeEventListener(`pause`, this.pauseEventListener!);\n this.#abortSignal!.removeEventListener(`abort`, this.abortEventListener!);\n }\n\n private async startApiTransferAndCreateMetadata() {\n if (this.isUploadAppendInfo(this.#info))\n throw new TransferUploadError(`Options are not TransferUploadOptions`);\n\n try {\n const encryptionDataAndIvSaltHex = await this.generateEncryptionDataAndIvSaltHmacHex(this.#info.e2eeKey);\n\n const request: InitializeTransferRequest = {\n e2ee: Boolean(encryptionDataAndIvSaltHex),\n e2ee_keyhash: encryptionDataAndIvSaltHex?.ivSaltHmacHex,\n transfersize: this.totalSizeInBytes,\n to: this.#info.to,\n from: this.#info.from,\n subject: this.#info.subject,\n message: this.#info.message,\n notify: this.#info.notify,\n confirmation: this.#info.confirmation,\n days: this.#info.days,\n password: this.#info.uploadPassword,\n companyid: this.#info.companyId,\n incominglogintoken: this.#info.incomingLoginToken,\n incomingpageid: this.#info.incomingPageId,\n filerequestid: this.#info.fileRequestId,\n filerequestshareid: this.#info.fileRequestShareId,\n customfields: this.#info.customFields,\n };\n\n const response = await this.#apiClient.initializeTransfer(request, this.#mergedPauseAndAbortSignal);\n\n this.#transferMetadata = {\n transferId: response.transferId,\n transferKey: response.transferKey,\n transferFileServerUrl: response.transferUrl,\n transferRegion: response.transferRegion,\n encryptionData: encryptionDataAndIvSaltHex?.encryptionData,\n udpData: this.getResponseOrForcedUdpData(response),\n };\n }\n catch (error) {\n throw new TransferUploadError(`Error initializing transfer through the API`, { cause: error as Error });\n }\n }\n\n private async generateEncryptionDataAndIvSaltHmacHex(e2eeKey?: string): Promise<{ encryptionData: { iv: Uint8Array, key: Uint8Array }, ivSaltHmacHex: string, salt: Uint8Array, hmac: Uint8Array } | undefined> {\n if (!e2eeKey)\n return undefined;\n\n const salt = this.#cryptography.generateRandomBytes(16);\n const key = await this.#cryptography.deriveKey(e2eeKey, salt);\n const hmac = await this.#cryptography.generateHmac(key);\n const iv = this.#cryptography.generateRandomBytes(16);\n\n const ivSaltHmac = concatUint8Arrays([iv, salt, hmac]);\n const ivSaltHmacHex = uint8ArrayToHex(ivSaltHmac);\n\n return {\n encryptionData: { iv, key },\n hmac,\n salt,\n ivSaltHmacHex,\n };\n }\n\n private getResponseOrForcedUdpData(response: InitializeTransferResponse): InitializeTransferResponseUdpData | undefined {\n if (!this.#config.forceUdp || !response.udp)\n return response.udp;\n\n return {\n ...response.udp,\n threshold: 0,\n };\n }\n\n private async finalizeTransfer(): Promise<void> {\n this.#eventsEngine.emit(TransferUploadEvent.TransferFinalizing);\n\n if (this.isUploadAppend())\n await this.resetApiTransfer();\n else\n await this.finalizeApiTransfer();\n }\n\n private async resetApiTransfer(): Promise<void> {\n try {\n const request: ResetTransferRequest = {\n transferid: this.#transferMetadata!.transferId,\n };\n\n await this.#apiClient.resetTransfer(request, this.#mergedPauseAndAbortSignal);\n }\n catch (error) {\n throw new TransferUploadError(`Error resetting transfer through the API`, { cause: error as Error });\n }\n }\n\n private async finalizeApiTransfer(): Promise<void> {\n try {\n const request: FinalizeTransferRequest = {\n transferid: this.#transferMetadata!.transferId,\n transferkey: this.#transferMetadata!.transferKey,\n protocol: this.#isUdpUploadMode ? `udp` : `tcp`,\n };\n\n const response = await this.#apiClient.finalizeTransfer(request, this.#mergedPauseAndAbortSignal);\n\n this.#transferDownloadUrl = response.downloadUrl;\n }\n catch (error) {\n throw new TransferUploadError(`Error finalizing transfer through the API`, { cause: error as Error });\n }\n }\n\n async cancel(abortSignal?: AbortSignal): Promise<void> {\n try {\n const isTransferApiInitialized = Boolean(this.#transferState) && Boolean(this.#transferMetadata);\n\n if (!isTransferApiInitialized) {\n this.emitCancelEvents();\n return;\n }\n\n this.throwIfInWrongStateToCancel();\n\n this.#transferState!.transferCancelRequested();\n\n if (this.isUploadAppend()) {\n // There is no possibility to cancel transfer upload append on API for now\n }\n else {\n try {\n await this.cancelApiTransfer(abortSignal);\n }\n catch {\n // If API cancel fails we still finalize local transfer state as canceled to avoid hanging in Canceling.\n }\n }\n\n this.#transferState!.transferCanceled();\n }\n catch (error) {\n if (error instanceof TransferUploadError)\n throw error;\n else\n throw new TransferUploadError(`Unhandled error occured. See 'cause' for more details`, { cause: error as Error });\n }\n }\n\n private emitCancelEvents() {\n this.#eventsEngine.emit(TransferUploadEvent.TransferCancelRequested);\n this.#eventsEngine.emit(TransferUploadEvent.TransferCanceled);\n }\n\n private throwIfInWrongStateToCancel() {\n if (!this.#transferState)\n return;\n\n if (this.#transferState.status !== TransferStatus.Failed\n && this.#transferState.status !== TransferStatus.Aborted\n && this.#transferState.status !== TransferStatus.Initialized\n && this.#transferState.status !== TransferStatus.Paused)\n throw new TransferUploadError(`Transfer is in ${TransferStatus[this.#transferState!.status]} state and cannot be canceled`);\n }\n\n private async cancelApiTransfer(abortSignal?: AbortSignal): Promise<void> {\n try {\n const request: CancelTransferRequest = {\n transferid: this.#transferMetadata!.transferId,\n transferkey: this.#transferMetadata!.transferKey,\n };\n\n await this.#apiClient.cancelTransfer(request, abortSignal);\n }\n catch (error) {\n throw new TransferUploadError(`Error canceling transfer through the API`, { cause: error as Error });\n }\n }\n\n addEventListener(eventName: TransferUploadEvent.TransferRun | TransferUploadEvent.TransferPauseRequested | TransferUploadEvent.TransferPaused | TransferUploadEvent.TransferAbortRequested | TransferUploadEvent.TransferAborted | TransferUploadEvent.TransferCancelRequested | TransferUploadEvent.TransferCanceled | TransferUploadEvent.TransferFailed, handler: () => void): void\n addEventListener(eventName: TransferUploadEvent.FileUploadStarted | TransferUploadEvent.FileUploadCompleted, handler: (event: FileUploadEventArgs) => void): void\n addEventListener(eventName: TransferUploadEvent.FileUploadFailed, handler: (event: FileUploadFailedEventArgs) => void): void\n addEventListener(eventName: TransferUploadEvent.FileChunkUploadProgressed, handler: (event: FileChunkUploadProgressedEventArgs) => void): void\n addEventListener(eventName: TransferUploadEvent.FileChunkUploadStarted, handler: (event: FileChunkUploadEventArgs) => void): void\n addEventListener(eventName: TransferUploadEvent.FileChunkUploadCompleted, handler: (event: FileChunkUploadCompletedEventArgs) => void): void\n addEventListener(eventName: TransferUploadEvent.FileChunkUploadCompletedPartially, handler: (event: FileChunkUploadCompletedPartiallyEventArgs) => void): void\n addEventListener(eventName: TransferUploadEvent.FileChunkUploadFailed, handler: (event: FileChunkUploadFailedEventArgs) => void): void\n addEventListener(eventName: TransferUploadEvent.TransferProgressed, handler: (event: TransferUploadProgressedEventArgs) => void): void\n addEventListener(eventName: TransferUploadEvent.TransferCompleted, handler: (event: TransferUploadCompletedEventArgs) => void): void\n addEventListener(eventName: TransferUploadEvent.TransferUploadModeChosen, handler: (event: TransferUploadModeChosenEventArgs) => void): void\n addEventListener(eventName: TransferUploadEvent.TransferMetadataDetermined, handler: (event: TransferMetadataDeterminedEventArgs) => void): void\n addEventListener(eventName: string, handler: (arg?: any) => void): void\n addEventListener(eventName: string, handler: (arg?: any) => void): void {\n this.#eventsEngine.addEventListener(eventName, handler);\n }\n\n exportAsString(): string {\n const exportData = this.export();\n return JSON.stringify(exportData);\n }\n\n export(): TransferUploadExportData<T> {\n if (!this.#transferState?.files)\n throw new TransferUploadError(`Can't export not started Transfer`); // fileStatuses are not created yet and it really doesn't make any sens to export not started transfer\n\n return {\n transferMetadata: this.getTransferMetadataExportValue(),\n info: this.#info,\n state: this.#transferState.export(),\n };\n }\n\n private getTransferMetadataExportValue(): TransferUploadExportDataMetadata | undefined {\n if (!this.#transferMetadata)\n return undefined;\n\n const { encryptionData, ...rest } = this.#transferMetadata;\n\n return {\n ...rest,\n encryptionData: !encryptionData ? undefined : {\n ivHex: uint8ArrayToHex(encryptionData.iv),\n keyHex: uint8ArrayToHex(encryptionData.key),\n },\n };\n }\n\n static recreate<T extends FileDetails>(transferExportData: TransferUploadExportData<T>, config: TransferUploadConfig, chunkStreamProviderFactory: UploaderChunkStreamProviderFactory<T>, apiClient: ApiClient, fileServerClientFactory: FileServerClientFactory, eventsEngine: EventsEngine, optimizer: UploadOptimizer, cryptography: CryptographyProvider): TransferUpload<T> {\n try {\n TransferUpload.validateRecreateParams(transferExportData);\n\n const transfer = new TransferUpload<T>(chunkStreamProviderFactory, apiClient, fileServerClientFactory, eventsEngine, transferExportData.info, config, optimizer, cryptography);\n\n transfer.#transferMetadata = this.recreateTransferMetadata(transferExportData.transferMetadata);\n transfer.#transferState = new TransferUploadState(transferExportData.info.files, eventsEngine, config.currentRatesTimespanInMs, config.progressEventThrottlingInMs, transferExportData.state);\n\n return transfer;\n }\n catch (error) {\n if (error instanceof TransferUploadError)\n throw error;\n else\n throw new TransferUploadError(`Unhandled error occured. See 'cause' for more details`, { cause: error as Error });\n }\n }\n\n private static recreateTransferMetadata(transferMetadata?: TransferUploadExportDataMetadata): TransferUploadMetadata | undefined {\n if (!transferMetadata)\n return undefined;\n\n const { encryptionData, ...rest } = transferMetadata;\n\n return {\n ...rest,\n encryptionData: !encryptionData ? undefined : {\n iv: hexToUint8Array(encryptionData.ivHex),\n key: hexToUint8Array(encryptionData.keyHex),\n },\n };\n }\n\n private static validateRecreateParams<T extends FileDetails>(transferExportData: TransferUploadExportData<T>) {\n if (!transferExportData.info)\n throw new TransferUploadError(`Info must be defined`);\n\n if (!transferExportData.state)\n throw new TransferUploadError(`State must be defined`);\n\n if (transferExportData.transferMetadata && (!transferExportData.transferMetadata.transferId || !transferExportData.transferMetadata.transferKey || !transferExportData.transferMetadata.transferFileServerUrl))\n throw new TransferUploadError(`Not all transfer metadata properties are defined`);\n\n if (transferExportData.transferMetadata?.encryptionData) {\n if (transferExportData.transferMetadata.encryptionData.ivHex.length !== 32)\n throw new TransferUploadError(`Encryption IV must be 16 bytes long`);\n if (transferExportData.transferMetadata.encryptionData.keyHex.length !== 64)\n throw new TransferUploadError(`Encryption key must be 32 bytes long`);\n }\n }\n}\n"]}
|
|
@@ -19,6 +19,8 @@ export default class NodeChunkStreamProvider implements ChunkStreamProvider {
|
|
|
19
19
|
decipherStream?: Writable;
|
|
20
20
|
}>;
|
|
21
21
|
release(): Promise<void>;
|
|
22
|
+
private registerPauseListener;
|
|
23
|
+
private cleanupPauseListener;
|
|
22
24
|
private closeHandle;
|
|
23
25
|
private destroyStream;
|
|
24
26
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"nodeChunkStreamProvider.d.ts","sourceRoot":"","sources":["../../../../../src/utils/fileSystem/node/nodeChunkStreamProvider.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAMvC,OAAO,KAAK,mBAAmB,MAAM,2BAA2B,CAAC;AACjE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sCAAsC,CAAC;AACxE,OAAO,KAAK,EAAE,iCAAiC,EAAE,MAAM,2BAA2B,CAAC;AAEnF,MAAM,CAAC,OAAO,OAAO,uBAAwB,YAAW,mBAAmB;;IACvE,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAC;IACpC,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"nodeChunkStreamProvider.d.ts","sourceRoot":"","sources":["../../../../../src/utils/fileSystem/node/nodeChunkStreamProvider.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAMvC,OAAO,KAAK,mBAAmB,MAAM,2BAA2B,CAAC;AACjE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sCAAsC,CAAC;AACxE,OAAO,KAAK,EAAE,iCAAiC,EAAE,MAAM,2BAA2B,CAAC;AAEnF,MAAM,CAAC,OAAO,OAAO,uBAAwB,YAAW,mBAAmB;;IACvE,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAC;IACpC,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAC;IAepC,IAAI,UAAU,IAAI,OAAO,CAYxB;gBAEW,YAAY,EAAE,MAAM,EAAE,kBAAkB,EAAE,MAAM,EAAE,kBAAkB,EAAE,MAAM,EAAE,cAAc,EAAE,iCAAiC,GAAG,SAAS;IAavJ,OAAO,CAAC,+BAA+B;IAUjC,cAAc,CAAC,MAAM,EAAE,KAAK,GAAG,QAAQ,EAAE,WAAW,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC;IAmBpF,kBAAkB,CAAC,WAAW,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,cAAc,CAAC;IAqC5E,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;IAI7B,OAAO,CAAC,mBAAmB;IAOrB,mBAAmB,IAAI,OAAO,CAAC;QAAE,UAAU,EAAE,QAAQ,CAAC;QAAC,cAAc,CAAC,EAAE,QAAQ,CAAA;KAAE,CAAC;IA8BnF,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAsB9B,OAAO,CAAC,qBAAqB;IAiB7B,OAAO,CAAC,oBAAoB;IAU5B,OAAO,CAAC,WAAW,CAQjB;IAEF,OAAO,CAAC,aAAa,CAQnB;CACL"}
|
|
@@ -18,6 +18,8 @@ export default class NodeChunkStreamProvider {
|
|
|
18
18
|
#fileWriteHandle = null;
|
|
19
19
|
#fileWriteStream = null;
|
|
20
20
|
#fileWriteDecipherStream = null;
|
|
21
|
+
#pauseSignal;
|
|
22
|
+
#pauseListener;
|
|
21
23
|
get isReleased() {
|
|
22
24
|
const isFileReadHandleReleased = this.#fileReadHandle === null;
|
|
23
25
|
const isFileReadStreamReleased = this.#fileReadStream?.destroyed ?? true;
|
|
@@ -78,11 +80,7 @@ export default class NodeChunkStreamProvider {
|
|
|
78
80
|
}
|
|
79
81
|
else
|
|
80
82
|
this.#fileReadStream.pipe(this.#fileReadPassThroughStream);
|
|
81
|
-
pauseSignal
|
|
82
|
-
this.#fileReadStream?.destroy();
|
|
83
|
-
this.#fileReadCipherStream?.destroy();
|
|
84
|
-
this.#fileReadPassThroughStream?.end();
|
|
85
|
-
});
|
|
83
|
+
this.registerPauseListener(pauseSignal);
|
|
86
84
|
return ReadableStream.from(this.#fileReadPassThroughStream);
|
|
87
85
|
}
|
|
88
86
|
catch (error) {
|
|
@@ -119,6 +117,7 @@ export default class NodeChunkStreamProvider {
|
|
|
119
117
|
}
|
|
120
118
|
}
|
|
121
119
|
async release() {
|
|
120
|
+
this.cleanupPauseListener();
|
|
122
121
|
await Promise.allSettled([
|
|
123
122
|
this.closeHandle(this.#fileReadHandle),
|
|
124
123
|
this.destroyStream(this.#fileReadStream),
|
|
@@ -136,6 +135,25 @@ export default class NodeChunkStreamProvider {
|
|
|
136
135
|
this.#fileWriteStream = null;
|
|
137
136
|
this.#fileWriteDecipherStream = null;
|
|
138
137
|
}
|
|
138
|
+
registerPauseListener(pauseSignal) {
|
|
139
|
+
this.cleanupPauseListener();
|
|
140
|
+
if (!pauseSignal)
|
|
141
|
+
return;
|
|
142
|
+
this.#pauseSignal = pauseSignal;
|
|
143
|
+
this.#pauseListener = () => {
|
|
144
|
+
this.#fileReadStream?.destroy();
|
|
145
|
+
this.#fileReadCipherStream?.destroy();
|
|
146
|
+
this.#fileReadPassThroughStream?.end();
|
|
147
|
+
};
|
|
148
|
+
this.#pauseSignal.addEventListener(`pause`, this.#pauseListener);
|
|
149
|
+
}
|
|
150
|
+
cleanupPauseListener() {
|
|
151
|
+
if (!this.#pauseSignal || !this.#pauseListener)
|
|
152
|
+
return;
|
|
153
|
+
this.#pauseSignal.removeEventListener(`pause`, this.#pauseListener);
|
|
154
|
+
this.#pauseSignal = undefined;
|
|
155
|
+
this.#pauseListener = undefined;
|
|
156
|
+
}
|
|
139
157
|
closeHandle = async (handle) => {
|
|
140
158
|
if (!handle)
|
|
141
159
|
return;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"nodeChunkStreamProvider.js","sourceRoot":"","sources":["../../../../../src/utils/fileSystem/node/nodeChunkStreamProvider.ts"],"names":[],"mappings":"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","sourcesContent":["import fs from \"fs/promises\";\nimport { ReadStream, WriteStream, constants as fsConsts } from \"fs\";\nimport crypto from \"crypto\";\nimport { pipeline, finished } from \"stream/promises\";\nimport { PassThrough, Transform } from \"stream\";\n\nimport { ReadableStream } from \"stream/web\";\nimport type { Writable } from \"stream\";\n\nimport { createCipher, createDecipher } from 'aes-ctr-concurrent';\n\nimport FsError from '../fsError.js';\n\nimport type ChunkStreamProvider from \"../chunkStreamProvider.js\";\nimport type { PauseSignal } from \"../../../uploader/pauseController.js\";\nimport type { ChunkStreamProviderEncryptionData } from \"../chunkStreamProvider.js\";\n\nexport default class NodeChunkStreamProvider implements ChunkStreamProvider {\n readonly chunkStartPosition: number;\n readonly chunkLengthInBytes: number;\n\n readonly #encryptionData?: ChunkStreamProviderEncryptionData;\n readonly #fullFilePath: string;\n\n #fileReadHandle: fs.FileHandle | null = null;\n #fileReadStream: ReadStream | null = null;\n #fileReadCipherStream: Transform | null = null;\n #fileReadPassThroughStream: PassThrough | null = null;\n #fileWriteHandle: fs.FileHandle | null = null;\n #fileWriteStream: WriteStream | null = null;\n #fileWriteDecipherStream: Transform | null = null;\n\n get isReleased(): boolean {\n const isFileReadHandleReleased = this.#fileReadHandle === null;\n const isFileReadStreamReleased = this.#fileReadStream?.destroyed ?? true;\n const isFileReadCipherStreamReleased = this.#fileReadCipherStream?.destroyed ?? true;\n const isFileReadPassThroughStreamReleased = this.#fileReadPassThroughStream?.destroyed ?? true;\n const isFileWriteHandleReleased = this.#fileWriteHandle === null;\n const isFileWriteStreamReleased = this.#fileWriteStream?.destroyed ?? true;\n const isFileWriteDecipherStreamReleased = this.#fileWriteDecipherStream?.destroyed ?? true;\n\n return isFileReadHandleReleased && isFileReadStreamReleased && isFileReadCipherStreamReleased\n && isFileReadPassThroughStreamReleased && isFileWriteStreamReleased && isFileWriteDecipherStreamReleased\n && isFileWriteHandleReleased;\n }\n\n constructor(fullFilePath: string, chunkStartPosition: number, chunkLengthInBytes: number, encryptionData: ChunkStreamProviderEncryptionData | undefined) {\n this.throwIfEncryptionDataIsNotValid(encryptionData);\n\n this.#fullFilePath = fullFilePath;\n this.#encryptionData = encryptionData;\n this.chunkStartPosition = chunkStartPosition;\n\n if (chunkLengthInBytes < 0)\n throw new FsError(`chunkLengthInBytes can't be a negative value`);\n\n this.chunkLengthInBytes = chunkLengthInBytes;\n }\n\n private throwIfEncryptionDataIsNotValid(encryptionData: ChunkStreamProviderEncryptionData | undefined) {\n if (!encryptionData)\n return;\n\n if (encryptionData.iv.length !== 16)\n throw new FsError(`Encryption IV must be 16 bytes long`);\n if (encryptionData.key.length !== 32)\n throw new FsError(`Encryption key must be 32 bytes long`);\n }\n\n async getMd5Checksum(format: `hex` | `base64`, pauseSignal?: PauseSignal): Promise<string> {\n try {\n const fileStream = await this.getChunkReadStream(pauseSignal);\n\n const hash = crypto.createHash(`md5`);\n\n await pipeline(fileStream, hash);\n\n return hash.digest(format);\n }\n catch (error) {\n throw new FsError(`ComputingFileMd5ChecksumException`, { cause: error as Error });\n }\n finally {\n if (!this.isReleased)\n await this.release();\n }\n }\n\n async getChunkReadStream(pauseSignal?: PauseSignal): Promise<ReadableStream> {\n try {\n if (!this.isReleased)\n await this.release();\n\n this.#fileReadHandle = await fs.open(this.#fullFilePath, fsConsts.O_RDONLY);\n\n this.#fileReadStream = this.#fileReadHandle.createReadStream({\n start: this.chunkStartPosition,\n end: this.getChunkEndPosition(),\n });\n\n this.#fileReadPassThroughStream = new PassThrough();\n\n if (this.#encryptionData) {\n this.#fileReadCipherStream = createCipher(\n Buffer.from(this.#encryptionData.key),\n Buffer.from(this.#encryptionData.iv),\n this.chunkStartPosition,\n ) as Transform;\n this.#fileReadStream.pipe(this.#fileReadCipherStream).pipe(this.#fileReadPassThroughStream);\n }\n else\n this.#fileReadStream.pipe(this.#fileReadPassThroughStream);\n\n pauseSignal?.addEventListener(`pause`, () => {\n this.#fileReadStream?.destroy();\n this.#fileReadCipherStream?.destroy();\n this.#fileReadPassThroughStream?.end();\n });\n\n return ReadableStream.from(this.#fileReadPassThroughStream);\n }\n catch (error) {\n if (!this.isReleased)\n await this.release();\n\n throw new FsError(`CreatingFileReadStreamException`, { cause: error as Error });\n }\n }\n\n getChunkBlob(): Promise<Blob> {\n throw new Error(`Not implemented for NodeJS`);\n }\n\n private getChunkEndPosition() {\n if (this.chunkLengthInBytes === 0)\n return this.chunkStartPosition;\n\n return this.chunkStartPosition + this.chunkLengthInBytes - 1;\n }\n\n async getChunkWriteStream(): Promise<{ fileStream: Writable, decipherStream?: Writable }> {\n try {\n if (!this.isReleased)\n await this.release();\n\n this.#fileWriteHandle = await fs.open(this.#fullFilePath, fsConsts.O_WRONLY);\n\n this.#fileWriteStream = this.#fileWriteHandle.createWriteStream({\n start: this.chunkStartPosition,\n });\n\n if (!this.#encryptionData)\n return { fileStream: this.#fileWriteStream };\n\n this.#fileWriteDecipherStream = createDecipher(\n Buffer.from(this.#encryptionData.key),\n Buffer.from(this.#encryptionData.iv),\n this.chunkStartPosition,\n ) as Transform;\n\n return { fileStream: this.#fileWriteStream, decipherStream: this.#fileWriteDecipherStream };\n }\n catch (error) {\n if (!this.isReleased)\n await this.release();\n\n throw new FsError(`CreatingFileWriteStreamException`, { cause: error as Error });\n }\n }\n\n async release(): Promise<void> {\n await Promise.allSettled([\n this.closeHandle(this.#fileReadHandle),\n this.destroyStream(this.#fileReadStream),\n this.destroyStream(this.#fileReadCipherStream),\n this.destroyStream(this.#fileReadPassThroughStream),\n this.closeHandle(this.#fileWriteHandle),\n this.destroyStream(this.#fileWriteStream),\n this.destroyStream(this.#fileWriteDecipherStream),\n ]);\n\n this.#fileReadHandle = null;\n this.#fileReadStream = null;\n this.#fileReadCipherStream = null;\n this.#fileReadPassThroughStream = null;\n this.#fileWriteHandle = null;\n this.#fileWriteStream = null;\n this.#fileWriteDecipherStream = null;\n }\n\n private closeHandle = async (handle: fs.FileHandle | null): Promise<void> => {\n if (!handle)\n return;\n\n try {\n await handle.close();\n }\n catch { /* ignore errors during handle closing */ }\n };\n\n private destroyStream = async (stream: ReadStream | Writable | Transform | PassThrough | null): Promise<void> => {\n if (!stream || stream.destroyed)\n return;\n\n stream.once(`error`, () => { /* absorb premature close errors */ });\n const finishPromise = finished(stream).catch(() => { /* safely ignore */ });\n stream.destroy();\n await finishPromise;\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"nodeChunkStreamProvider.js","sourceRoot":"","sources":["../../../../../src/utils/fileSystem/node/nodeChunkStreamProvider.ts"],"names":[],"mappings":"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","sourcesContent":["import fs from \"fs/promises\";\nimport { ReadStream, WriteStream, constants as fsConsts } from \"fs\";\nimport crypto from \"crypto\";\nimport { pipeline, finished } from \"stream/promises\";\nimport { PassThrough, Transform } from \"stream\";\n\nimport { ReadableStream } from \"stream/web\";\nimport type { Writable } from \"stream\";\n\nimport { createCipher, createDecipher } from 'aes-ctr-concurrent';\n\nimport FsError from '../fsError.js';\n\nimport type ChunkStreamProvider from \"../chunkStreamProvider.js\";\nimport type { PauseSignal } from \"../../../uploader/pauseController.js\";\nimport type { ChunkStreamProviderEncryptionData } from \"../chunkStreamProvider.js\";\n\nexport default class NodeChunkStreamProvider implements ChunkStreamProvider {\n readonly chunkStartPosition: number;\n readonly chunkLengthInBytes: number;\n\n readonly #encryptionData?: ChunkStreamProviderEncryptionData;\n readonly #fullFilePath: string;\n\n #fileReadHandle: fs.FileHandle | null = null;\n #fileReadStream: ReadStream | null = null;\n #fileReadCipherStream: Transform | null = null;\n #fileReadPassThroughStream: PassThrough | null = null;\n #fileWriteHandle: fs.FileHandle | null = null;\n #fileWriteStream: WriteStream | null = null;\n #fileWriteDecipherStream: Transform | null = null;\n #pauseSignal: PauseSignal | undefined;\n #pauseListener: (() => void) | undefined;\n\n get isReleased(): boolean {\n const isFileReadHandleReleased = this.#fileReadHandle === null;\n const isFileReadStreamReleased = this.#fileReadStream?.destroyed ?? true;\n const isFileReadCipherStreamReleased = this.#fileReadCipherStream?.destroyed ?? true;\n const isFileReadPassThroughStreamReleased = this.#fileReadPassThroughStream?.destroyed ?? true;\n const isFileWriteHandleReleased = this.#fileWriteHandle === null;\n const isFileWriteStreamReleased = this.#fileWriteStream?.destroyed ?? true;\n const isFileWriteDecipherStreamReleased = this.#fileWriteDecipherStream?.destroyed ?? true;\n\n return isFileReadHandleReleased && isFileReadStreamReleased && isFileReadCipherStreamReleased\n && isFileReadPassThroughStreamReleased && isFileWriteStreamReleased && isFileWriteDecipherStreamReleased\n && isFileWriteHandleReleased;\n }\n\n constructor(fullFilePath: string, chunkStartPosition: number, chunkLengthInBytes: number, encryptionData: ChunkStreamProviderEncryptionData | undefined) {\n this.throwIfEncryptionDataIsNotValid(encryptionData);\n\n this.#fullFilePath = fullFilePath;\n this.#encryptionData = encryptionData;\n this.chunkStartPosition = chunkStartPosition;\n\n if (chunkLengthInBytes < 0)\n throw new FsError(`chunkLengthInBytes can't be a negative value`);\n\n this.chunkLengthInBytes = chunkLengthInBytes;\n }\n\n private throwIfEncryptionDataIsNotValid(encryptionData: ChunkStreamProviderEncryptionData | undefined) {\n if (!encryptionData)\n return;\n\n if (encryptionData.iv.length !== 16)\n throw new FsError(`Encryption IV must be 16 bytes long`);\n if (encryptionData.key.length !== 32)\n throw new FsError(`Encryption key must be 32 bytes long`);\n }\n\n async getMd5Checksum(format: `hex` | `base64`, pauseSignal?: PauseSignal): Promise<string> {\n try {\n const fileStream = await this.getChunkReadStream(pauseSignal);\n\n const hash = crypto.createHash(`md5`);\n\n await pipeline(fileStream, hash);\n\n return hash.digest(format);\n }\n catch (error) {\n throw new FsError(`ComputingFileMd5ChecksumException`, { cause: error as Error });\n }\n finally {\n if (!this.isReleased)\n await this.release();\n }\n }\n\n async getChunkReadStream(pauseSignal?: PauseSignal): Promise<ReadableStream> {\n try {\n if (!this.isReleased)\n await this.release();\n\n this.#fileReadHandle = await fs.open(this.#fullFilePath, fsConsts.O_RDONLY);\n\n this.#fileReadStream = this.#fileReadHandle.createReadStream({\n start: this.chunkStartPosition,\n end: this.getChunkEndPosition(),\n });\n\n this.#fileReadPassThroughStream = new PassThrough();\n\n if (this.#encryptionData) {\n this.#fileReadCipherStream = createCipher(\n Buffer.from(this.#encryptionData.key),\n Buffer.from(this.#encryptionData.iv),\n this.chunkStartPosition,\n ) as Transform;\n this.#fileReadStream.pipe(this.#fileReadCipherStream).pipe(this.#fileReadPassThroughStream);\n }\n else\n this.#fileReadStream.pipe(this.#fileReadPassThroughStream);\n\n this.registerPauseListener(pauseSignal);\n\n return ReadableStream.from(this.#fileReadPassThroughStream);\n }\n catch (error) {\n if (!this.isReleased)\n await this.release();\n\n throw new FsError(`CreatingFileReadStreamException`, { cause: error as Error });\n }\n }\n\n getChunkBlob(): Promise<Blob> {\n throw new Error(`Not implemented for NodeJS`);\n }\n\n private getChunkEndPosition() {\n if (this.chunkLengthInBytes === 0)\n return this.chunkStartPosition;\n\n return this.chunkStartPosition + this.chunkLengthInBytes - 1;\n }\n\n async getChunkWriteStream(): Promise<{ fileStream: Writable, decipherStream?: Writable }> {\n try {\n if (!this.isReleased)\n await this.release();\n\n this.#fileWriteHandle = await fs.open(this.#fullFilePath, fsConsts.O_WRONLY);\n\n this.#fileWriteStream = this.#fileWriteHandle.createWriteStream({\n start: this.chunkStartPosition,\n });\n\n if (!this.#encryptionData)\n return { fileStream: this.#fileWriteStream };\n\n this.#fileWriteDecipherStream = createDecipher(\n Buffer.from(this.#encryptionData.key),\n Buffer.from(this.#encryptionData.iv),\n this.chunkStartPosition,\n ) as Transform;\n\n return { fileStream: this.#fileWriteStream, decipherStream: this.#fileWriteDecipherStream };\n }\n catch (error) {\n if (!this.isReleased)\n await this.release();\n\n throw new FsError(`CreatingFileWriteStreamException`, { cause: error as Error });\n }\n }\n\n async release(): Promise<void> {\n this.cleanupPauseListener();\n\n await Promise.allSettled([\n this.closeHandle(this.#fileReadHandle),\n this.destroyStream(this.#fileReadStream),\n this.destroyStream(this.#fileReadCipherStream),\n this.destroyStream(this.#fileReadPassThroughStream),\n this.closeHandle(this.#fileWriteHandle),\n this.destroyStream(this.#fileWriteStream),\n this.destroyStream(this.#fileWriteDecipherStream),\n ]);\n\n this.#fileReadHandle = null;\n this.#fileReadStream = null;\n this.#fileReadCipherStream = null;\n this.#fileReadPassThroughStream = null;\n this.#fileWriteHandle = null;\n this.#fileWriteStream = null;\n this.#fileWriteDecipherStream = null;\n }\n\n private registerPauseListener(pauseSignal?: PauseSignal) {\n this.cleanupPauseListener();\n\n if (!pauseSignal)\n return;\n\n this.#pauseSignal = pauseSignal;\n\n this.#pauseListener = () => {\n this.#fileReadStream?.destroy();\n this.#fileReadCipherStream?.destroy();\n this.#fileReadPassThroughStream?.end();\n };\n\n this.#pauseSignal.addEventListener(`pause`, this.#pauseListener);\n }\n\n private cleanupPauseListener() {\n if (!this.#pauseSignal || !this.#pauseListener)\n return;\n\n this.#pauseSignal.removeEventListener(`pause`, this.#pauseListener);\n\n this.#pauseSignal = undefined;\n this.#pauseListener = undefined;\n }\n\n private closeHandle = async (handle: fs.FileHandle | null): Promise<void> => {\n if (!handle)\n return;\n\n try {\n await handle.close();\n }\n catch { /* ignore errors during handle closing */ }\n };\n\n private destroyStream = async (stream: ReadStream | Writable | Transform | PassThrough | null): Promise<void> => {\n if (!stream || stream.destroyed)\n return;\n\n stream.once(`error`, () => { /* absorb premature close errors */ });\n const finishPromise = finished(stream).catch(() => { /* safely ignore */ });\n stream.destroy();\n await finishPromise;\n };\n}\n"]}
|