fix(server): hata yönetimini iyileştir
Zamanlayıcı ve qbit istemcisi bileşenlerinde hata işleme yeteneklerini güçlendirir. - loop.scheduler: qbit hatalarında sistem durumunu ve sağlık bilgisini güncelleme ekler. - qbit.client: geçici ağ hatalarını (EAI_AGAIN vb.) algılayarak oturum durumunu sıfırlar. - timer.worker: global hata yakalama ekleyerek işleyicinin çökmesini engeller ve hataları günlüğe kaydeder.
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
import { QbitClient } from "../qbit/qbit.client"
|
import { QbitClient } from "../qbit/qbit.client"
|
||||||
import { tickLoopJobs } from "./loop.engine"
|
import { tickLoopJobs } from "./loop.engine"
|
||||||
import { getStatusSnapshot, refreshJobsStatus, setTorrentsStatus } from "../status/status.service"
|
import { getStatusSnapshot, refreshJobsStatus, setQbitStatus, setTorrentsStatus } from "../status/status.service"
|
||||||
import { emitStatusUpdate } from "../realtime/emitter"
|
import { emitQbitHealth, emitStatusUpdate } from "../realtime/emitter"
|
||||||
import { logger } from "../utils/logger"
|
import { logger } from "../utils/logger"
|
||||||
|
|
||||||
export const startLoopScheduler = (qbit: QbitClient, intervalMs: number) => {
|
export const startLoopScheduler = (qbit: QbitClient, intervalMs: number) => {
|
||||||
@@ -20,7 +20,19 @@ export const startLoopScheduler = (qbit: QbitClient, intervalMs: number) => {
|
|||||||
jobs,
|
jobs,
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
const message = error instanceof Error ? error.message : "Unknown error";
|
||||||
logger.error({ error }, "Loop scheduler tick failed");
|
logger.error({ error }, "Loop scheduler tick failed");
|
||||||
|
setQbitStatus({ ok: false, lastError: message });
|
||||||
|
emitQbitHealth({ ok: false, lastError: message });
|
||||||
|
try {
|
||||||
|
const current = await getStatusSnapshot();
|
||||||
|
emitStatusUpdate({
|
||||||
|
...current,
|
||||||
|
qbit: { ...current.qbit, ok: false, lastError: message },
|
||||||
|
});
|
||||||
|
} catch {
|
||||||
|
// Swallow secondary status errors to keep scheduler alive.
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}, intervalMs);
|
}, intervalMs);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -48,6 +48,18 @@ export class QbitClient {
|
|||||||
}
|
}
|
||||||
return await fn();
|
return await fn();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
if (axios.isAxiosError(error)) {
|
||||||
|
const code = error.code ?? "";
|
||||||
|
const transient =
|
||||||
|
code === "EAI_AGAIN" ||
|
||||||
|
code === "ENOTFOUND" ||
|
||||||
|
code === "ECONNREFUSED" ||
|
||||||
|
code === "ECONNRESET" ||
|
||||||
|
code === "ETIMEDOUT";
|
||||||
|
if (transient) {
|
||||||
|
this.loggedIn = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (
|
if (
|
||||||
axios.isAxiosError(error) &&
|
axios.isAxiosError(error) &&
|
||||||
(error.response?.status === 401 || error.response?.status === 403)
|
(error.response?.status === 401 || error.response?.status === 403)
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { readDb, writeDb } from "../storage/jsondb";
|
|||||||
import { TimerLog, TimerSummary } from "../types";
|
import { TimerLog, TimerSummary } from "../types";
|
||||||
import { emitTimerLog, emitTimerSummary } from "../realtime/emitter";
|
import { emitTimerLog, emitTimerSummary } from "../realtime/emitter";
|
||||||
import { nowIso } from "../utils/time";
|
import { nowIso } from "../utils/time";
|
||||||
|
import { logger } from "../utils/logger";
|
||||||
|
|
||||||
const MAX_LOGS = 2000;
|
const MAX_LOGS = 2000;
|
||||||
|
|
||||||
@@ -17,6 +18,7 @@ const normalizeTags = (tags?: string, category?: string) => {
|
|||||||
|
|
||||||
export const startTimerWorker = (qbit: QbitClient, intervalMs: number) => {
|
export const startTimerWorker = (qbit: QbitClient, intervalMs: number) => {
|
||||||
setInterval(async () => {
|
setInterval(async () => {
|
||||||
|
try {
|
||||||
const db = await readDb();
|
const db = await readDb();
|
||||||
const rules = db.timerRules ?? [];
|
const rules = db.timerRules ?? [];
|
||||||
if (rules.length === 0) {
|
if (rules.length === 0) {
|
||||||
@@ -88,5 +90,8 @@ export const startTimerWorker = (qbit: QbitClient, intervalMs: number) => {
|
|||||||
db.timerSummary = summary;
|
db.timerSummary = summary;
|
||||||
await writeDb(db);
|
await writeDb(db);
|
||||||
}
|
}
|
||||||
|
} catch (error) {
|
||||||
|
logger.error({ error }, "Timer worker tick failed");
|
||||||
|
}
|
||||||
}, intervalMs);
|
}, intervalMs);
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user