feat(startup): provision managed tools in the background after install
Windows CI / verify (push) Failing after 3m49s

A fresh installation only provisioned Streamlink and FFmpeg when the
first download started, which delayed that download by the full tool
download and extraction time. Packaged builds now schedule a background
provisioning pass fifteen seconds after startup so the tools are
typically ready before the first download begins, reusing the existing
ensure functions with their in-flight deduplication so a download that
starts earlier simply joins the running installation. The timer is
tracked and cleared during shutdown, and development and test launches
keep the previous deferred behavior so isolated environments never
trigger network provisioning.
This commit is contained in:
Sucukdeluxe
2026-08-14 18:35:12 +02:00
parent d2a4ba2154
commit 1d38bb9084
2 changed files with 35 additions and 1 deletions
+27 -1
View File
@@ -171,6 +171,7 @@ const DEFAULT_FILENAME_TEMPLATE_CLIP = '{date}_{part}.mp4';
// ./main/domain/config-normalize (Single-Source-Of-Truth, vermeidet
// Drift wenn man eine der Defaults aendert).
const QUEUE_SAVE_DEBOUNCE_MS = 250;
const STARTUP_TOOLS_PROVISION_DELAY_MS = 15 * 1000;
const MIN_FREE_DISK_BYTES = 128 * 1024 * 1024;
const DEBUG_LOG_FLUSH_INTERVAL_MS = 1000;
const DEBUG_LOG_BUFFER_FLUSH_LINES = 48;
@@ -4970,6 +4971,14 @@ function runStorageCleanup(opts: { dryRun: boolean }): CleanupReport {
let autoCleanupTimer: NodeJS.Timeout | null = null;
let autoCleanupStartupTimer: NodeJS.Timeout | null = null;
let lastAutoCleanupAt = 0;
let startupToolsProvisionTimer: NodeJS.Timeout | null = null;
function stopStartupToolsProvisionTimer(): void {
if (startupToolsProvisionTimer) {
clearTimeout(startupToolsProvisionTimer);
startupToolsProvisionTimer = null;
}
}
function stopAutoCleanupTimer(): void {
if (autoCleanupTimer) {
@@ -9052,7 +9061,23 @@ app.whenReady().then(() => {
restartAutoCleanupTimer();
createWindow();
startDevelopmentReload();
appendDebugLog('startup-tools-check-skipped', 'Deferred to first use');
if (app.isPackaged) {
startupToolsProvisionTimer = setTimeout(() => {
startupToolsProvisionTimer = null;
if (appShutdownStarted) return;
appendDebugLog('startup-tools-provisioning-start');
void (async () => {
const streamlinkReady = await ensureStreamlinkInstalled();
if (appShutdownStarted) return;
const ffmpegReady = await ensureFfmpegInstalled();
appendDebugLog('startup-tools-provisioning-finished', { streamlinkReady, ffmpegReady });
})().catch((error) => {
appendDebugLog('startup-tools-provisioning-failed', String(error));
});
}, STARTUP_TOOLS_PROVISION_DELAY_MS);
} else {
appendDebugLog('startup-tools-check-skipped', 'Deferred to first use');
}
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) {
@@ -9110,6 +9135,7 @@ async function shutdownCleanup(reason: 'window-all-closed' | 'before-quit'): Pro
['auto-vod-poller', () => stopAutoVodPoller()],
['live-status-poller', () => stopLiveStatusPoller()],
['auto-cleanup-timer', () => stopAutoCleanupTimer()],
['startup-tools-provision-timer', () => stopStartupToolsProvisionTimer()],
['queue-lifecycle', async () => {
await queueRunLifecycle.shutdown(
() => {