Multi-Hoster-Upload/lib/semaphore.js
Administrator 25b2afbf11 feat: add queue system, per-hoster settings, retry logic, and full UI overhaul
- Add FIFO semaphore for per-hoster concurrency control
- Add token-bucket speed limiter with abort signal support
- Rewrite upload-manager with retry loop, speed monitoring, and rich progress events
- Add per-hoster settings: retries, max speed, parallel count, restart below speed, time interval, max size
- Add context menu with shutdown-after-finish (sleep/shutdown/restart), always-on-top
- Add z-o-o-m-style queue table with 8 columns, status-colored rows, progress bars
- Add debounced queue rendering with scroll position preservation
- Add statusbar with global speed, total bytes, elapsed time
- Fix speedMonitor interval leak on error and scoping bug
- Fix throttle not respecting abort signal during cancellation
- Fix combined signal listener cleanup
- Bump version to 1.1.0

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 05:57:00 +01:00

49 lines
1.0 KiB
JavaScript

/**
* FIFO Semaphore for per-hoster concurrency control.
* acquire() blocks until a slot is available, release() frees it.
*/
class Semaphore {
constructor(limit) {
this.limit = Math.max(1, limit || 1);
this.active = 0;
this.queue = [];
}
acquire() {
return new Promise((resolve) => {
if (this.active < this.limit) {
this.active++;
resolve();
} else {
this.queue.push(resolve);
}
});
}
release() {
if (this.queue.length > 0) {
// Don't decrement active — hand slot directly to next waiter
const next = this.queue.shift();
next();
} else {
this.active = Math.max(0, this.active - 1);
}
}
updateLimit(newLimit) {
this.limit = Math.max(1, newLimit || 1);
// If new limit is higher, wake up waiting tasks
while (this.active < this.limit && this.queue.length > 0) {
this.active++;
const next = this.queue.shift();
next();
}
}
get pending() {
return this.queue.length;
}
}
module.exports = Semaphore;