fix(servarr): add timeout to Radarr/Sonarr API requests to prevent infinite loading (#2375)

* fix(servarr): add timeout to Radarr/Sonarr API requests to prevent infinite loading

Adds a 5-second timeout to all Radarr/Sonarr API requests and displays a warning banner when
services are unreachable. This prevents the Recent Requests section and request list pages from
hanging indefinitely when a configured service has connection issues.

fix #2374

* fix(requests): only show service error banner to users with advanced permissions
This commit is contained in:
fallenbagel
2026-02-07 01:38:21 +05:00
committed by GitHub
parent a0a784b976
commit faa2c0a005
9 changed files with 109 additions and 7 deletions

View File

@@ -1,14 +1,25 @@
import { sliderTitles } from '@app/components/Discover/constants';
import RequestCard from '@app/components/RequestCard';
import Slider from '@app/components/Slider';
import { ArrowRightCircleIcon } from '@heroicons/react/24/outline';
import { Permission, useUser } from '@app/hooks/useUser';
import defineMessages from '@app/utils/defineMessages';
import {
ArrowRightCircleIcon,
ExclamationTriangleIcon,
} from '@heroicons/react/24/outline';
import type { RequestResultsResponse } from '@server/interfaces/api/requestInterfaces';
import Link from 'next/link';
import { useIntl } from 'react-intl';
import useSWR from 'swr';
const messages = defineMessages('components.Discover.RecentRequestsSlider', {
unableToConnect:
'Unable to connect to {services}. Some information may be unavailable.',
});
const RecentRequestsSlider = () => {
const intl = useIntl();
const { hasPermission } = useUser();
const { data: requests, error: requestError } =
useSWR<RequestResultsResponse>(
'/api/v1/request?filter=all&take=10&sort=modified&skip=0',
@@ -21,6 +32,11 @@ const RecentRequestsSlider = () => {
return null;
}
const hasServiceErrors =
requests?.serviceErrors &&
(requests.serviceErrors.radarr.length > 0 ||
requests.serviceErrors.sonarr.length > 0);
return (
<>
<div className="slider-header">
@@ -29,6 +45,23 @@ const RecentRequestsSlider = () => {
<ArrowRightCircleIcon />
</Link>
</div>
{hasServiceErrors &&
(hasPermission(Permission.MANAGE_REQUESTS) ||
hasPermission(Permission.REQUEST_ADVANCED)) && (
<div className="service-error-banner">
<ExclamationTriangleIcon className="h-5 w-5 flex-shrink-0" />
<span>
{intl.formatMessage(messages.unableToConnect, {
services: [
...requests.serviceErrors.radarr.map((s) => s.name),
...requests.serviceErrors.sonarr.map((s) => s.name),
].join(', '),
})}
</span>
</div>
)}
<Slider
sliderKey="requests"
isLoading={!requests}