chore: bump version to 1.7.22 and update CHANGELOG, tests and docs
Docs Check / Markdown lint (push) Successful in 1m14s
Build and Push Docker Image / build (push) Successful in 1m52s
Licence Check / Licence compatibility and copyright header verification (push) Successful in 1m55s
CI / Security audit (push) Successful in 2m25s
Docs Check / Mermaid diagram parse check (push) Successful in 3m6s
CI / Swagger Validation & Coverage (push) Successful in 3m22s
CI / Tests & coverage (push) Successful in 3m45s
Docs Check / Markdown lint (push) Successful in 1m14s
Build and Push Docker Image / build (push) Successful in 1m52s
Licence Check / Licence compatibility and copyright header verification (push) Successful in 1m55s
CI / Security audit (push) Successful in 2m25s
Docs Check / Mermaid diagram parse check (push) Successful in 3m6s
CI / Swagger Validation & Coverage (push) Successful in 3m22s
CI / Tests & coverage (push) Successful in 3m45s
This commit is contained in:
@@ -180,7 +180,7 @@ function validateWebhookSecret(req) {
|
||||
* @param {string} serviceType - 'sonarr', 'radarr', or 'ombi'
|
||||
* @param {string} eventType - the eventType from the webhook payload
|
||||
*/
|
||||
async function processWebhookEvent(serviceType, eventType) {
|
||||
async function processWebhookEvent(serviceType, eventType, payload = null) {
|
||||
const affectsQueue = QUEUE_EVENTS.has(eventType);
|
||||
const affectsHistory = HISTORY_EVENTS.has(eventType);
|
||||
const affectsOmbi = OMBI_EVENTS.has(eventType);
|
||||
@@ -259,9 +259,66 @@ async function processWebhookEvent(serviceType, eventType) {
|
||||
const ombiInstances = getOmbiInstances();
|
||||
|
||||
if (affectsOmbi) {
|
||||
// Add a 2000ms delay to resolve the race condition where Ombi fires the webhook before committing to DB
|
||||
await new Promise(r => setTimeout(r, 2000));
|
||||
const ombiRequests = await arrRetrieverRegistry.getOmbiRequests(true);
|
||||
const delayMs = parseInt(process.env.OMBI_WEBHOOK_REFRESH_DELAY_MS, 10);
|
||||
const initialDelay = !isNaN(delayMs) ? delayMs : 2000;
|
||||
logToFile(`[Webhook] Waiting initial delay of ${initialDelay}ms for Ombi webhook synchronization...`);
|
||||
await new Promise(r => setTimeout(r, initialDelay));
|
||||
|
||||
const requestId = payload ? (payload.requestId || payload.RequestId || payload.id || payload.Id) : null;
|
||||
const mediaType = payload ? (payload.type || payload.Type || '').toLowerCase() : null;
|
||||
|
||||
let ombiRequests = { movie: [], tv: [] };
|
||||
let foundAndValid = false;
|
||||
const maxRetries = 3;
|
||||
const retryDelayMs = 1500;
|
||||
|
||||
for (let attempt = 1; attempt <= maxRetries; attempt++) {
|
||||
if (attempt > 1) {
|
||||
logToFile(`[Webhook] Ombi request not found or missing user (attempt ${attempt-1}/${maxRetries}), retrying in ${retryDelayMs}ms...`);
|
||||
await new Promise(r => setTimeout(r, retryDelayMs));
|
||||
}
|
||||
|
||||
ombiRequests = await arrRetrieverRegistry.getOmbiRequests(true);
|
||||
|
||||
if (!requestId) {
|
||||
// If no requestId was provided in payload, we can't search specifically, so just accept the fetch
|
||||
foundAndValid = true;
|
||||
break;
|
||||
}
|
||||
|
||||
// Search in movie or tv lists
|
||||
const targetList = (mediaType === 'tv' || mediaType === 'series') ? (ombiRequests.tv || []) : (ombiRequests.movie || []);
|
||||
// Also check both if mediaType not specified
|
||||
const searchList = mediaType ? targetList : [...(ombiRequests.movie || []), ...(ombiRequests.tv || [])];
|
||||
|
||||
const targetReq = searchList.find(r => r && (r.id === requestId || r.Id === requestId));
|
||||
if (targetReq) {
|
||||
const user = extractRequestedUser(targetReq);
|
||||
if (user) {
|
||||
logToFile(`[Webhook] Verified request ${requestId} has valid user "${user}" on attempt ${attempt}`);
|
||||
foundAndValid = true;
|
||||
break;
|
||||
} else {
|
||||
logToFile(`[Webhook] Found request ${requestId} on attempt ${attempt}, but user extraction was empty.`);
|
||||
}
|
||||
} else {
|
||||
logToFile(`[Webhook] Request ${requestId} not found in retrieved list on attempt ${attempt}.`);
|
||||
}
|
||||
}
|
||||
|
||||
if (!foundAndValid && requestId) {
|
||||
logToFile(`[Webhook] WARNING: Could not verify request ${requestId} with valid user info after ${maxRetries} retries.`);
|
||||
// Try to log the raw target request if we found one
|
||||
ombiRequests = await arrRetrieverRegistry.getOmbiRequests(true);
|
||||
const searchList = [...(ombiRequests.movie || []), ...(ombiRequests.tv || [])];
|
||||
const targetReq = searchList.find(r => r && (r.id === requestId || r.Id === requestId));
|
||||
if (targetReq) {
|
||||
logToFile(`[Webhook] Raw request object where extraction failed: ${JSON.stringify(targetReq)}`);
|
||||
} else {
|
||||
logToFile(`[Webhook] Request ${requestId} was completely absent from Ombi requests list.`);
|
||||
}
|
||||
}
|
||||
|
||||
cache.set('poll:ombi-requests', ombiRequests, CACHE_TTL);
|
||||
logToFile(`[Webhook] Refreshed poll:ombi-requests (${ombiRequests.movie?.length || 0} movies, ${ombiRequests.tv?.length || 0} TV shows)`);
|
||||
}
|
||||
@@ -777,7 +834,7 @@ router.post('/ombi', webhookLimiter, (req, res) => {
|
||||
}
|
||||
|
||||
// Background cache refresh + SSE broadcast (fire-and-forget)
|
||||
processWebhookEvent('ombi', eventType).catch(err => {
|
||||
processWebhookEvent('ombi', eventType, req.body).catch(err => {
|
||||
logToFile(`[Webhook] Ombi background refresh error: ${err.message}`);
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user