filemail-sdk 10.4.0 → 10.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/client/downloader/downloaderCore.d.ts +2 -1
- package/dist/src/client/downloader/downloaderCore.d.ts.map +1 -1
- package/dist/src/client/downloader/downloaderCore.js +6 -4
- package/dist/src/client/downloader/downloaderCore.js.map +1 -1
- package/dist/src/client/downloader/node/nodeTransferDownloader.d.ts.map +1 -1
- package/dist/src/client/downloader/node/nodeTransferDownloader.js +4 -2
- package/dist/src/client/downloader/node/nodeTransferDownloader.js.map +1 -1
- package/dist/src/client/uploader/node/nodeTransferUploader.d.ts.map +1 -1
- package/dist/src/client/uploader/node/nodeTransferUploader.js +10 -4
- package/dist/src/client/uploader/node/nodeTransferUploader.js.map +1 -1
- package/dist/src/client/uploader/transferUploaderBase.js +1 -1
- package/dist/src/client/uploader/transferUploaderBase.js.map +1 -1
- package/dist/src/client/uploader/web/webTransferUploader.d.ts +2 -2
- package/dist/src/client/uploader/web/webTransferUploader.d.ts.map +1 -1
- package/dist/src/client/uploader/web/webTransferUploader.js +7 -2
- package/dist/src/client/uploader/web/webTransferUploader.js.map +1 -1
- package/dist/src/client/uploader/web/webTransferUploaderConfig.d.ts +7 -0
- package/dist/src/client/uploader/web/webTransferUploaderConfig.d.ts.map +1 -0
- package/dist/src/client/uploader/web/webTransferUploaderConfig.js +2 -0
- package/dist/src/client/uploader/web/webTransferUploaderConfig.js.map +1 -0
- package/dist/src/downloader/api/fileServerDownloadClient.d.ts +2 -2
- package/dist/src/downloader/api/fileServerDownloadClient.d.ts.map +1 -1
- package/dist/src/downloader/api/fileServerDownloadClient.js.map +1 -1
- package/dist/src/downloader/chunkDownloader.d.ts +3 -2
- package/dist/src/downloader/chunkDownloader.d.ts.map +1 -1
- package/dist/src/downloader/chunkDownloader.js +6 -3
- package/dist/src/downloader/chunkDownloader.js.map +1 -1
- package/dist/src/downloader/filesDownloader.d.ts +2 -1
- package/dist/src/downloader/filesDownloader.d.ts.map +1 -1
- package/dist/src/downloader/filesDownloader.js +4 -2
- package/dist/src/downloader/filesDownloader.js.map +1 -1
- package/dist/src/downloader/md5Provider/downloaderChunkMD5Provider.d.ts +6 -0
- package/dist/src/downloader/md5Provider/downloaderChunkMD5Provider.d.ts.map +1 -0
- package/dist/src/downloader/md5Provider/downloaderChunkMD5Provider.js +2 -0
- package/dist/src/downloader/md5Provider/downloaderChunkMD5Provider.js.map +1 -0
- package/dist/src/downloader/md5Provider/downloaderChunkMD5ProviderFactory.d.ts +7 -0
- package/dist/src/downloader/md5Provider/downloaderChunkMD5ProviderFactory.d.ts.map +1 -0
- package/dist/src/downloader/md5Provider/downloaderChunkMD5ProviderFactory.js +2 -0
- package/dist/src/downloader/md5Provider/downloaderChunkMD5ProviderFactory.js.map +1 -0
- package/dist/src/downloader/md5Provider/node/nodeOnDemandMD5Provider.d.ts +10 -0
- package/dist/src/downloader/md5Provider/node/nodeOnDemandMD5Provider.d.ts.map +1 -0
- package/dist/src/downloader/md5Provider/node/nodeOnDemandMD5Provider.js +36 -0
- package/dist/src/downloader/md5Provider/node/nodeOnDemandMD5Provider.js.map +1 -0
- package/dist/src/downloader/md5Provider/node/nodeOnDemandMD5ProviderFactory.d.ts +10 -0
- package/dist/src/downloader/md5Provider/node/nodeOnDemandMD5ProviderFactory.d.ts.map +1 -0
- package/dist/src/downloader/md5Provider/node/nodeOnDemandMD5ProviderFactory.js +14 -0
- package/dist/src/downloader/md5Provider/node/nodeOnDemandMD5ProviderFactory.js.map +1 -0
- package/dist/src/index.d.ts +10 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +1 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/index.node.d.ts +4 -0
- package/dist/src/index.node.d.ts.map +1 -1
- package/dist/src/index.node.js +4 -0
- package/dist/src/index.node.js.map +1 -1
- package/dist/src/index.web.d.ts +5 -0
- package/dist/src/index.web.d.ts.map +1 -1
- package/dist/src/index.web.js +4 -0
- package/dist/src/index.web.js.map +1 -1
- package/dist/src/uploader/api/node/nodeFileServerUploadClient.d.ts.map +1 -1
- package/dist/src/uploader/api/node/nodeFileServerUploadClient.js +1 -2
- package/dist/src/uploader/api/node/nodeFileServerUploadClient.js.map +1 -1
- package/dist/src/uploader/api/web/webFileServerUploadClient.d.ts.map +1 -1
- package/dist/src/uploader/api/web/webFileServerUploadClient.js +1 -2
- package/dist/src/uploader/api/web/webFileServerUploadClient.js.map +1 -1
- package/dist/src/uploader/chunkStreamProviderFactory/node/nodeFileDetailsUploaderChunkStreamProviderFactory.d.ts +9 -0
- package/dist/src/uploader/chunkStreamProviderFactory/node/nodeFileDetailsUploaderChunkStreamProviderFactory.d.ts.map +1 -0
- package/dist/src/uploader/chunkStreamProviderFactory/{nodeFileDetailsUploaderChunkStreamProviderFactory.js → node/nodeFileDetailsUploaderChunkStreamProviderFactory.js} +1 -1
- package/dist/src/uploader/chunkStreamProviderFactory/node/nodeFileDetailsUploaderChunkStreamProviderFactory.js.map +1 -0
- package/dist/src/uploader/chunkStreamProviderFactory/uploaderChunkStreamProviderFactory.d.ts +2 -2
- package/dist/src/uploader/chunkStreamProviderFactory/uploaderChunkStreamProviderFactory.d.ts.map +1 -1
- package/dist/src/uploader/chunkStreamProviderFactory/uploaderChunkStreamProviderFactory.js.map +1 -1
- package/dist/src/uploader/chunkStreamProviderFactory/web/webFileDetailsUploaderChunkStreamProviderFactory.d.ts +9 -0
- package/dist/src/uploader/chunkStreamProviderFactory/web/webFileDetailsUploaderChunkStreamProviderFactory.d.ts.map +1 -0
- package/dist/src/uploader/chunkStreamProviderFactory/{webFileDetailsUploaderChunkStreamProviderFactory.js → web/webFileDetailsUploaderChunkStreamProviderFactory.js} +1 -1
- package/dist/src/uploader/chunkStreamProviderFactory/web/webFileDetailsUploaderChunkStreamProviderFactory.js.map +1 -0
- package/dist/src/uploader/fileChunksPlan.d.ts +8 -0
- package/dist/src/uploader/fileChunksPlan.d.ts.map +1 -0
- package/dist/src/uploader/fileChunksPlan.js +2 -0
- package/dist/src/uploader/fileChunksPlan.js.map +1 -0
- package/dist/src/uploader/md5Provider/md5ComputationStrategies/defaultMD5ComputationStrategyFactory.d.ts +10 -0
- package/dist/src/uploader/md5Provider/md5ComputationStrategies/defaultMD5ComputationStrategyFactory.d.ts.map +1 -0
- package/dist/src/uploader/md5Provider/md5ComputationStrategies/defaultMD5ComputationStrategyFactory.js +12 -0
- package/dist/src/uploader/md5Provider/md5ComputationStrategies/defaultMD5ComputationStrategyFactory.js.map +1 -0
- package/dist/src/uploader/md5Provider/md5ComputationStrategies/md5ComputationSession.d.ts +7 -0
- package/dist/src/uploader/md5Provider/md5ComputationStrategies/md5ComputationSession.d.ts.map +1 -0
- package/dist/src/uploader/md5Provider/md5ComputationStrategies/md5ComputationSession.js +2 -0
- package/dist/src/uploader/md5Provider/md5ComputationStrategies/md5ComputationSession.js.map +1 -0
- package/dist/src/uploader/md5Provider/md5ComputationStrategies/md5ComputationStrategy.d.ts +6 -0
- package/dist/src/uploader/md5Provider/md5ComputationStrategies/md5ComputationStrategy.d.ts.map +1 -0
- package/dist/src/uploader/md5Provider/md5ComputationStrategies/md5ComputationStrategy.js +2 -0
- package/dist/src/uploader/md5Provider/md5ComputationStrategies/md5ComputationStrategy.js.map +1 -0
- package/dist/src/uploader/md5Provider/md5ComputationStrategies/md5ComputationStrategyFactory.d.ts +6 -0
- package/dist/src/uploader/md5Provider/md5ComputationStrategies/md5ComputationStrategyFactory.d.ts.map +1 -0
- package/dist/src/uploader/md5Provider/md5ComputationStrategies/md5ComputationStrategyFactory.js +2 -0
- package/dist/src/uploader/md5Provider/md5ComputationStrategies/md5ComputationStrategyFactory.js.map +1 -0
- package/dist/src/uploader/md5Provider/md5ComputationStrategies/node/nodeAsyncMD5ComputationStrategy.d.ts +7 -0
- package/dist/src/uploader/md5Provider/md5ComputationStrategies/node/nodeAsyncMD5ComputationStrategy.d.ts.map +1 -0
- package/dist/src/uploader/md5Provider/md5ComputationStrategies/node/nodeAsyncMD5ComputationStrategy.js +14 -0
- package/dist/src/uploader/md5Provider/md5ComputationStrategies/node/nodeAsyncMD5ComputationStrategy.js.map +1 -0
- package/dist/src/uploader/md5Provider/md5ComputationStrategies/web/computeBlobMD5.d.ts +2 -0
- package/dist/src/uploader/md5Provider/md5ComputationStrategies/web/computeBlobMD5.d.ts.map +1 -0
- package/dist/src/uploader/md5Provider/md5ComputationStrategies/web/computeBlobMD5.js +27 -0
- package/dist/src/uploader/md5Provider/md5ComputationStrategies/web/computeBlobMD5.js.map +1 -0
- package/dist/src/uploader/md5Provider/md5ComputationStrategies/web/md5WebWorker/md5.worker.d.ts +2 -0
- package/dist/src/uploader/md5Provider/md5ComputationStrategies/web/md5WebWorker/md5.worker.d.ts.map +1 -0
- package/dist/src/uploader/md5Provider/md5ComputationStrategies/web/md5WebWorker/md5.worker.js +5 -0
- package/dist/src/uploader/md5Provider/md5ComputationStrategies/web/md5WebWorker/md5.worker.js.map +1 -0
- package/dist/src/uploader/md5Provider/md5ComputationStrategies/web/md5WebWorker/md5WorkerMessages.d.ts +14 -0
- package/dist/src/uploader/md5Provider/md5ComputationStrategies/web/md5WebWorker/md5WorkerMessages.d.ts.map +1 -0
- package/dist/src/uploader/md5Provider/md5ComputationStrategies/web/md5WebWorker/md5WorkerMessages.js +2 -0
- package/dist/src/uploader/md5Provider/md5ComputationStrategies/web/md5WebWorker/md5WorkerMessages.js.map +1 -0
- package/dist/src/uploader/md5Provider/md5ComputationStrategies/web/md5WebWorker/md5WorkersManager.d.ts +17 -0
- package/dist/src/uploader/md5Provider/md5ComputationStrategies/web/md5WebWorker/md5WorkersManager.d.ts.map +1 -0
- package/dist/src/uploader/md5Provider/md5ComputationStrategies/web/md5WebWorker/md5WorkersManager.js +113 -0
- package/dist/src/uploader/md5Provider/md5ComputationStrategies/web/md5WebWorker/md5WorkersManager.js.map +1 -0
- package/dist/src/uploader/md5Provider/md5ComputationStrategies/web/md5WebWorker/registerMD5Worker.d.ts +7 -0
- package/dist/src/uploader/md5Provider/md5ComputationStrategies/web/md5WebWorker/registerMD5Worker.d.ts.map +1 -0
- package/dist/src/uploader/md5Provider/md5ComputationStrategies/web/md5WebWorker/registerMD5Worker.js +17 -0
- package/dist/src/uploader/md5Provider/md5ComputationStrategies/web/md5WebWorker/registerMD5Worker.js.map +1 -0
- package/dist/src/uploader/md5Provider/md5ComputationStrategies/web/webAsyncWebWorkerMD5ComputationStrategy.d.ts +9 -0
- package/dist/src/uploader/md5Provider/md5ComputationStrategies/web/webAsyncWebWorkerMD5ComputationStrategy.d.ts.map +1 -0
- package/dist/src/uploader/md5Provider/md5ComputationStrategies/web/webAsyncWebWorkerMD5ComputationStrategy.js +62 -0
- package/dist/src/uploader/md5Provider/md5ComputationStrategies/web/webAsyncWebWorkerMD5ComputationStrategy.js.map +1 -0
- package/dist/src/uploader/md5Provider/md5ComputationStrategies/web/webMD5ComputationStrategyFactory.d.ts +9 -0
- package/dist/src/uploader/md5Provider/md5ComputationStrategies/web/webMD5ComputationStrategyFactory.d.ts.map +1 -0
- package/dist/src/uploader/md5Provider/md5ComputationStrategies/web/webMD5ComputationStrategyFactory.js +41 -0
- package/dist/src/uploader/md5Provider/md5ComputationStrategies/web/webMD5ComputationStrategyFactory.js.map +1 -0
- package/dist/src/uploader/md5Provider/md5ComputationStrategies/web/webSyncMD5ComputationStrategy.d.ts +6 -0
- package/dist/src/uploader/md5Provider/md5ComputationStrategies/web/webSyncMD5ComputationStrategy.d.ts.map +1 -0
- package/dist/src/uploader/md5Provider/md5ComputationStrategies/web/webSyncMD5ComputationStrategy.js +9 -0
- package/dist/src/uploader/md5Provider/md5ComputationStrategies/web/webSyncMD5ComputationStrategy.js.map +1 -0
- package/dist/src/uploader/md5Provider/precomputedMD5Provider.d.ts +27 -0
- package/dist/src/uploader/md5Provider/precomputedMD5Provider.d.ts.map +1 -0
- package/dist/src/uploader/md5Provider/precomputedMD5Provider.js +189 -0
- package/dist/src/uploader/md5Provider/precomputedMD5Provider.js.map +1 -0
- package/dist/src/uploader/md5Provider/uploaderMD5Provider.d.ts +28 -0
- package/dist/src/uploader/md5Provider/uploaderMD5Provider.d.ts.map +1 -0
- package/dist/src/uploader/md5Provider/uploaderMD5Provider.js +2 -0
- package/dist/src/uploader/md5Provider/uploaderMD5Provider.js.map +1 -0
- package/dist/src/uploader/transferUpload.d.ts +4 -2
- package/dist/src/uploader/transferUpload.d.ts.map +1 -1
- package/dist/src/uploader/transferUpload.js +27 -9
- package/dist/src/uploader/transferUpload.js.map +1 -1
- package/dist/src/utils/api/dtos/sendFileChunkRequest.d.ts +1 -0
- package/dist/src/utils/api/dtos/sendFileChunkRequest.d.ts.map +1 -1
- package/dist/src/utils/api/dtos/sendFileChunkRequest.js.map +1 -1
- package/dist/src/utils/fileSystem/chunkStreamEncryptionData.d.ts +6 -0
- package/dist/src/utils/fileSystem/chunkStreamEncryptionData.d.ts.map +1 -0
- package/dist/src/utils/fileSystem/chunkStreamEncryptionData.js +2 -0
- package/dist/src/utils/fileSystem/chunkStreamEncryptionData.js.map +1 -0
- package/dist/src/utils/fileSystem/chunkStreamProvider.d.ts +0 -5
- package/dist/src/utils/fileSystem/chunkStreamProvider.d.ts.map +1 -1
- package/dist/src/utils/fileSystem/chunkStreamProvider.js.map +1 -1
- package/dist/src/utils/fileSystem/chunkStreamProviderFactory.d.ts +2 -2
- package/dist/src/utils/fileSystem/chunkStreamProviderFactory.d.ts.map +1 -1
- package/dist/src/utils/fileSystem/chunkStreamProviderFactory.js.map +1 -1
- package/dist/src/utils/fileSystem/node/nodeChunkStreamProvider.d.ts +2 -3
- package/dist/src/utils/fileSystem/node/nodeChunkStreamProvider.d.ts.map +1 -1
- package/dist/src/utils/fileSystem/node/nodeChunkStreamProvider.js +9 -28
- package/dist/src/utils/fileSystem/node/nodeChunkStreamProvider.js.map +1 -1
- package/dist/src/utils/fileSystem/node/nodeChunkStreamProviderFactory.d.ts +2 -2
- package/dist/src/utils/fileSystem/node/nodeChunkStreamProviderFactory.d.ts.map +1 -1
- package/dist/src/utils/fileSystem/node/nodeChunkStreamProviderFactory.js +1 -1
- package/dist/src/utils/fileSystem/node/nodeChunkStreamProviderFactory.js.map +1 -1
- package/dist/src/utils/fileSystem/web/chunkStreamProvider/webChunkStreamProvider.d.ts +2 -3
- package/dist/src/utils/fileSystem/web/chunkStreamProvider/webChunkStreamProvider.d.ts.map +1 -1
- package/dist/src/utils/fileSystem/web/chunkStreamProvider/webChunkStreamProvider.js +0 -19
- package/dist/src/utils/fileSystem/web/chunkStreamProvider/webChunkStreamProvider.js.map +1 -1
- package/dist/src/utils/fileSystem/web/webChunkStreamProviderFactory.d.ts +2 -2
- package/dist/src/utils/fileSystem/web/webChunkStreamProviderFactory.d.ts.map +1 -1
- package/dist/src/utils/fileSystem/web/webChunkStreamProviderFactory.js +1 -1
- package/dist/src/utils/fileSystem/web/webChunkStreamProviderFactory.js.map +1 -1
- package/package.json +5 -4
- package/dist/src/uploader/chunkStreamProviderFactory/nodeFileDetailsUploaderChunkStreamProviderFactory.d.ts +0 -9
- package/dist/src/uploader/chunkStreamProviderFactory/nodeFileDetailsUploaderChunkStreamProviderFactory.d.ts.map +0 -1
- package/dist/src/uploader/chunkStreamProviderFactory/nodeFileDetailsUploaderChunkStreamProviderFactory.js.map +0 -1
- package/dist/src/uploader/chunkStreamProviderFactory/webFileDetailsUploaderChunkStreamProviderFactory.d.ts +0 -9
- package/dist/src/uploader/chunkStreamProviderFactory/webFileDetailsUploaderChunkStreamProviderFactory.d.ts.map +0 -1
- package/dist/src/uploader/chunkStreamProviderFactory/webFileDetailsUploaderChunkStreamProviderFactory.js.map +0 -1
package/dist/src/uploader/md5Provider/md5ComputationStrategies/web/md5WebWorker/md5WorkersManager.js
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
const WorkerStartupTimeoutInMs = 10_000;
|
|
2
|
+
export default class MD5WebWorkersManager {
|
|
3
|
+
#createWorker;
|
|
4
|
+
#workers = [];
|
|
5
|
+
#roundRobinCounter = 0;
|
|
6
|
+
constructor(createWorker) {
|
|
7
|
+
if (!createWorker)
|
|
8
|
+
throw new Error(`CreateWorker method is not defined`);
|
|
9
|
+
this.#createWorker = createWorker;
|
|
10
|
+
}
|
|
11
|
+
hasAvailableWorkers() {
|
|
12
|
+
return this.#workers.length > 0;
|
|
13
|
+
}
|
|
14
|
+
getWorker() {
|
|
15
|
+
if (!this.hasAvailableWorkers())
|
|
16
|
+
throw new Error(`There are no available MD5 Web Workers`);
|
|
17
|
+
const workerIndex = this.#roundRobinCounter % this.#workers.length;
|
|
18
|
+
this.#roundRobinCounter = (this.#roundRobinCounter + 1) % this.#workers.length;
|
|
19
|
+
return this.#workers[workerIndex];
|
|
20
|
+
}
|
|
21
|
+
async createWorkers(workersCount, abortSignal) {
|
|
22
|
+
for (let i = 0; i < workersCount; i++) {
|
|
23
|
+
abortSignal?.throwIfAborted();
|
|
24
|
+
const worker = await this.createWorker(abortSignal);
|
|
25
|
+
this.#workers.push(worker);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
async createWorker(abortSignal) {
|
|
29
|
+
const worker = this.#createWorker();
|
|
30
|
+
try {
|
|
31
|
+
await this.waitUntilWorkerReady(worker, abortSignal);
|
|
32
|
+
abortSignal?.throwIfAborted();
|
|
33
|
+
this.addWorkerFailureListeners(worker);
|
|
34
|
+
return worker;
|
|
35
|
+
}
|
|
36
|
+
catch (error) {
|
|
37
|
+
worker.terminate();
|
|
38
|
+
throw error;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
addWorkerFailureListeners(worker) {
|
|
42
|
+
worker.addEventListener(`error`, this.workerErrorHandler);
|
|
43
|
+
worker.addEventListener(`messageerror`, this.workerMessageErrorHandler);
|
|
44
|
+
}
|
|
45
|
+
workerErrorHandler = (event) => {
|
|
46
|
+
this.workerFailureCleanup(event.currentTarget);
|
|
47
|
+
};
|
|
48
|
+
workerMessageErrorHandler = (event) => {
|
|
49
|
+
this.workerFailureCleanup(event.currentTarget);
|
|
50
|
+
};
|
|
51
|
+
removeWorkerFailureListeners(worker) {
|
|
52
|
+
worker.removeEventListener(`error`, this.workerErrorHandler);
|
|
53
|
+
worker.removeEventListener(`messageerror`, this.workerMessageErrorHandler);
|
|
54
|
+
}
|
|
55
|
+
workerFailureCleanup(worker) {
|
|
56
|
+
this.removeWorkerFailureListeners(worker);
|
|
57
|
+
this.deleteWorker(worker);
|
|
58
|
+
worker.terminate();
|
|
59
|
+
}
|
|
60
|
+
deleteWorker(worker) {
|
|
61
|
+
const index = this.#workers.indexOf(worker);
|
|
62
|
+
if (index === -1)
|
|
63
|
+
return;
|
|
64
|
+
this.#workers.splice(index, 1);
|
|
65
|
+
if (this.#workers.length === 0) {
|
|
66
|
+
this.#roundRobinCounter = 0;
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
if (index < this.#roundRobinCounter)
|
|
70
|
+
this.#roundRobinCounter -= 1;
|
|
71
|
+
this.#roundRobinCounter %= this.#workers.length;
|
|
72
|
+
}
|
|
73
|
+
waitUntilWorkerReady(worker, abortSignal) {
|
|
74
|
+
return new Promise((resolve, reject) => {
|
|
75
|
+
const cleanup = () => {
|
|
76
|
+
clearTimeout(timeout);
|
|
77
|
+
worker.removeEventListener(`message`, readyListener);
|
|
78
|
+
worker.removeEventListener(`error`, errorListener);
|
|
79
|
+
worker.removeEventListener(`messageerror`, messageErrorListener);
|
|
80
|
+
abortSignal?.removeEventListener(`abort`, abortListener);
|
|
81
|
+
};
|
|
82
|
+
const fail = (error) => {
|
|
83
|
+
cleanup();
|
|
84
|
+
reject(error);
|
|
85
|
+
};
|
|
86
|
+
const readyListener = (event) => {
|
|
87
|
+
if (event.data?.type !== `md5-ready`)
|
|
88
|
+
return;
|
|
89
|
+
cleanup();
|
|
90
|
+
resolve();
|
|
91
|
+
};
|
|
92
|
+
const errorListener = (event) => fail(event.error instanceof Error ? event.error : new Error(event.message || `MD5 worker failed to start`));
|
|
93
|
+
const messageErrorListener = () => fail(new Error(`Cannot deserialize MD5 worker startup response`));
|
|
94
|
+
const abortListener = () => fail(abortSignal?.reason ?? new Error(`Aborted`));
|
|
95
|
+
const timeout = setTimeout(() => fail(new Error(`MD5 worker startup timed out`)), WorkerStartupTimeoutInMs);
|
|
96
|
+
worker.addEventListener(`message`, readyListener);
|
|
97
|
+
worker.addEventListener(`error`, errorListener, { once: true });
|
|
98
|
+
worker.addEventListener(`messageerror`, messageErrorListener, { once: true });
|
|
99
|
+
abortSignal?.addEventListener(`abort`, abortListener, { once: true });
|
|
100
|
+
if (abortSignal?.aborted)
|
|
101
|
+
abortListener();
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
dispose() {
|
|
105
|
+
this.#workers.forEach(worker => {
|
|
106
|
+
this.removeWorkerFailureListeners(worker);
|
|
107
|
+
worker.terminate();
|
|
108
|
+
});
|
|
109
|
+
this.#workers = [];
|
|
110
|
+
this.#roundRobinCounter = 0;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
//# sourceMappingURL=md5WorkersManager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"md5WorkersManager.js","sourceRoot":"","sources":["../../../../../../../src/uploader/md5Provider/md5ComputationStrategies/web/md5WebWorker/md5WorkersManager.ts"],"names":[],"mappings":"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","sourcesContent":["import { MD5WorkerReady } from \"./md5WorkerMessages.js\";\n\nconst WorkerStartupTimeoutInMs = 10_000;\n\nexport default class MD5WebWorkersManager {\n #createWorker: () => Worker;\n\n #workers: Worker[] = [];\n\n #roundRobinCounter = 0;\n\n constructor(createWorker: () => Worker) {\n if (!createWorker)\n throw new Error(`CreateWorker method is not defined`);\n\n this.#createWorker = createWorker;\n }\n\n hasAvailableWorkers(): boolean {\n return this.#workers.length > 0;\n }\n\n getWorker(): Worker {\n if (!this.hasAvailableWorkers())\n throw new Error(`There are no available MD5 Web Workers`);\n\n const workerIndex = this.#roundRobinCounter % this.#workers.length;\n\n this.#roundRobinCounter = (this.#roundRobinCounter + 1) % this.#workers.length;\n\n return this.#workers[workerIndex];\n }\n\n async createWorkers(workersCount: number, abortSignal?: AbortSignal): Promise<void> {\n for (let i = 0; i < workersCount; i++) {\n abortSignal?.throwIfAborted();\n\n const worker = await this.createWorker(abortSignal);\n this.#workers.push(worker);\n }\n }\n\n private async createWorker(abortSignal?: AbortSignal): Promise<Worker> {\n const worker = this.#createWorker();\n\n try {\n await this.waitUntilWorkerReady(worker, abortSignal);\n\n abortSignal?.throwIfAborted();\n\n this.addWorkerFailureListeners(worker);\n\n return worker;\n }\n catch (error) {\n worker.terminate();\n throw error;\n }\n }\n\n private addWorkerFailureListeners(worker: Worker) {\n worker.addEventListener(`error`, this.workerErrorHandler);\n worker.addEventListener(`messageerror`, this.workerMessageErrorHandler);\n }\n\n private workerErrorHandler = (event: ErrorEvent) => {\n this.workerFailureCleanup(event.currentTarget as Worker);\n };\n\n private workerMessageErrorHandler = (event: MessageEvent) => {\n this.workerFailureCleanup(event.currentTarget as Worker);\n };\n\n private removeWorkerFailureListeners(worker: Worker) {\n worker.removeEventListener(`error`, this.workerErrorHandler);\n worker.removeEventListener(`messageerror`, this.workerMessageErrorHandler);\n }\n\n private workerFailureCleanup(worker: Worker) {\n this.removeWorkerFailureListeners(worker);\n this.deleteWorker(worker);\n worker.terminate();\n }\n\n private deleteWorker(worker: Worker) {\n const index = this.#workers.indexOf(worker);\n\n if (index === -1)\n return;\n\n this.#workers.splice(index, 1);\n\n if (this.#workers.length === 0) {\n this.#roundRobinCounter = 0;\n return;\n }\n\n if (index < this.#roundRobinCounter)\n this.#roundRobinCounter -= 1;\n\n this.#roundRobinCounter %= this.#workers.length;\n }\n\n private waitUntilWorkerReady(worker: Worker, abortSignal?: AbortSignal): Promise<void> {\n return new Promise((resolve, reject) => {\n const cleanup = () => {\n clearTimeout(timeout);\n\n worker.removeEventListener(`message`, readyListener);\n worker.removeEventListener(`error`, errorListener);\n worker.removeEventListener(`messageerror`, messageErrorListener);\n abortSignal?.removeEventListener(`abort`, abortListener);\n };\n\n const fail = (error: unknown) => {\n cleanup();\n reject(error);\n };\n\n const readyListener = (event: MessageEvent<MD5WorkerReady>) => {\n if (event.data?.type !== `md5-ready`)\n return;\n\n cleanup();\n resolve();\n };\n\n const errorListener = (event: ErrorEvent) => fail(event.error instanceof Error ? event.error : new Error(event.message || `MD5 worker failed to start`));\n const messageErrorListener = () => fail(new Error(`Cannot deserialize MD5 worker startup response`));\n const abortListener = () => fail(abortSignal?.reason ?? new Error(`Aborted`));\n const timeout = setTimeout(() => fail(new Error(`MD5 worker startup timed out`)), WorkerStartupTimeoutInMs);\n\n worker.addEventListener(`message`, readyListener);\n worker.addEventListener(`error`, errorListener, { once: true });\n worker.addEventListener(`messageerror`, messageErrorListener, { once: true });\n abortSignal?.addEventListener(`abort`, abortListener, { once: true });\n\n if (abortSignal?.aborted)\n abortListener();\n });\n }\n\n dispose() {\n this.#workers.forEach(worker => {\n this.removeWorkerFailureListeners(worker);\n worker.terminate();\n });\n\n this.#workers = [];\n this.#roundRobinCounter = 0;\n }\n}"]}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { MD5WorkerRequest, MD5WorkerResponse } from "./md5WorkerMessages.js";
|
|
2
|
+
export default function registerMD5Worker(worker: MD5WorkerScope): void;
|
|
3
|
+
export interface MD5WorkerScope {
|
|
4
|
+
addEventListener(type: `message`, listener: (event: MessageEvent<MD5WorkerRequest>) => void): void;
|
|
5
|
+
postMessage(message: MD5WorkerResponse): void;
|
|
6
|
+
}
|
|
7
|
+
//# sourceMappingURL=registerMD5Worker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registerMD5Worker.d.ts","sourceRoot":"","sources":["../../../../../../../src/uploader/md5Provider/md5ComputationStrategies/web/md5WebWorker/registerMD5Worker.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAElF,MAAM,CAAC,OAAO,UAAU,iBAAiB,CAAC,MAAM,EAAE,cAAc,GAAG,IAAI,CAetE;AAED,MAAM,WAAW,cAAc;IAC3B,gBAAgB,CAAC,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,YAAY,CAAC,gBAAgB,CAAC,KAAK,IAAI,GAAG,IAAI,CAAC;IACnG,WAAW,CAAC,OAAO,EAAE,iBAAiB,GAAG,IAAI,CAAC;CACjD"}
|
package/dist/src/uploader/md5Provider/md5ComputationStrategies/web/md5WebWorker/registerMD5Worker.js
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import computeBlobMD5 from "../computeBlobMD5.js";
|
|
2
|
+
export default function registerMD5Worker(worker) {
|
|
3
|
+
const compute = async ({ workId, chunkBlob, format }) => {
|
|
4
|
+
try {
|
|
5
|
+
const md5 = await computeBlobMD5(chunkBlob, format);
|
|
6
|
+
worker.postMessage({ workId, result: { isSuccess: true, md5 } });
|
|
7
|
+
}
|
|
8
|
+
catch (error) {
|
|
9
|
+
const responseError = new Error(error instanceof Error ? error.message : String(error));
|
|
10
|
+
worker.postMessage({ workId, result: { isSuccess: false, error: responseError } });
|
|
11
|
+
}
|
|
12
|
+
};
|
|
13
|
+
worker.addEventListener(`message`, (event) => {
|
|
14
|
+
compute(event.data);
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=registerMD5Worker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registerMD5Worker.js","sourceRoot":"","sources":["../../../../../../../src/uploader/md5Provider/md5ComputationStrategies/web/md5WebWorker/registerMD5Worker.ts"],"names":[],"mappings":"AAAA,OAAO,cAAc,MAAM,sBAAsB,CAAC;AAIlD,MAAM,CAAC,OAAO,UAAU,iBAAiB,CAAC,MAAsB;IAC5D,MAAM,OAAO,GAAG,KAAK,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAoB,EAAE,EAAE;QACtE,IAAI,CAAC;YACD,MAAM,GAAG,GAAG,MAAM,cAAc,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;YACpD,MAAM,CAAC,WAAW,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC;QACrE,CAAC;QACD,OAAO,KAAK,EAAE,CAAC;YACX,MAAM,aAAa,GAAG,IAAI,KAAK,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;YACxF,MAAM,CAAC,WAAW,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,KAAK,EAAE,aAAa,EAAE,EAAE,CAAC,CAAC;QACvF,CAAC;IACL,CAAC,CAAC;IAEF,MAAM,CAAC,gBAAgB,CAAC,SAAS,EAAE,CAAC,KAAqC,EAAE,EAAE;QACzE,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACxB,CAAC,CAAC,CAAC;AACP,CAAC","sourcesContent":["import computeBlobMD5 from \"../computeBlobMD5.js\";\n\nimport type { MD5WorkerRequest, MD5WorkerResponse } from \"./md5WorkerMessages.js\";\n\nexport default function registerMD5Worker(worker: MD5WorkerScope): void {\n const compute = async ({ workId, chunkBlob, format }: MD5WorkerRequest) => {\n try {\n const md5 = await computeBlobMD5(chunkBlob, format);\n worker.postMessage({ workId, result: { isSuccess: true, md5 } });\n }\n catch (error) {\n const responseError = new Error(error instanceof Error ? error.message : String(error));\n worker.postMessage({ workId, result: { isSuccess: false, error: responseError } });\n }\n };\n\n worker.addEventListener(`message`, (event: MessageEvent<MD5WorkerRequest>) => {\n compute(event.data);\n });\n}\n\nexport interface MD5WorkerScope {\n addEventListener(type: `message`, listener: (event: MessageEvent<MD5WorkerRequest>) => void): void;\n postMessage(message: MD5WorkerResponse): void;\n}"]}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type MD5ComputationStrategy from "../md5ComputationStrategy.js";
|
|
2
|
+
import type ChunkStreamProvider from "../../../../utils/fileSystem/chunkStreamProvider.js";
|
|
3
|
+
import type MD5WebWorkersManager from "./md5WebWorker/md5WorkersManager.js";
|
|
4
|
+
export default class WebAsyncWebWorkerMD5ComputationStrategy implements MD5ComputationStrategy {
|
|
5
|
+
#private;
|
|
6
|
+
constructor(workersManager: MD5WebWorkersManager);
|
|
7
|
+
computeMD5(chunkStreamProvider: ChunkStreamProvider, format: string, abortSignal?: AbortSignal): Promise<string>;
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=webAsyncWebWorkerMD5ComputationStrategy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"webAsyncWebWorkerMD5ComputationStrategy.d.ts","sourceRoot":"","sources":["../../../../../../src/uploader/md5Provider/md5ComputationStrategies/web/webAsyncWebWorkerMD5ComputationStrategy.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,sBAAsB,MAAM,8BAA8B,CAAC;AACvE,OAAO,KAAK,mBAAmB,MAAM,qDAAqD,CAAC;AAE3F,OAAO,KAAK,oBAAoB,MAAM,qCAAqC,CAAC;AAE5E,MAAM,CAAC,OAAO,OAAO,uCAAwC,YAAW,sBAAsB;;gBAG9E,cAAc,EAAE,oBAAoB;IAO1C,UAAU,CAAC,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC;CAqEzH"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { v4 as guid } from "uuid";
|
|
2
|
+
export default class WebAsyncWebWorkerMD5ComputationStrategy {
|
|
3
|
+
#workersManager;
|
|
4
|
+
constructor(workersManager) {
|
|
5
|
+
if (!workersManager)
|
|
6
|
+
throw new Error(`Workers manager is not defined`);
|
|
7
|
+
this.#workersManager = workersManager;
|
|
8
|
+
}
|
|
9
|
+
async computeMD5(chunkStreamProvider, format, abortSignal) {
|
|
10
|
+
abortSignal?.throwIfAborted();
|
|
11
|
+
if (!this.#workersManager.hasAvailableWorkers())
|
|
12
|
+
throw new Error(`There are no available MD5 Web Workers`);
|
|
13
|
+
return new Promise((resolve, reject) => {
|
|
14
|
+
let worker;
|
|
15
|
+
const workId = guid();
|
|
16
|
+
const cleanup = () => {
|
|
17
|
+
worker?.removeEventListener(`message`, resultListener);
|
|
18
|
+
worker?.removeEventListener(`error`, errorListener);
|
|
19
|
+
worker?.removeEventListener(`messageerror`, messageErrorListener);
|
|
20
|
+
abortSignal?.removeEventListener(`abort`, abortListener);
|
|
21
|
+
};
|
|
22
|
+
const succeed = (md5) => {
|
|
23
|
+
cleanup();
|
|
24
|
+
resolve(md5);
|
|
25
|
+
};
|
|
26
|
+
const fail = (error) => {
|
|
27
|
+
cleanup();
|
|
28
|
+
reject(error);
|
|
29
|
+
};
|
|
30
|
+
const errorListener = (event) => {
|
|
31
|
+
fail(event.error instanceof Error ? event.error : new Error(event.message || `MD5 worker failed`));
|
|
32
|
+
};
|
|
33
|
+
const messageErrorListener = () => fail(new Error(`Cannot deserialize MD5 worker response`));
|
|
34
|
+
const abortListener = () => fail(abortSignal?.reason ?? new Error(`Aborted`));
|
|
35
|
+
const resultListener = (event) => {
|
|
36
|
+
if (event.data?.workId !== workId)
|
|
37
|
+
return;
|
|
38
|
+
if (event.data.result.isSuccess)
|
|
39
|
+
succeed(event.data.result.md5);
|
|
40
|
+
else
|
|
41
|
+
fail(event.data.result.error);
|
|
42
|
+
};
|
|
43
|
+
abortSignal?.addEventListener(`abort`, abortListener, { once: true });
|
|
44
|
+
const dispatchWorkToWebWorker = async () => {
|
|
45
|
+
try {
|
|
46
|
+
const chunkBlob = await chunkStreamProvider.getChunkBlob();
|
|
47
|
+
abortSignal?.throwIfAborted();
|
|
48
|
+
worker = this.#workersManager.getWorker();
|
|
49
|
+
worker.addEventListener(`message`, resultListener);
|
|
50
|
+
worker.addEventListener(`error`, errorListener, { once: true });
|
|
51
|
+
worker.addEventListener(`messageerror`, messageErrorListener, { once: true });
|
|
52
|
+
worker.postMessage({ workId, chunkBlob, format });
|
|
53
|
+
}
|
|
54
|
+
catch (error) {
|
|
55
|
+
fail(error);
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
dispatchWorkToWebWorker();
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=webAsyncWebWorkerMD5ComputationStrategy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"webAsyncWebWorkerMD5ComputationStrategy.js","sourceRoot":"","sources":["../../../../../../src/uploader/md5Provider/md5ComputationStrategies/web/webAsyncWebWorkerMD5ComputationStrategy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,IAAI,IAAI,EAAE,MAAM,MAAM,CAAC;AAOlC,MAAM,CAAC,OAAO,OAAO,uCAAuC;IACxD,eAAe,CAAuB;IAEtC,YAAY,cAAoC;QAC5C,IAAI,CAAC,cAAc;YACf,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC;QAEtD,IAAI,CAAC,eAAe,GAAG,cAAc,CAAC;IAC1C,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,mBAAwC,EAAE,MAAc,EAAE,WAAyB;QAChG,WAAW,EAAE,cAAc,EAAE,CAAC;QAE9B,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,mBAAmB,EAAE;YAC3C,MAAM,IAAI,KAAK,CAAC,wCAAwC,CAAC,CAAC;QAE9D,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACnC,IAAI,MAA0B,CAAC;YAE/B,MAAM,MAAM,GAAG,IAAI,EAAE,CAAC;YAEtB,MAAM,OAAO,GAAG,GAAG,EAAE;gBACjB,MAAM,EAAE,mBAAmB,CAAC,SAAS,EAAE,cAAc,CAAC,CAAC;gBACvD,MAAM,EAAE,mBAAmB,CAAC,OAAO,EAAE,aAAa,CAAC,CAAC;gBACpD,MAAM,EAAE,mBAAmB,CAAC,cAAc,EAAE,oBAAoB,CAAC,CAAC;gBAClE,WAAW,EAAE,mBAAmB,CAAC,OAAO,EAAE,aAAa,CAAC,CAAC;YAC7D,CAAC,CAAC;YAEF,MAAM,OAAO,GAAG,CAAC,GAAW,EAAE,EAAE;gBAC5B,OAAO,EAAE,CAAC;gBACV,OAAO,CAAC,GAAG,CAAC,CAAC;YACjB,CAAC,CAAC;YAEF,MAAM,IAAI,GAAG,CAAC,KAAc,EAAE,EAAE;gBAC5B,OAAO,EAAE,CAAC;gBACV,MAAM,CAAC,KAAK,CAAC,CAAC;YAClB,CAAC,CAAC;YAEF,MAAM,aAAa,GAAG,CAAC,KAAiB,EAAE,EAAE;gBACxC,IAAI,CAAC,KAAK,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,KAAK,CAAC,OAAO,IAAI,mBAAmB,CAAC,CAAC,CAAC;YACvG,CAAC,CAAC;YAEF,MAAM,oBAAoB,GAAG,GAAG,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,wCAAwC,CAAC,CAAC,CAAC;YAC7F,MAAM,aAAa,GAAG,GAAG,EAAE,CAAC,IAAI,CAAC,WAAW,EAAE,MAAM,IAAI,IAAI,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC;YAE9E,MAAM,cAAc,GAAG,CAAC,KAAsC,EAAE,EAAE;gBAC9D,IAAI,KAAK,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM;oBAC7B,OAAO;gBAEX,IAAI,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS;oBAC3B,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;;oBAE/B,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACtC,CAAC,CAAC;YAEF,WAAW,EAAE,gBAAgB,CAAC,OAAO,EAAE,aAAa,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;YAEtE,MAAM,uBAAuB,GAAG,KAAK,IAAI,EAAE;gBACvC,IAAI,CAAC;oBACD,MAAM,SAAS,GAAG,MAAM,mBAAmB,CAAC,YAAY,EAAE,CAAC;oBAE3D,WAAW,EAAE,cAAc,EAAE,CAAC;oBAE9B,MAAM,GAAG,IAAI,CAAC,eAAe,CAAC,SAAS,EAAE,CAAC;oBAE1C,MAAM,CAAC,gBAAgB,CAAC,SAAS,EAAE,cAAc,CAAC,CAAC;oBACnD,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,aAAa,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;oBAChE,MAAM,CAAC,gBAAgB,CAAC,cAAc,EAAE,oBAAoB,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;oBAE9E,MAAM,CAAC,WAAW,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAA6B,CAAC,CAAC;gBACjF,CAAC;gBACD,OAAO,KAAK,EAAE,CAAC;oBACX,IAAI,CAAC,KAAK,CAAC,CAAC;gBAChB,CAAC;YACL,CAAC,CAAC;YAEF,uBAAuB,EAAE,CAAC;QAC9B,CAAC,CAAC,CAAC;IACP,CAAC;CACJ","sourcesContent":["import { v4 as guid } from \"uuid\";\n\nimport type MD5ComputationStrategy from \"../md5ComputationStrategy.js\";\nimport type ChunkStreamProvider from \"../../../../utils/fileSystem/chunkStreamProvider.js\";\nimport type { MD5WorkerRequest, MD5WorkerResponse } from \"./md5WebWorker/md5WorkerMessages.js\";\nimport type MD5WebWorkersManager from \"./md5WebWorker/md5WorkersManager.js\";\n\nexport default class WebAsyncWebWorkerMD5ComputationStrategy implements MD5ComputationStrategy {\n #workersManager: MD5WebWorkersManager;\n\n constructor(workersManager: MD5WebWorkersManager) {\n if (!workersManager)\n throw new Error(`Workers manager is not defined`);\n\n this.#workersManager = workersManager;\n }\n\n async computeMD5(chunkStreamProvider: ChunkStreamProvider, format: string, abortSignal?: AbortSignal): Promise<string> {\n abortSignal?.throwIfAborted();\n\n if (!this.#workersManager.hasAvailableWorkers())\n throw new Error(`There are no available MD5 Web Workers`);\n\n return new Promise((resolve, reject) => {\n let worker: Worker | undefined;\n\n const workId = guid();\n\n const cleanup = () => {\n worker?.removeEventListener(`message`, resultListener);\n worker?.removeEventListener(`error`, errorListener);\n worker?.removeEventListener(`messageerror`, messageErrorListener);\n abortSignal?.removeEventListener(`abort`, abortListener);\n };\n\n const succeed = (md5: string) => {\n cleanup();\n resolve(md5);\n };\n\n const fail = (error: unknown) => {\n cleanup();\n reject(error);\n };\n\n const errorListener = (event: ErrorEvent) => {\n fail(event.error instanceof Error ? event.error : new Error(event.message || `MD5 worker failed`));\n };\n\n const messageErrorListener = () => fail(new Error(`Cannot deserialize MD5 worker response`));\n const abortListener = () => fail(abortSignal?.reason ?? new Error(`Aborted`));\n\n const resultListener = (event: MessageEvent<MD5WorkerResponse>) => {\n if (event.data?.workId !== workId)\n return;\n\n if (event.data.result.isSuccess)\n succeed(event.data.result.md5);\n else\n fail(event.data.result.error);\n };\n\n abortSignal?.addEventListener(`abort`, abortListener, { once: true });\n\n const dispatchWorkToWebWorker = async () => {\n try {\n const chunkBlob = await chunkStreamProvider.getChunkBlob();\n\n abortSignal?.throwIfAborted();\n\n worker = this.#workersManager.getWorker();\n\n worker.addEventListener(`message`, resultListener);\n worker.addEventListener(`error`, errorListener, { once: true });\n worker.addEventListener(`messageerror`, messageErrorListener, { once: true });\n\n worker.postMessage({ workId, chunkBlob, format } satisfies MD5WorkerRequest);\n }\n catch (error) {\n fail(error);\n }\n };\n\n dispatchWorkToWebWorker();\n });\n }\n}"]}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type MD5ComputationStrategyFactory from "../md5ComputationStrategyFactory.js";
|
|
2
|
+
import type MD5ComputationSession from "../md5ComputationSession.js";
|
|
3
|
+
export default class WebMD5ComputationStrategyFactory implements MD5ComputationStrategyFactory {
|
|
4
|
+
#private;
|
|
5
|
+
constructor(createWorker: () => Worker, workersCount: number, onFallback: (error: Error) => void);
|
|
6
|
+
createSession(abortSignal?: AbortSignal): Promise<MD5ComputationSession>;
|
|
7
|
+
private getSyncStrategy;
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=webMD5ComputationStrategyFactory.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"webMD5ComputationStrategyFactory.d.ts","sourceRoot":"","sources":["../../../../../../src/uploader/md5Provider/md5ComputationStrategies/web/webMD5ComputationStrategyFactory.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,6BAA6B,MAAM,qCAAqC,CAAC;AACrF,OAAO,KAAK,qBAAqB,MAAM,6BAA6B,CAAC;AAErE,MAAM,CAAC,OAAO,OAAO,gCAAiC,YAAW,6BAA6B;;gBAK9E,YAAY,EAAE,MAAM,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI;IAS1F,aAAa,CAAC,WAAW,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,qBAAqB,CAAC;IAiC9E,OAAO,CAAC,eAAe;CAG1B"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import WebAsyncWebWorkerMD5ComputationStrategy from "./webAsyncWebWorkerMD5ComputationStrategy.js";
|
|
2
|
+
import WebSyncMD5ComputationStrategy from "./webSyncMD5ComputationStrategy.js";
|
|
3
|
+
import MD5WebWorkersManager from "./md5WebWorker/md5WorkersManager.js";
|
|
4
|
+
export default class WebMD5ComputationStrategyFactory {
|
|
5
|
+
#createWorker;
|
|
6
|
+
#workersCount;
|
|
7
|
+
#onFallback;
|
|
8
|
+
constructor(createWorker, workersCount, onFallback) {
|
|
9
|
+
if (!Number.isSafeInteger(workersCount) || workersCount < 1)
|
|
10
|
+
throw new Error(`MD5 workers count must be a positive integer`);
|
|
11
|
+
this.#createWorker = createWorker;
|
|
12
|
+
this.#workersCount = workersCount;
|
|
13
|
+
this.#onFallback = onFallback;
|
|
14
|
+
}
|
|
15
|
+
async createSession(abortSignal) {
|
|
16
|
+
abortSignal?.throwIfAborted();
|
|
17
|
+
let workersManager;
|
|
18
|
+
const dispose = () => {
|
|
19
|
+
workersManager?.dispose();
|
|
20
|
+
workersManager = undefined;
|
|
21
|
+
};
|
|
22
|
+
try {
|
|
23
|
+
workersManager = new MD5WebWorkersManager(this.#createWorker);
|
|
24
|
+
await workersManager.createWorkers(this.#workersCount, abortSignal);
|
|
25
|
+
abortSignal?.throwIfAborted();
|
|
26
|
+
const strategy = new WebAsyncWebWorkerMD5ComputationStrategy(workersManager);
|
|
27
|
+
return { strategy, dispose };
|
|
28
|
+
}
|
|
29
|
+
catch (error) {
|
|
30
|
+
dispose();
|
|
31
|
+
if (abortSignal?.aborted)
|
|
32
|
+
throw abortSignal.reason ?? new Error(`Aborted`);
|
|
33
|
+
this.#onFallback(error instanceof Error ? error : new Error(String(error)));
|
|
34
|
+
return this.getSyncStrategy();
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
getSyncStrategy() {
|
|
38
|
+
return { strategy: new WebSyncMD5ComputationStrategy(), dispose: () => { } };
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=webMD5ComputationStrategyFactory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"webMD5ComputationStrategyFactory.js","sourceRoot":"","sources":["../../../../../../src/uploader/md5Provider/md5ComputationStrategies/web/webMD5ComputationStrategyFactory.ts"],"names":[],"mappings":"AAAA,OAAO,uCAAuC,MAAM,8CAA8C,CAAC;AACnG,OAAO,6BAA6B,MAAM,oCAAoC,CAAC;AAC/E,OAAO,oBAAoB,MAAM,qCAAqC,CAAC;AAKvE,MAAM,CAAC,OAAO,OAAO,gCAAgC;IACxC,aAAa,CAAe;IAC5B,aAAa,CAAS;IACtB,WAAW,CAAyB;IAE7C,YAAY,YAA0B,EAAE,YAAoB,EAAE,UAAkC;QAC5F,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,YAAY,CAAC,IAAI,YAAY,GAAG,CAAC;YACvD,MAAM,IAAI,KAAK,CAAC,8CAA8C,CAAC,CAAC;QAEpE,IAAI,CAAC,aAAa,GAAG,YAAY,CAAC;QAClC,IAAI,CAAC,aAAa,GAAG,YAAY,CAAC;QAClC,IAAI,CAAC,WAAW,GAAG,UAAU,CAAC;IAClC,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,WAAyB;QACzC,WAAW,EAAE,cAAc,EAAE,CAAC;QAE9B,IAAI,cAAgD,CAAC;QAErD,MAAM,OAAO,GAAG,GAAG,EAAE;YACjB,cAAc,EAAE,OAAO,EAAE,CAAC;YAC1B,cAAc,GAAG,SAAS,CAAC;QAC/B,CAAC,CAAC;QAEF,IAAI,CAAC;YACD,cAAc,GAAG,IAAI,oBAAoB,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;YAE9D,MAAM,cAAc,CAAC,aAAa,CAAC,IAAI,CAAC,aAAa,EAAE,WAAW,CAAC,CAAC;YAEpE,WAAW,EAAE,cAAc,EAAE,CAAC;YAE9B,MAAM,QAAQ,GAAG,IAAI,uCAAuC,CAAC,cAAc,CAAC,CAAC;YAE7E,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC;QACjC,CAAC;QACD,OAAO,KAAK,EAAE,CAAC;YACX,OAAO,EAAE,CAAC;YAEV,IAAI,WAAW,EAAE,OAAO;gBACpB,MAAM,WAAW,CAAC,MAAM,IAAI,IAAI,KAAK,CAAC,SAAS,CAAC,CAAC;YAErD,IAAI,CAAC,WAAW,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;YAE5E,OAAO,IAAI,CAAC,eAAe,EAAE,CAAC;QAClC,CAAC;IACL,CAAC;IAEO,eAAe;QACnB,OAAO,EAAE,QAAQ,EAAE,IAAI,6BAA6B,EAAE,EAAE,OAAO,EAAE,GAAG,EAAE,GAAG,CAAC,EAAE,CAAC;IACjF,CAAC;CACJ","sourcesContent":["import WebAsyncWebWorkerMD5ComputationStrategy from \"./webAsyncWebWorkerMD5ComputationStrategy.js\";\nimport WebSyncMD5ComputationStrategy from \"./webSyncMD5ComputationStrategy.js\";\nimport MD5WebWorkersManager from \"./md5WebWorker/md5WorkersManager.js\";\n\nimport type MD5ComputationStrategyFactory from \"../md5ComputationStrategyFactory.js\";\nimport type MD5ComputationSession from \"../md5ComputationSession.js\";\n\nexport default class WebMD5ComputationStrategyFactory implements MD5ComputationStrategyFactory {\n readonly #createWorker: () => Worker;\n readonly #workersCount: number;\n readonly #onFallback: (error: Error) => void;\n\n constructor(createWorker: () => Worker, workersCount: number, onFallback: (error: Error) => void) {\n if (!Number.isSafeInteger(workersCount) || workersCount < 1)\n throw new Error(`MD5 workers count must be a positive integer`);\n\n this.#createWorker = createWorker;\n this.#workersCount = workersCount;\n this.#onFallback = onFallback;\n }\n\n async createSession(abortSignal?: AbortSignal): Promise<MD5ComputationSession> {\n abortSignal?.throwIfAborted();\n\n let workersManager: MD5WebWorkersManager | undefined;\n\n const dispose = () => {\n workersManager?.dispose();\n workersManager = undefined;\n };\n\n try {\n workersManager = new MD5WebWorkersManager(this.#createWorker);\n\n await workersManager.createWorkers(this.#workersCount, abortSignal);\n\n abortSignal?.throwIfAborted();\n\n const strategy = new WebAsyncWebWorkerMD5ComputationStrategy(workersManager);\n\n return { strategy, dispose };\n }\n catch (error) {\n dispose();\n\n if (abortSignal?.aborted)\n throw abortSignal.reason ?? new Error(`Aborted`);\n\n this.#onFallback(error instanceof Error ? error : new Error(String(error)));\n\n return this.getSyncStrategy();\n }\n }\n\n private getSyncStrategy(): MD5ComputationSession | PromiseLike<MD5ComputationSession> {\n return { strategy: new WebSyncMD5ComputationStrategy(), dispose: () => { } };\n }\n}"]}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type MD5ComputationStrategy from "../md5ComputationStrategy.js";
|
|
2
|
+
import type ChunkStreamProvider from "../../../../utils/fileSystem/chunkStreamProvider.js";
|
|
3
|
+
export default class WebSyncMD5ComputationStrategy implements MD5ComputationStrategy {
|
|
4
|
+
computeMD5(chunkStreamProvider: ChunkStreamProvider, format: string, _abortSignal?: AbortSignal): Promise<string>;
|
|
5
|
+
}
|
|
6
|
+
//# sourceMappingURL=webSyncMD5ComputationStrategy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"webSyncMD5ComputationStrategy.d.ts","sourceRoot":"","sources":["../../../../../../src/uploader/md5Provider/md5ComputationStrategies/web/webSyncMD5ComputationStrategy.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,sBAAsB,MAAM,8BAA8B,CAAC;AACvE,OAAO,KAAK,mBAAmB,MAAM,qDAAqD,CAAC;AAE3F,MAAM,CAAC,OAAO,OAAO,6BAA8B,YAAW,sBAAsB;IAE1E,UAAU,CAAC,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC;CAK1H"}
|
package/dist/src/uploader/md5Provider/md5ComputationStrategies/web/webSyncMD5ComputationStrategy.js
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import computeBlobMD5 from "./computeBlobMD5.js";
|
|
2
|
+
export default class WebSyncMD5ComputationStrategy {
|
|
3
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
4
|
+
async computeMD5(chunkStreamProvider, format, _abortSignal) {
|
|
5
|
+
const chunkBlob = await chunkStreamProvider.getChunkBlob();
|
|
6
|
+
return await computeBlobMD5(chunkBlob, format);
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=webSyncMD5ComputationStrategy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"webSyncMD5ComputationStrategy.js","sourceRoot":"","sources":["../../../../../../src/uploader/md5Provider/md5ComputationStrategies/web/webSyncMD5ComputationStrategy.ts"],"names":[],"mappings":"AAAA,OAAO,cAAc,MAAM,qBAAqB,CAAC;AAKjD,MAAM,CAAC,OAAO,OAAO,6BAA6B;IAC9C,6DAA6D;IAC7D,KAAK,CAAC,UAAU,CAAC,mBAAwC,EAAE,MAAc,EAAE,YAA0B;QACjG,MAAM,SAAS,GAAG,MAAM,mBAAmB,CAAC,YAAY,EAAE,CAAC;QAE3D,OAAO,MAAM,cAAc,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;IACnD,CAAC;CACJ","sourcesContent":["import computeBlobMD5 from \"./computeBlobMD5.js\";\n\nimport type MD5ComputationStrategy from \"../md5ComputationStrategy.js\";\nimport type ChunkStreamProvider from \"../../../../utils/fileSystem/chunkStreamProvider.js\";\n\nexport default class WebSyncMD5ComputationStrategy implements MD5ComputationStrategy {\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n async computeMD5(chunkStreamProvider: ChunkStreamProvider, format: string, _abortSignal?: AbortSignal): Promise<string> {\n const chunkBlob = await chunkStreamProvider.getChunkBlob();\n\n return await computeBlobMD5(chunkBlob, format);\n }\n}"]}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import UploaderChunkStreamProviderFactory from "../chunkStreamProviderFactory/uploaderChunkStreamProviderFactory.js";
|
|
2
|
+
import UploaderMD5Provider, { UploaderMD5ProviderFileToBeMD5Hashed } from "./uploaderMD5Provider.js";
|
|
3
|
+
import ChunkStreamEncryptionData from "../../utils/fileSystem/chunkStreamEncryptionData.js";
|
|
4
|
+
import ConcurrencyController from "../../utils/concurrencyController/concurrencyController.js";
|
|
5
|
+
import FileDetails from "../../utils/fileSystem/fileDetails.js";
|
|
6
|
+
import type MD5ComputationStrategyFactory from "./md5ComputationStrategies/md5ComputationStrategyFactory.js";
|
|
7
|
+
export default class PrecomputedMD5Provider<T extends FileDetails> implements UploaderMD5Provider<T> {
|
|
8
|
+
#private;
|
|
9
|
+
constructor(md5ComputationStrategyFactory: MD5ComputationStrategyFactory, format: string, chunkStreamProviderFactory: UploaderChunkStreamProviderFactory<T>, concurrencyController: ConcurrencyController);
|
|
10
|
+
start(files: UploaderMD5ProviderFileToBeMD5Hashed<T>[], encryptionData: ChunkStreamEncryptionData | undefined, abortSignal?: AbortSignal): Promise<void>;
|
|
11
|
+
private clear;
|
|
12
|
+
private addAbortSignalListener;
|
|
13
|
+
private throwIfEncryptionDataIsNotValid;
|
|
14
|
+
private precomputeAllFiles;
|
|
15
|
+
private precomputeChunks;
|
|
16
|
+
private precomputeChunkMd5;
|
|
17
|
+
private getChunkError;
|
|
18
|
+
private createAbortError;
|
|
19
|
+
private setComputationResult;
|
|
20
|
+
private shouldStopProcessing;
|
|
21
|
+
stop(): Promise<void>;
|
|
22
|
+
private notifyObservers;
|
|
23
|
+
private notifyAndRemoveObserverIfResultExists;
|
|
24
|
+
private removeObserver;
|
|
25
|
+
getMd5Checksum(file: T, chunkStartPosition: number): Promise<string>;
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=precomputedMD5Provider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"precomputedMD5Provider.d.ts","sourceRoot":"","sources":["../../../../src/uploader/md5Provider/precomputedMD5Provider.ts"],"names":[],"mappings":"AAAA,OAAO,kCAAkC,MAAM,qEAAqE,CAAC;AACrH,OAAO,mBAAmB,EAAE,EAA6C,oCAAoC,EAAE,MAAM,0BAA0B,CAAC;AAChJ,OAAO,yBAAyB,MAAM,qDAAqD,CAAC;AAC5F,OAAO,qBAAqB,MAAM,4DAA4D,CAAC;AAI/F,OAAO,WAAW,MAAM,uCAAuC,CAAC;AAIhE,OAAO,KAAK,6BAA6B,MAAM,6DAA6D,CAAC;AAG7G,MAAM,CAAC,OAAO,OAAO,sBAAsB,CAAC,CAAC,SAAS,WAAW,CAAE,YAAW,mBAAmB,CAAC,CAAC,CAAC;;gBAoBpF,6BAA6B,EAAE,6BAA6B,EAAE,MAAM,EAAE,MAAM,EAAE,0BAA0B,EAAE,kCAAkC,CAAC,CAAC,CAAC,EAAE,qBAAqB,EAAE,qBAAqB;IAgBnM,KAAK,CAAC,KAAK,EAAE,oCAAoC,CAAC,CAAC,CAAC,EAAE,EAAE,cAAc,EAAE,yBAAyB,GAAG,SAAS,EAAE,WAAW,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IA8B9J,OAAO,CAAC,KAAK;IAMb,OAAO,CAAC,sBAAsB;IAS9B,OAAO,CAAC,+BAA+B;YAUzB,kBAAkB;YAoBlB,gBAAgB;YAkChB,kBAAkB;IAyBhC,OAAO,CAAC,aAAa;IAUrB,OAAO,CAAC,gBAAgB;IAOxB,OAAO,CAAC,oBAAoB;IAO5B,OAAO,CAAC,oBAAoB;IAItB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAM3B,OAAO,CAAC,eAAe;IAIvB,OAAO,CAAC,qCAAqC;IA2B7C,OAAO,CAAC,cAAc;IAIhB,cAAc,CAAC,IAAI,EAAE,CAAC,EAAE,kBAAkB,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;CAW7E"}
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
import FsError from "../../utils/fileSystem/fsError.js";
|
|
2
|
+
import { promiseAllSettled } from "../../utils/promiseAll.js";
|
|
3
|
+
export default class PrecomputedMD5Provider {
|
|
4
|
+
#md5ComputationStrategyFactory;
|
|
5
|
+
#format;
|
|
6
|
+
#isRunning = false;
|
|
7
|
+
#isFinished = false;
|
|
8
|
+
#isError = undefined;
|
|
9
|
+
#mainLoopPromise;
|
|
10
|
+
#internalAbortController;
|
|
11
|
+
#computedMD5s = new Map();
|
|
12
|
+
#observers = new Set();
|
|
13
|
+
#encryptionData;
|
|
14
|
+
#chunkStreamProviderFactory;
|
|
15
|
+
#concurrencyController;
|
|
16
|
+
constructor(md5ComputationStrategyFactory, format, chunkStreamProviderFactory, concurrencyController) {
|
|
17
|
+
if (!md5ComputationStrategyFactory)
|
|
18
|
+
throw new Error(`MD5 computation strategy factory is undefined`);
|
|
19
|
+
if (!format || format.length === 0)
|
|
20
|
+
throw new Error(`MD5 format is incorrect`);
|
|
21
|
+
if (!chunkStreamProviderFactory)
|
|
22
|
+
throw new Error(`Chunk stream provider factory is undefined`);
|
|
23
|
+
if (!concurrencyController)
|
|
24
|
+
throw new Error(`Concurrency controller is undefined`);
|
|
25
|
+
this.#md5ComputationStrategyFactory = md5ComputationStrategyFactory;
|
|
26
|
+
this.#format = format;
|
|
27
|
+
this.#chunkStreamProviderFactory = chunkStreamProviderFactory;
|
|
28
|
+
this.#concurrencyController = concurrencyController;
|
|
29
|
+
}
|
|
30
|
+
async start(files, encryptionData, abortSignal) {
|
|
31
|
+
try {
|
|
32
|
+
this.clear();
|
|
33
|
+
this.#encryptionData = encryptionData;
|
|
34
|
+
this.throwIfEncryptionDataIsNotValid();
|
|
35
|
+
this.#isRunning = true;
|
|
36
|
+
this.#internalAbortController = new AbortController();
|
|
37
|
+
this.addAbortSignalListener(abortSignal);
|
|
38
|
+
this.#mainLoopPromise = this.precomputeAllFiles(files);
|
|
39
|
+
await this.#mainLoopPromise;
|
|
40
|
+
this.#isFinished = !this.#internalAbortController.signal.aborted;
|
|
41
|
+
}
|
|
42
|
+
catch (error) {
|
|
43
|
+
this.#isError = new Error(`Unhandled error occured in WebPrecomputedMD5Provider. See 'cause' for more details`, { cause: error });
|
|
44
|
+
}
|
|
45
|
+
finally {
|
|
46
|
+
this.#isRunning = false;
|
|
47
|
+
this.notifyObservers();
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
clear() {
|
|
51
|
+
this.#computedMD5s.clear();
|
|
52
|
+
this.#isFinished = false;
|
|
53
|
+
this.#isError = undefined;
|
|
54
|
+
}
|
|
55
|
+
addAbortSignalListener(abortSignal) {
|
|
56
|
+
const internalAbortController = this.#internalAbortController;
|
|
57
|
+
if (abortSignal?.aborted)
|
|
58
|
+
internalAbortController.abort();
|
|
59
|
+
else
|
|
60
|
+
abortSignal?.addEventListener(`abort`, () => internalAbortController.abort(), { once: true });
|
|
61
|
+
}
|
|
62
|
+
throwIfEncryptionDataIsNotValid() {
|
|
63
|
+
if (!this.#encryptionData)
|
|
64
|
+
return;
|
|
65
|
+
if (this.#encryptionData.iv.length !== 16)
|
|
66
|
+
throw new FsError(`Encryption IV must be 16 bytes long`);
|
|
67
|
+
if (this.#encryptionData.key.length !== 32)
|
|
68
|
+
throw new FsError(`Encryption key must be 32 bytes long`);
|
|
69
|
+
}
|
|
70
|
+
async precomputeAllFiles(files) {
|
|
71
|
+
let session;
|
|
72
|
+
try {
|
|
73
|
+
if (this.shouldStopProcessing())
|
|
74
|
+
return;
|
|
75
|
+
session = await this.#md5ComputationStrategyFactory.createSession(this.#internalAbortController?.signal);
|
|
76
|
+
await this.precomputeChunks(files, session.strategy);
|
|
77
|
+
}
|
|
78
|
+
catch (error) {
|
|
79
|
+
if (!this.#internalAbortController?.signal.aborted)
|
|
80
|
+
throw error;
|
|
81
|
+
}
|
|
82
|
+
finally {
|
|
83
|
+
session?.dispose();
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
async precomputeChunks(files, strategy) {
|
|
87
|
+
const ongoingChunkMD5Computations = new Set();
|
|
88
|
+
try {
|
|
89
|
+
for (const file of files) {
|
|
90
|
+
for (const chunk of file.chunksIterator) {
|
|
91
|
+
const releaseSemaphore = await this.#concurrencyController.acquire();
|
|
92
|
+
if (this.shouldStopProcessing()) {
|
|
93
|
+
releaseSemaphore();
|
|
94
|
+
break;
|
|
95
|
+
}
|
|
96
|
+
const chunkMD5ComputingPromise = this.precomputeChunkMd5(file.file, chunk.startPosition, chunk.sizeInBytes, releaseSemaphore, strategy);
|
|
97
|
+
const trackedChunkUploadPromise = chunkMD5ComputingPromise.finally(() => {
|
|
98
|
+
ongoingChunkMD5Computations.delete(trackedChunkUploadPromise);
|
|
99
|
+
});
|
|
100
|
+
ongoingChunkMD5Computations.add(trackedChunkUploadPromise);
|
|
101
|
+
if (this.shouldStopProcessing())
|
|
102
|
+
break;
|
|
103
|
+
}
|
|
104
|
+
if (this.shouldStopProcessing())
|
|
105
|
+
break;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
finally {
|
|
109
|
+
await promiseAllSettled(Array.from(ongoingChunkMD5Computations));
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
async precomputeChunkMd5(file, chunkStartPosition, chunkSizeInBytes, releaseSemaphore, strategy) {
|
|
113
|
+
let chunkStreamProvider;
|
|
114
|
+
try {
|
|
115
|
+
chunkStreamProvider = this.#chunkStreamProviderFactory.createChunkStreamProvider(file, chunkStartPosition, chunkSizeInBytes, this.#encryptionData);
|
|
116
|
+
const md5 = await strategy.computeMD5(chunkStreamProvider, this.#format, this.#internalAbortController?.signal);
|
|
117
|
+
this.setComputationResult(file.externalId, chunkStartPosition, { isSuccess: true, md5 });
|
|
118
|
+
}
|
|
119
|
+
catch (error) {
|
|
120
|
+
const chunkError = this.getChunkError(error);
|
|
121
|
+
this.setComputationResult(file.externalId, chunkStartPosition, { isSuccess: false, error: chunkError });
|
|
122
|
+
}
|
|
123
|
+
finally {
|
|
124
|
+
releaseSemaphore();
|
|
125
|
+
if (chunkStreamProvider && !chunkStreamProvider.isReleased)
|
|
126
|
+
await chunkStreamProvider.release().catch(() => { });
|
|
127
|
+
this.notifyObservers();
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
getChunkError(error) {
|
|
131
|
+
if (this.#internalAbortController?.signal?.aborted)
|
|
132
|
+
return this.createAbortError(this.#internalAbortController?.signal);
|
|
133
|
+
if (error instanceof FsError)
|
|
134
|
+
return error;
|
|
135
|
+
return new FsError(`ComputingFileMd5ChecksumException`, { cause: error });
|
|
136
|
+
}
|
|
137
|
+
createAbortError(abortSignal) {
|
|
138
|
+
if (abortSignal.reason instanceof Error)
|
|
139
|
+
return abortSignal.reason;
|
|
140
|
+
return new Error(`Aborted`);
|
|
141
|
+
}
|
|
142
|
+
setComputationResult(fileId, chunkStartPosition, result) {
|
|
143
|
+
if (!this.#computedMD5s.has(fileId))
|
|
144
|
+
this.#computedMD5s.set(fileId, new Map());
|
|
145
|
+
this.#computedMD5s.get(fileId).set(chunkStartPosition, result);
|
|
146
|
+
}
|
|
147
|
+
shouldStopProcessing() {
|
|
148
|
+
return this.#internalAbortController?.signal.aborted === true || this.#isError;
|
|
149
|
+
}
|
|
150
|
+
async stop() {
|
|
151
|
+
this.#internalAbortController?.abort();
|
|
152
|
+
await this.#mainLoopPromise;
|
|
153
|
+
}
|
|
154
|
+
notifyObservers() {
|
|
155
|
+
this.#observers.forEach(observer => this.notifyAndRemoveObserverIfResultExists(observer));
|
|
156
|
+
}
|
|
157
|
+
notifyAndRemoveObserverIfResultExists(observer) {
|
|
158
|
+
const result = this.#computedMD5s.get(observer.fileId)?.get(observer.chunkStartPosition);
|
|
159
|
+
if (result) {
|
|
160
|
+
if (result.isSuccess)
|
|
161
|
+
observer.resolve(result.md5);
|
|
162
|
+
else
|
|
163
|
+
observer.reject(result.error);
|
|
164
|
+
this.removeObserver(observer);
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
if (this.#isRunning)
|
|
168
|
+
return;
|
|
169
|
+
if (this.#isError)
|
|
170
|
+
observer.reject(this.#isError);
|
|
171
|
+
else if (this.#isFinished)
|
|
172
|
+
observer.reject(new Error(`MD5 provider has never computed MD5 for this chunk`));
|
|
173
|
+
else
|
|
174
|
+
observer.reject(new Error(`MD5s precomputing failed`));
|
|
175
|
+
this.removeObserver(observer);
|
|
176
|
+
}
|
|
177
|
+
removeObserver(observer) {
|
|
178
|
+
this.#observers.delete(observer);
|
|
179
|
+
}
|
|
180
|
+
async getMd5Checksum(file, chunkStartPosition) {
|
|
181
|
+
const promise = new Promise((resolve, reject) => {
|
|
182
|
+
const observer = { fileId: file.externalId, chunkStartPosition, resolve, reject };
|
|
183
|
+
this.#observers.add(observer);
|
|
184
|
+
this.notifyAndRemoveObserverIfResultExists(observer);
|
|
185
|
+
});
|
|
186
|
+
return promise;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
//# sourceMappingURL=precomputedMD5Provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"precomputedMD5Provider.js","sourceRoot":"","sources":["../../../../src/uploader/md5Provider/precomputedMD5Provider.ts"],"names":[],"mappings":"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","sourcesContent":["import UploaderChunkStreamProviderFactory from \"../chunkStreamProviderFactory/uploaderChunkStreamProviderFactory.js\";\nimport UploaderMD5Provider, { MD5ComputationResult, MD5ProviderObserver, UploaderMD5ProviderFileToBeMD5Hashed } from \"./uploaderMD5Provider.js\";\nimport ChunkStreamEncryptionData from \"../../utils/fileSystem/chunkStreamEncryptionData.js\";\nimport ConcurrencyController from \"../../utils/concurrencyController/concurrencyController.js\";\nimport FsError from \"../../utils/fileSystem/fsError.js\";\nimport { promiseAllSettled } from \"../../utils/promiseAll.js\";\nimport ConcurrencyReleaser from \"../../utils/concurrencyController/concurrencyReleaser.js\";\nimport FileDetails from \"../../utils/fileSystem/fileDetails.js\";\n\nimport type ChunkStreamProvider from \"../../utils/fileSystem/chunkStreamProvider.js\";\nimport type MD5ComputationStrategy from \"./md5ComputationStrategies/md5ComputationStrategy.js\";\nimport type MD5ComputationStrategyFactory from \"./md5ComputationStrategies/md5ComputationStrategyFactory.js\";\nimport type MD5ComputationSession from \"./md5ComputationStrategies/md5ComputationSession.js\";\n\nexport default class PrecomputedMD5Provider<T extends FileDetails> implements UploaderMD5Provider<T> {\n readonly #md5ComputationStrategyFactory: MD5ComputationStrategyFactory;\n readonly #format: string;\n\n #isRunning = false;\n #isFinished = false;\n #isError: Error | undefined = undefined;\n\n #mainLoopPromise: Promise<void> | undefined;\n\n #internalAbortController: AbortController | undefined;\n\n #computedMD5s = new Map<string | number, Map<number, MD5ComputationResult>>();\n #observers: Set<MD5ProviderObserver> = new Set();\n\n #encryptionData?: ChunkStreamEncryptionData;\n\n readonly #chunkStreamProviderFactory: UploaderChunkStreamProviderFactory<T>;\n readonly #concurrencyController: ConcurrencyController;\n\n constructor(md5ComputationStrategyFactory: MD5ComputationStrategyFactory, format: string, chunkStreamProviderFactory: UploaderChunkStreamProviderFactory<T>, concurrencyController: ConcurrencyController) {\n if (!md5ComputationStrategyFactory)\n throw new Error(`MD5 computation strategy factory is undefined`);\n if (!format || format.length === 0)\n throw new Error(`MD5 format is incorrect`);\n if (!chunkStreamProviderFactory)\n throw new Error(`Chunk stream provider factory is undefined`);\n if (!concurrencyController)\n throw new Error(`Concurrency controller is undefined`);\n\n this.#md5ComputationStrategyFactory = md5ComputationStrategyFactory;\n this.#format = format;\n this.#chunkStreamProviderFactory = chunkStreamProviderFactory;\n this.#concurrencyController = concurrencyController;\n }\n\n async start(files: UploaderMD5ProviderFileToBeMD5Hashed<T>[], encryptionData: ChunkStreamEncryptionData | undefined, abortSignal?: AbortSignal): Promise<void> {\n try {\n this.clear();\n\n this.#encryptionData = encryptionData;\n\n this.throwIfEncryptionDataIsNotValid();\n\n this.#isRunning = true;\n\n this.#internalAbortController = new AbortController();\n\n this.addAbortSignalListener(abortSignal);\n\n this.#mainLoopPromise = this.precomputeAllFiles(files);\n\n await this.#mainLoopPromise;\n\n this.#isFinished = !this.#internalAbortController.signal.aborted;\n }\n catch (error) {\n this.#isError = new Error(`Unhandled error occured in WebPrecomputedMD5Provider. See 'cause' for more details`, { cause: error as Error });\n }\n finally {\n this.#isRunning = false;\n\n this.notifyObservers();\n }\n }\n\n private clear() {\n this.#computedMD5s.clear();\n this.#isFinished = false;\n this.#isError = undefined;\n }\n\n private addAbortSignalListener(abortSignal: AbortSignal | undefined) {\n const internalAbortController = this.#internalAbortController!;\n\n if (abortSignal?.aborted)\n internalAbortController.abort();\n else\n abortSignal?.addEventListener(`abort`, () => internalAbortController.abort(), { once: true });\n }\n\n private throwIfEncryptionDataIsNotValid() {\n if (!this.#encryptionData)\n return;\n\n if (this.#encryptionData.iv.length !== 16)\n throw new FsError(`Encryption IV must be 16 bytes long`);\n if (this.#encryptionData.key.length !== 32)\n throw new FsError(`Encryption key must be 32 bytes long`);\n }\n\n private async precomputeAllFiles(files: UploaderMD5ProviderFileToBeMD5Hashed<T>[]) {\n let session: MD5ComputationSession | undefined;\n\n try {\n if (this.shouldStopProcessing())\n return;\n\n session = await this.#md5ComputationStrategyFactory.createSession(this.#internalAbortController?.signal);\n\n await this.precomputeChunks(files, session.strategy);\n }\n catch (error) {\n if (!this.#internalAbortController?.signal.aborted)\n throw error;\n }\n finally {\n session?.dispose();\n }\n }\n\n private async precomputeChunks(files: UploaderMD5ProviderFileToBeMD5Hashed<T>[], strategy: MD5ComputationStrategy) {\n const ongoingChunkMD5Computations = new Set<Promise<void>>();\n\n try {\n for (const file of files) {\n for (const chunk of file.chunksIterator) {\n const releaseSemaphore = await this.#concurrencyController.acquire();\n\n if (this.shouldStopProcessing()) {\n releaseSemaphore();\n break;\n }\n\n const chunkMD5ComputingPromise = this.precomputeChunkMd5(file.file, chunk.startPosition, chunk.sizeInBytes, releaseSemaphore, strategy);\n\n const trackedChunkUploadPromise = chunkMD5ComputingPromise.finally(() => {\n ongoingChunkMD5Computations.delete(trackedChunkUploadPromise);\n });\n\n ongoingChunkMD5Computations.add(trackedChunkUploadPromise);\n\n if (this.shouldStopProcessing())\n break;\n }\n\n if (this.shouldStopProcessing())\n break;\n }\n }\n finally {\n await promiseAllSettled(Array.from(ongoingChunkMD5Computations));\n }\n }\n\n private async precomputeChunkMd5(file: T, chunkStartPosition: number, chunkSizeInBytes: number, releaseSemaphore: ConcurrencyReleaser, strategy: MD5ComputationStrategy) {\n let chunkStreamProvider: ChunkStreamProvider | undefined;\n\n try {\n chunkStreamProvider = this.#chunkStreamProviderFactory.createChunkStreamProvider(file, chunkStartPosition, chunkSizeInBytes, this.#encryptionData);\n\n const md5 = await strategy.computeMD5(chunkStreamProvider, this.#format, this.#internalAbortController?.signal);\n\n this.setComputationResult(file.externalId, chunkStartPosition, { isSuccess: true, md5 });\n }\n catch (error) {\n const chunkError = this.getChunkError(error);\n\n this.setComputationResult(file.externalId, chunkStartPosition, { isSuccess: false, error: chunkError });\n }\n finally {\n releaseSemaphore();\n\n if (chunkStreamProvider && !chunkStreamProvider.isReleased)\n await chunkStreamProvider.release().catch(() => { /* Cleanup failure must not replace the MD5 result. */ });\n\n this.notifyObservers();\n }\n }\n\n private getChunkError(error: unknown): Error {\n if (this.#internalAbortController?.signal?.aborted)\n return this.createAbortError(this.#internalAbortController?.signal);\n\n if (error instanceof FsError)\n return error;\n\n return new FsError(`ComputingFileMd5ChecksumException`, { cause: error as Error });\n }\n\n private createAbortError(abortSignal: AbortSignal) {\n if (abortSignal.reason instanceof Error)\n return abortSignal.reason;\n\n return new Error(`Aborted`);\n }\n\n private setComputationResult(fileId: string | number, chunkStartPosition: number, result: MD5ComputationResult) {\n if (!this.#computedMD5s.has(fileId))\n this.#computedMD5s.set(fileId, new Map());\n\n this.#computedMD5s.get(fileId)!.set(chunkStartPosition, result);\n }\n\n private shouldStopProcessing() {\n return this.#internalAbortController?.signal.aborted === true || this.#isError;\n }\n\n async stop(): Promise<void> {\n this.#internalAbortController?.abort();\n\n await this.#mainLoopPromise;\n }\n\n private notifyObservers() {\n this.#observers.forEach(observer => this.notifyAndRemoveObserverIfResultExists(observer));\n }\n\n private notifyAndRemoveObserverIfResultExists(observer: MD5ProviderObserver) {\n const result = this.#computedMD5s.get(observer.fileId)?.get(observer.chunkStartPosition);\n\n if (result) {\n if (result.isSuccess)\n observer.resolve(result.md5);\n else\n observer.reject(result.error);\n\n this.removeObserver(observer);\n\n return;\n }\n\n if (this.#isRunning)\n return;\n\n if (this.#isError)\n observer.reject(this.#isError);\n else if (this.#isFinished)\n observer.reject(new Error(`MD5 provider has never computed MD5 for this chunk`));\n else\n observer.reject(new Error(`MD5s precomputing failed`));\n\n this.removeObserver(observer);\n }\n\n private removeObserver(observer: MD5ProviderObserver) {\n this.#observers.delete(observer);\n }\n\n async getMd5Checksum(file: T, chunkStartPosition: number): Promise<string> {\n const promise = new Promise<string>((resolve, reject) => {\n const observer = { fileId: file.externalId, chunkStartPosition, resolve, reject };\n\n this.#observers.add(observer);\n\n this.notifyAndRemoveObserverIfResultExists(observer);\n });\n\n return promise;\n }\n}"]}
|