feat(startup): provision managed tools in the background after install
Windows CI / verify (push) Failing after 3m49s
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:
@@ -85,6 +85,14 @@ describe('main runtime safety production paths', () => {
|
||||
expect(closeHandler.indexOf('finish({ success: true, filename })')).toBeGreaterThan(closeHandler.indexOf('partialDownloadRegistry.commit'));
|
||||
});
|
||||
|
||||
it('provisions managed tools in the background after a packaged startup', () => {
|
||||
const source = mainSource();
|
||||
expect(source).toContain('let startupToolsProvisionTimer: NodeJS.Timeout | null = null;');
|
||||
expect(source).toContain('clearTimeout(startupToolsProvisionTimer)');
|
||||
expect(source).toMatch(/if \(app\.isPackaged\) \{\s*startupToolsProvisionTimer = setTimeout\([\s\S]*?appShutdownStarted[\s\S]*?startup-tools-provisioning-start[\s\S]*?ensureStreamlinkInstalled\(\)[\s\S]*?ensureFfmpegInstalled\(\)[\s\S]*?startup-tools-provisioning-finished/);
|
||||
expect(source).toMatch(/\} else \{\s*appendDebugLog\('startup-tools-check-skipped', 'Deferred to first use'\);/);
|
||||
});
|
||||
|
||||
it('announces tool preparation before every download tool gate', () => {
|
||||
const source = mainSource();
|
||||
const vod = source.slice(source.indexOf('async function downloadVOD'), source.indexOf('async function processDownloadMergeGroup'));
|
||||
|
||||
+27
-1
@@ -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(
|
||||
() => {
|
||||
|
||||
Reference in New Issue
Block a user