Compare commits

..

2 Commits

Author SHA1 Message Date
Administrator
79fe3037eb release: v3.3.45 2026-06-07 20:41:25 +02:00
Administrator
d280765feb fix(perf): freeze on Start with 2000+ jobs — gate probe + rot-log behind semaphore 2026-06-07 20:40:55 +02:00
3 changed files with 26 additions and 13 deletions

View File

@ -9,7 +9,7 @@ const DoodstreamUploader = require('./doodstream-upload');
const ClouddropUploader = require('./clouddrop-upload');
const Semaphore = require('./semaphore');
const Throttle = require('./throttle');
const { probeFileHead, summarizeFileStat } = require('./file-probe');
const { probeFileHead } = require('./file-probe');
const DEFAULT_SETTINGS = {
retries: 3,
@ -435,21 +435,25 @@ class UploadManager extends EventEmitter {
maxAttempts
});
const fileStat = summarizeFileStat(task.file);
const fileProbe = await probeFileHead(task.file, 64).catch((err) => ({ ok: false, error: err.message, kind: 'unreadable' }));
this._rotLog('upload-start', {
jobId, hoster: task.hoster, accountId: task.accountId, fileName,
fileSize: fileStat.size, fileMtime: fileStat.mtime,
detectedKind: fileProbe && fileProbe.kind ? fileProbe.kind : 'unknown',
isVideoLike: !!(fileProbe && fileProbe.isVideoLike),
headHex: fileProbe && fileProbe.headHex ? fileProbe.headHex.slice(0, 32) : null
});
// Acquire hoster semaphore first so jobs waiting for a hoster slot
// don't waste global slots (prevents underutilization)
await hosterSemaphore.acquire(signal);
hosterSlotAcquired = true;
let fileProbe = null;
try {
fileProbe = await probeFileHead(task.file, 64);
} catch (err) {
fileProbe = { ok: false, error: err && err.message, kind: 'unreadable' };
}
this._rotLog('upload-start', {
jobId, hoster: task.hoster, accountId: task.accountId, fileName,
fileSize,
detectedKind: fileProbe && fileProbe.kind ? fileProbe.kind : 'unknown',
isVideoLike: !!(fileProbe && fileProbe.isVideoLike),
headHex: fileProbe && fileProbe.headHex ? fileProbe.headHex.slice(0, 32) : null
});
if (globalSemaphore) {
await globalSemaphore.acquire(signal);
globalSlotAcquired = true;

11
main.js
View File

@ -1445,6 +1445,15 @@ ipcMain.handle('start-upload', (_event, payload) => {
}
});
const ROT_LOG_RENDERER_EVENTS = new Set([
'switchAccount',
'pre-job-swap',
'try-alternate-after-fail',
'mark-failed',
'rotation-end',
'doodstream-via-api',
'doodstream-via-web'
]);
uploadManager.on('rot-log', (entry) => {
const { ts, event, ...rest } = entry;
const pairs = Object.entries(rest)
@ -1454,7 +1463,7 @@ ipcMain.handle('start-upload', (_event, payload) => {
if (entry.jobId) {
_appendJobLog(entry.jobId, { ts: ts || Date.now(), kind: 'rot', event, ...rest });
}
if (mainWindow && !mainWindow.isDestroyed()) {
if (mainWindow && !mainWindow.isDestroyed() && ROT_LOG_RENDERER_EVENTS.has(event)) {
mainWindow.webContents.send('account-rotation-log', entry);
}
});

View File

@ -1,6 +1,6 @@
{
"name": "multi-hoster-uploader",
"version": "3.3.44",
"version": "3.3.45",
"description": "Upload files to doodstream, voe, vidmoly, byse simultaneously",
"main": "main.js",
"scripts": {