fix: rTorrent null-safety, configurable SAB_HISTORY_LIMIT, lastError visibility (#68)
Build and Push Docker Image / build (push) Successful in 59s
Docs Check / Markdown lint (push) Failing after 1m45s
Licence Check / Licence compatibility and copyright header verification (push) Successful in 2m7s
CI / Security audit (push) Successful in 2m33s
Docs Check / Mermaid diagram parse check (push) Successful in 2m55s
CI / Swagger Validation & Coverage (push) Successful in 3m19s
CI / Tests & coverage (push) Successful in 3m29s
Build and Push Docker Image / build (push) Successful in 59s
Docs Check / Markdown lint (push) Failing after 1m45s
Licence Check / Licence compatibility and copyright header verification (push) Successful in 2m7s
CI / Security audit (push) Successful in 2m33s
Docs Check / Mermaid diagram parse check (push) Successful in 2m55s
CI / Swagger Validation & Coverage (push) Successful in 3m19s
CI / Tests & coverage (push) Successful in 3m29s
- RTorrentClient: guard d.multicall2 returning non-array, per-row try/catch, explicit Number()/String() coercions, _extractArrInfo null-safe - RTorrentClient.getClientStatus: coerce rates through Number.isFinite - SABnzbdClient: history limit now reads SAB_HISTORY_LIMIT env var (default 10) - DownloadClient: added _recordLastError, _clearLastError, getLastError on base - All four clients call _recordLastError on failure, _clearLastError on success - DownloadClientRegistry.getAllClientStatuses: includes lastError in result - GET /api/status/status: exposes downloadClients[] array with per-client lastError - Tests: RTorrentClient null-safety + lastError, SABnzbd history limit + lastError, downloadClients.test expectation updated for new lastError field
This commit is contained in:
@@ -3,9 +3,27 @@ const axios = require('axios');
|
||||
const DownloadClient = require('./DownloadClient');
|
||||
const { logToFile } = require('../utils/logger');
|
||||
|
||||
// Number of recently completed jobs to pull from SABnzbd's /api?mode=history on
|
||||
// every poll. Larger values let DownloadMatcher correlate slightly older jobs
|
||||
// with their Sonarr/Radarr queue entries at the cost of one wider HTTP
|
||||
// response per poll cycle. Configurable via the SAB_HISTORY_LIMIT environment
|
||||
// variable; defaults to 10 to match the previous hardcoded value.
|
||||
const DEFAULT_HISTORY_LIMIT = 10;
|
||||
function resolveHistoryLimit() {
|
||||
const raw = process.env.SAB_HISTORY_LIMIT;
|
||||
if (raw === undefined || raw === null || raw === '') return DEFAULT_HISTORY_LIMIT;
|
||||
const parsed = parseInt(raw, 10);
|
||||
if (!Number.isFinite(parsed) || parsed < 0) {
|
||||
logToFile(`[SABnzbd] Invalid SAB_HISTORY_LIMIT='${raw}'; falling back to ${DEFAULT_HISTORY_LIMIT}`);
|
||||
return DEFAULT_HISTORY_LIMIT;
|
||||
}
|
||||
return parsed;
|
||||
}
|
||||
|
||||
class SABnzbdClient extends DownloadClient {
|
||||
constructor(instance) {
|
||||
super(instance);
|
||||
this.historyLimit = resolveHistoryLimit();
|
||||
}
|
||||
|
||||
getClientType() {
|
||||
@@ -16,9 +34,11 @@ class SABnzbdClient extends DownloadClient {
|
||||
try {
|
||||
const response = await this.makeRequest('', { mode: 'version' });
|
||||
logToFile(`[SABnzbd:${this.name}] Connection test successful, version: ${response.data.version}`);
|
||||
this._clearLastError();
|
||||
return true;
|
||||
} catch (error) {
|
||||
logToFile(`[SABnzbd:${this.name}] Connection test failed: ${error.message}`);
|
||||
this._recordLastError('testConnection', error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -47,7 +67,7 @@ class SABnzbdClient extends DownloadClient {
|
||||
// Get both queue and history to provide complete picture
|
||||
const [queueResponse, historyResponse] = await Promise.all([
|
||||
this.makeRequest({ mode: 'queue' }),
|
||||
this.makeRequest({ mode: 'history', limit: 10 })
|
||||
this.makeRequest({ mode: 'history', limit: this.historyLimit })
|
||||
]);
|
||||
|
||||
const queueData = queueResponse.data;
|
||||
@@ -99,10 +119,12 @@ class SABnzbdClient extends DownloadClient {
|
||||
}
|
||||
}
|
||||
|
||||
logToFile(`[SABnzbd:${this.name}] Retrieved ${downloads.length} downloads`);
|
||||
logToFile(`[SABnzbd:${this.name}] Retrieved ${downloads.length} downloads (historyLimit=${this.historyLimit})`);
|
||||
this._clearLastError();
|
||||
return downloads;
|
||||
} catch (error) {
|
||||
logToFile(`[SABnzbd:${this.name}] Error fetching downloads: ${error.message}`);
|
||||
this._recordLastError('getActiveDownloads', error);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
@@ -112,8 +134,12 @@ class SABnzbdClient extends DownloadClient {
|
||||
const response = await this.makeRequest({ mode: 'queue' });
|
||||
const queueData = response.data.queue;
|
||||
|
||||
if (!queueData) return null;
|
||||
if (!queueData) {
|
||||
this._clearLastError();
|
||||
return null;
|
||||
}
|
||||
|
||||
this._clearLastError();
|
||||
return {
|
||||
status: queueData.status,
|
||||
speed: queueData.speed,
|
||||
@@ -128,6 +154,7 @@ class SABnzbdClient extends DownloadClient {
|
||||
};
|
||||
} catch (error) {
|
||||
logToFile(`[SABnzbd:${this.name}] Error getting client status: ${error.message}`);
|
||||
this._recordLastError('getClientStatus', error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user