fix: prevent double-click race condition in upload start
Move `uploading = true` guard to immediately after the check in both startUpload() and startSelectedUpload(), before any async calls. Previously the flag was set after await executeHealthCheck(), allowing a fast double-click to bypass the guard and start duplicate batches. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
6233b192ab
commit
0c945e21b8
@ -1246,13 +1246,15 @@ function getSelectedJobLinks() {
|
|||||||
// --- Upload ---
|
// --- Upload ---
|
||||||
async function startUpload() {
|
async function startUpload() {
|
||||||
if (healthCheckRunning || uploading) return;
|
if (healthCheckRunning || uploading) return;
|
||||||
|
uploading = true; // set immediately to prevent double-click race
|
||||||
|
updateQueueActionButtons();
|
||||||
|
|
||||||
const hosters = getSelectedHosters();
|
const hosters = getSelectedHosters();
|
||||||
if (hosters.length === 0) { alert('Bitte mindestens einen Hoster auswählen.'); return; }
|
if (hosters.length === 0) { alert('Bitte mindestens einen Hoster auswählen.'); uploading = false; updateQueueActionButtons(); return; }
|
||||||
if (queueJobs.length === 0 && selectedFiles.length > 0) buildQueuePreview();
|
if (queueJobs.length === 0 && selectedFiles.length > 0) buildQueuePreview();
|
||||||
|
|
||||||
const jobsToStart = queueJobs.filter((job) => job.status === 'preview' || job.status === 'queued');
|
const jobsToStart = queueJobs.filter((job) => job.status === 'preview' || job.status === 'queued');
|
||||||
if (jobsToStart.length === 0) return;
|
if (jobsToStart.length === 0) { uploading = false; updateQueueActionButtons(); return; }
|
||||||
|
|
||||||
// Auto health check — only check hosters that have jobs to start
|
// Auto health check — only check hosters that have jobs to start
|
||||||
if (autoHealthCheckEnabled) {
|
if (autoHealthCheckEnabled) {
|
||||||
@ -1265,10 +1267,12 @@ async function startUpload() {
|
|||||||
const errors = rows.filter(r => r.status === 'error');
|
const errors = rows.filter(r => r.status === 'error');
|
||||||
if (errors.length > 0) {
|
if (errors.length > 0) {
|
||||||
alert(`Auto-Check fehlgeschlagen:\n${errors.map(r => `${r.hoster}: ${r.message}`).join('\n')}\n\nUpload wurde nicht gestartet.`);
|
alert(`Auto-Check fehlgeschlagen:\n${errors.map(r => `${r.hoster}: ${r.message}`).join('\n')}\n\nUpload wurde nicht gestartet.`);
|
||||||
|
uploading = false; updateQueueActionButtons();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
alert(`Auto-Check fehlgeschlagen: ${err.message}\nUpload wurde nicht gestartet.`);
|
alert(`Auto-Check fehlgeschlagen: ${err.message}\nUpload wurde nicht gestartet.`);
|
||||||
|
uploading = false; updateQueueActionButtons();
|
||||||
return;
|
return;
|
||||||
} finally {
|
} finally {
|
||||||
healthCheckRunning = false;
|
healthCheckRunning = false;
|
||||||
@ -1276,7 +1280,6 @@ async function startUpload() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uploading = true;
|
|
||||||
queueJobs.forEach(j => {
|
queueJobs.forEach(j => {
|
||||||
if (j.status === 'preview') j.status = 'queued';
|
if (j.status === 'preview') j.status = 'queued';
|
||||||
});
|
});
|
||||||
@ -1306,12 +1309,14 @@ async function startUpload() {
|
|||||||
|
|
||||||
async function startSelectedUpload() {
|
async function startSelectedUpload() {
|
||||||
if (healthCheckRunning || uploading) return;
|
if (healthCheckRunning || uploading) return;
|
||||||
|
uploading = true; // set immediately to prevent double-click race
|
||||||
|
updateQueueActionButtons();
|
||||||
|
|
||||||
const hosters = getSelectedHosters();
|
const hosters = getSelectedHosters();
|
||||||
if (hosters.length === 0) { alert('Bitte mindestens einen Hoster auswählen.'); return; }
|
if (hosters.length === 0) { alert('Bitte mindestens einen Hoster auswählen.'); uploading = false; updateQueueActionButtons(); return; }
|
||||||
|
|
||||||
const jobsToStart = queueJobs.filter((job) => selectedJobIds.has(job.id) && (job.status === 'preview' || job.status === 'queued'));
|
const jobsToStart = queueJobs.filter((job) => selectedJobIds.has(job.id) && (job.status === 'preview' || job.status === 'queued'));
|
||||||
if (jobsToStart.length === 0) return;
|
if (jobsToStart.length === 0) { uploading = false; updateQueueActionButtons(); return; }
|
||||||
|
|
||||||
// Auto health check — only check hosters that have jobs to start
|
// Auto health check — only check hosters that have jobs to start
|
||||||
if (autoHealthCheckEnabled) {
|
if (autoHealthCheckEnabled) {
|
||||||
@ -1324,10 +1329,12 @@ async function startSelectedUpload() {
|
|||||||
const errors = rows.filter(r => r.status === 'error');
|
const errors = rows.filter(r => r.status === 'error');
|
||||||
if (errors.length > 0) {
|
if (errors.length > 0) {
|
||||||
alert(`Auto-Check fehlgeschlagen:\n${errors.map(r => `${r.hoster}: ${r.message}`).join('\n')}\n\nUpload wurde nicht gestartet.`);
|
alert(`Auto-Check fehlgeschlagen:\n${errors.map(r => `${r.hoster}: ${r.message}`).join('\n')}\n\nUpload wurde nicht gestartet.`);
|
||||||
|
uploading = false; updateQueueActionButtons();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
alert(`Auto-Check fehlgeschlagen: ${err.message}\nUpload wurde nicht gestartet.`);
|
alert(`Auto-Check fehlgeschlagen: ${err.message}\nUpload wurde nicht gestartet.`);
|
||||||
|
uploading = false; updateQueueActionButtons();
|
||||||
return;
|
return;
|
||||||
} finally {
|
} finally {
|
||||||
healthCheckRunning = false;
|
healthCheckRunning = false;
|
||||||
@ -1335,7 +1342,6 @@ async function startSelectedUpload() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uploading = true;
|
|
||||||
jobsToStart.forEach(j => {
|
jobsToStart.forEach(j => {
|
||||||
if (j.status === 'preview') j.status = 'queued';
|
if (j.status === 'preview') j.status = 'queued';
|
||||||
});
|
});
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user