Files
sofarr/server/clients/PollingRadarrRetriever.js
T
gronod d568800942
Licence Check / Licence compatibility and copyright header verification (push) Successful in 51s
Build and Push Docker Image / build (push) Successful in 1m27s
CI / Security audit (push) Successful in 1m27s
CI / Tests & coverage (push) Successful in 1m43s
fix: limit history pagination to prevent 40s response times
The full pagination fix (ddad80a, e772001) caused history retrieval to
fetch up to 50 pages sequentially, taking 10-40 seconds instead of ~200ms.

Changes:
- Add maxPages parameter to getHistory() with default of 1 page
- Update poller to fetch 50 records (up from 10) in a single API call
- historyFetcher retains 100 records per page for UI display

This provides 5x more history for matching than before while keeping
the fast single-request performance.

Refs: develop-merge pagination performance issue
2026-05-20 21:44:53 +01:00

135 lines
3.8 KiB
JavaScript

// Copyright (c) 2026 Gordon Bolton. MIT License.
const axios = require('axios');
const ArrRetriever = require('./ArrRetriever');
const { logToFile } = require('../utils/logger');
/**
* Polling-based Radarr data retriever.
* Implements the ArrRetriever interface using direct HTTP polling.
*/
class PollingRadarrRetriever extends ArrRetriever {
constructor(instanceConfig) {
super(instanceConfig);
}
getRetrieverType() {
return 'radarr';
}
/**
* Get tags from Radarr instance
* @returns {Promise<Array>} Array of tag objects
*/
async getTags() {
try {
const response = await axios.get(`${this.url}/api/v3/tag`, {
headers: { 'X-Api-Key': this.apiKey }
});
return response.data;
} catch (error) {
logToFile(`[PollingRadarrRetriever] ${this.id} tags error: ${error.message}`);
return [];
}
}
/**
* Get queue from Radarr instance
* @returns {Promise<Object>} Queue object with records array
*/
async getQueue() {
const instanceName = this.name;
let page = 1;
let allRecords = [];
let responseData = null;
do {
try {
const response = await axios.get(`${this.url}/api/v3/queue`, {
headers: { 'X-Api-Key': this.apiKey },
params: { includeMovie: true, page, pageSize: 1000 }
});
responseData = response.data;
} catch (error) {
console.error(`Radarr queue fetch failed for instance ${instanceName}:`, error.response?.data || error.message);
throw error;
}
const records = responseData.records || (Array.isArray(responseData) ? responseData : []);
allRecords = allRecords.concat(records);
page++;
} while (
(responseData.records || (Array.isArray(responseData) ? responseData : [])).length === 1000 &&
page <= 50
);
return {
...responseData,
records: allRecords
};
}
/**
* Get history from Radarr instance
* @param {Object} options - Optional parameters for history fetch
* @param {number} [options.pageSize=100] - Number of records to fetch per page
* @param {number} [options.maxPages=1] - Maximum pages to fetch (for pagination control)
* @param {string} [options.sortKey] - Field to sort by
* @param {string} [options.sortDir] - Sort direction ('ascending' or 'descending')
* @param {boolean} [options.includeMovie=true] - Include movie data
* @param {string} [options.startDate] - ISO date string for filtering
* @returns {Promise<Object>} History object with records array
*/
async getHistory(options = {}) {
const {
pageSize = 100,
maxPages = 1,
sortKey,
sortDir,
includeMovie = true,
startDate
} = options;
const instanceName = this.name;
let page = 1;
let allRecords = [];
let responseData = null;
do {
const params = {
page,
pageSize,
includeMovie
};
if (sortKey) params.sortKey = sortKey;
if (sortDir) params.sortDir = sortDir;
if (startDate) params.startDate = startDate;
try {
const response = await axios.get(`${this.url}/api/v3/history`, {
headers: { 'X-Api-Key': this.apiKey },
params
});
responseData = response.data;
} catch (error) {
console.error(`Radarr history fetch failed for instance ${instanceName}:`, error.response?.data || error.message);
throw error;
}
const records = responseData.records || (Array.isArray(responseData) ? responseData : []);
allRecords = allRecords.concat(records);
page++;
} while (
(responseData.records || (Array.isArray(responseData) ? responseData : [])).length === pageSize &&
page <= maxPages
);
return {
...responseData,
records: allRecords
};
}
}
module.exports = PollingRadarrRetriever;