mirror of
https://github.com/immich-app/immich
synced 2025-11-07 17:27:20 +00:00
feat(web): Improved assets upload (#3850)
* Improved asset upload algorithm. - Upload Queue: New process algorithm - Upload Queue: Concurrency correctly respected when dragging / adding multiple group of files to the queue - Upload Task: Add more information about progress (upload speed and remaining time) - Upload Panel: Add more information to about the queue status (Remaining, Errors, Duplicated, Uploaded) - Error recovery: asset information are kept in the queue to give the user a chance to read the error message - Error recovery: on error allow the user to retry the upload or hide the error / all errors * Support "live" editing of the upload concurrency * Fixed some issues * Reformat * fix: merge, linting, dark mode, upload to share --------- Co-authored-by: Jason Rasmussen <jrasm91@gmail.com>
This commit is contained in:
parent
a26ed3d1a6
commit
ca35e5557b
10 changed files with 483 additions and 169 deletions
69
web/src/lib/utils/executor-queue.ts
Normal file
69
web/src/lib/utils/executor-queue.ts
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
interface Options {
|
||||
concurrency: number;
|
||||
}
|
||||
|
||||
type Runnable = () => Promise<unknown>;
|
||||
|
||||
export class ExecutorQueue {
|
||||
private queue: Array<Runnable> = [];
|
||||
private running = 0;
|
||||
private _concurrency: number;
|
||||
|
||||
constructor(options?: Options) {
|
||||
this._concurrency = options?.concurrency || 2;
|
||||
}
|
||||
|
||||
get concurrency() {
|
||||
return this._concurrency;
|
||||
}
|
||||
|
||||
set concurrency(concurrency: number) {
|
||||
if (concurrency < 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._concurrency = concurrency;
|
||||
|
||||
const v = concurrency - this.running;
|
||||
if (v > 0) {
|
||||
[...new Array(this._concurrency)].forEach(() => this.tryRun());
|
||||
}
|
||||
}
|
||||
|
||||
addTask<T>(task: () => Promise<T>): Promise<T> {
|
||||
return new Promise((resolve, reject) => {
|
||||
// Add a custom task that wrap the original one;
|
||||
this.queue.push(async () => {
|
||||
try {
|
||||
this.running++;
|
||||
const result = task();
|
||||
resolve(await result);
|
||||
} catch (e) {
|
||||
reject(e);
|
||||
} finally {
|
||||
this.taskFinished();
|
||||
}
|
||||
});
|
||||
// Then run it if possible !
|
||||
this.tryRun();
|
||||
});
|
||||
}
|
||||
|
||||
private taskFinished(): void {
|
||||
this.running--;
|
||||
this.tryRun();
|
||||
}
|
||||
|
||||
private tryRun() {
|
||||
if (this.running >= this.concurrency) {
|
||||
return;
|
||||
}
|
||||
|
||||
const runnable = this.queue.shift();
|
||||
if (!runnable) {
|
||||
return;
|
||||
}
|
||||
|
||||
runnable();
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue