Optimize debug log I/O and settings auto-refresh polling (v4.1.11)

This commit is contained in:
xRangerDE 2026-02-21 00:47:20 +01:00
parent 9392398db7
commit 8d656772fc
5 changed files with 105 additions and 10 deletions

View File

@ -1,12 +1,12 @@
{
"name": "twitch-vod-manager",
"version": "4.1.10",
"version": "4.1.11",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "twitch-vod-manager",
"version": "4.1.10",
"version": "4.1.11",
"license": "MIT",
"dependencies": {
"axios": "^1.6.0",

View File

@ -1,6 +1,6 @@
{
"name": "twitch-vod-manager",
"version": "4.1.10",
"version": "4.1.11",
"description": "Twitch VOD Manager - Download Twitch VODs easily",
"main": "dist/main.js",
"author": "xRangerDE",

View File

@ -457,7 +457,7 @@
<div class="settings-card">
<h3 id="updateTitle">Updates</h3>
<p id="versionInfo" style="margin-bottom: 10px; color: var(--text-secondary);">Version: v4.1.10</p>
<p id="versionInfo" style="margin-bottom: 10px; color: var(--text-secondary);">Version: v4.1.11</p>
<button class="btn-secondary" id="checkUpdateBtn" onclick="checkUpdate()">Nach Updates suchen</button>
</div>
@ -502,7 +502,7 @@
<div class="status-dot" id="statusDot"></div>
<span id="statusText">Nicht verbunden</span>
</div>
<span id="versionText">v4.1.10</span>
<span id="versionText">v4.1.11</span>
</div>
</main>
</div>

View File

@ -8,7 +8,7 @@ import { autoUpdater } from 'electron-updater';
// ==========================================
// CONFIG & CONSTANTS
// ==========================================
const APP_VERSION = '4.1.10';
const APP_VERSION = '4.1.11';
const UPDATE_CHECK_URL = 'http://24-music.de/version.json';
// Paths
@ -30,6 +30,9 @@ const MIN_FREE_DISK_BYTES = 128 * 1024 * 1024;
const TOOL_PATH_REFRESH_TTL_MS = 10 * 1000;
const DEBUG_LOG_FLUSH_INTERVAL_MS = 1000;
const DEBUG_LOG_BUFFER_FLUSH_LINES = 48;
const DEBUG_LOG_READ_TAIL_BYTES = 512 * 1024;
const DEBUG_LOG_MAX_BYTES = 8 * 1024 * 1024;
const DEBUG_LOG_TRIM_TO_BYTES = 4 * 1024 * 1024;
const AUTO_UPDATE_CHECK_INTERVAL_MS = 10 * 60 * 1000;
const AUTO_UPDATE_STARTUP_CHECK_DELAY_MS = 5000;
const AUTO_UPDATE_MIN_CHECK_GAP_MS = 45 * 1000;
@ -533,11 +536,78 @@ function flushPendingDebugLogLines(): void {
const payload = pendingDebugLogLines.join('');
pendingDebugLogLines = [];
fs.appendFileSync(DEBUG_LOG_FILE, payload);
trimDebugLogFileIfNeeded();
} catch {
// ignore debug log errors
}
}
function trimDebugLogFileIfNeeded(): void {
try {
if (!fs.existsSync(DEBUG_LOG_FILE)) {
return;
}
const stats = fs.statSync(DEBUG_LOG_FILE);
if (stats.size <= DEBUG_LOG_MAX_BYTES) {
return;
}
const bytesToKeep = Math.min(DEBUG_LOG_TRIM_TO_BYTES, stats.size);
const startOffset = Math.max(0, stats.size - bytesToKeep);
const buffer = Buffer.allocUnsafe(bytesToKeep);
let fileHandle: number | null = null;
try {
fileHandle = fs.openSync(DEBUG_LOG_FILE, 'r');
fs.readSync(fileHandle, buffer, 0, bytesToKeep, startOffset);
} finally {
if (fileHandle !== null) {
fs.closeSync(fileHandle);
}
}
const firstLineBreak = buffer.indexOf(0x0a);
const trimmed = firstLineBreak >= 0 && firstLineBreak + 1 < buffer.length
? buffer.subarray(firstLineBreak + 1)
: buffer;
fs.writeFileSync(DEBUG_LOG_FILE, trimmed);
} catch {
// ignore debug log errors
}
}
function readDebugLogTailFromDisk(): string {
const stats = fs.statSync(DEBUG_LOG_FILE);
if (stats.size <= 0) {
return '';
}
const bytesToRead = Math.min(stats.size, DEBUG_LOG_READ_TAIL_BYTES);
if (bytesToRead === stats.size) {
return fs.readFileSync(DEBUG_LOG_FILE, 'utf-8');
}
const buffer = Buffer.allocUnsafe(bytesToRead);
let fileHandle: number | null = null;
try {
fileHandle = fs.openSync(DEBUG_LOG_FILE, 'r');
fs.readSync(fileHandle, buffer, 0, bytesToRead, stats.size - bytesToRead);
} finally {
if (fileHandle !== null) {
fs.closeSync(fileHandle);
}
}
const firstLineBreak = buffer.indexOf(0x0a);
const slice = firstLineBreak >= 0 && firstLineBreak + 1 < buffer.length
? buffer.subarray(firstLineBreak + 1)
: buffer;
return slice.toString('utf-8');
}
function startDebugLogFlushTimer(): void {
if (debugLogFlushTimer) {
return;
@ -569,7 +639,7 @@ function readDebugLog(lines = 200): string {
return 'Debug-Log ist leer.';
}
const text = fs.readFileSync(DEBUG_LOG_FILE, 'utf-8');
const text = readDebugLogTailFromDisk();
const rows = text.split(/\r?\n/).filter(Boolean);
return rows.slice(-lines).join('\n') || 'Debug-Log ist leer.';
} catch (e) {

View File

@ -1,4 +1,13 @@
let lastRuntimeMetricsOutput = '';
let lastDebugLogOutput = '';
function canRunSettingsAutoRefresh(): boolean {
if (document.hidden) {
return false;
}
return document.querySelector('.tab-content.active')?.id === 'settingsTab';
}
async function connect(): Promise<void> {
const hasCredentials = Boolean((config.client_id ?? '').toString().trim() && (config.client_secret ?? '').toString().trim());
@ -142,6 +151,10 @@ function toggleRuntimeMetricsAutoRefresh(enabled: boolean): void {
if (enabled) {
runtimeMetricsAutoRefreshTimer = window.setInterval(() => {
if (!canRunSettingsAutoRefresh()) {
return;
}
void refreshRuntimeMetrics(false);
}, 2000);
}
@ -245,8 +258,16 @@ async function runPreflight(autoFix = false): Promise<void> {
async function refreshDebugLog(): Promise<void> {
const text = await window.api.getDebugLog(250);
const panel = byId('debugLogOutput');
const keepAtBottom = (panel.scrollHeight - panel.scrollTop - panel.clientHeight) < 20;
if (text !== lastDebugLogOutput) {
panel.textContent = text;
lastDebugLogOutput = text;
}
if (keepAtBottom) {
panel.scrollTop = panel.scrollHeight;
}
}
function toggleDebugAutoRefresh(enabled: boolean): void {
@ -257,8 +278,12 @@ function toggleDebugAutoRefresh(enabled: boolean): void {
if (enabled) {
debugLogAutoRefreshTimer = window.setInterval(() => {
if (!canRunSettingsAutoRefresh()) {
return;
}
void refreshDebugLog();
}, 1500);
}, 2000);
}
}