fix(caddy): decouple status check from routes fetch, use useEffect for load trigger

Routes now load immediately from DB without waiting for the Caddy Admin API
status check (which can take up to 2s timeout). A dedicated useEffect on
caddyEnabled replaces the unreliable fire-and-forget call inside loadSettings.
This commit is contained in:
Brückner
2026-06-08 13:59:03 +02:00
parent 2857040803
commit 1526d25144

View File

@ -223,6 +223,10 @@ export default function Settings({ currentUser: _currentUser }: SettingsProps) {
.catch(() => {});
}, []);
useEffect(() => {
if (caddyEnabled) loadCaddyRoutes();
}, [caddyEnabled]);
async function loadSettings() {
setLoading(true);
setError('');
@ -255,7 +259,6 @@ export default function Settings({ currentUser: _currentUser }: SettingsProps) {
setSemaphoreProjectId(data.semaphore_project_id || '');
setCaddyEnabled(data.caddy_enabled === 'true');
setCaddyAdminUrl(data.caddy_admin_url || 'http://localhost:2019');
if (data.caddy_enabled === 'true') loadCaddyRoutes();
} catch {
setError('Network error loading settings.');
} finally {
@ -357,26 +360,18 @@ export default function Settings({ currentUser: _currentUser }: SettingsProps) {
}
async function loadCaddyRoutes() {
const [statusResult, routesResult] = await Promise.allSettled([
authFetch('/api/caddy/status'),
authFetch('/api/caddy/routes'),
]);
if (statusResult.status === 'fulfilled' && statusResult.value.ok) {
// Status check is background — never blocks route display
authFetch('/api/caddy/status')
.then(res => res.ok ? res.json() : null)
.then(s => setCaddyStatus(s?.available ? 'available' : 'unavailable'))
.catch(() => setCaddyStatus('unavailable'));
// Routes load immediately from DB
try {
const s = await statusResult.value.json();
setCaddyStatus(s.available ? 'available' : 'unavailable');
} catch {
setCaddyStatus('unavailable');
}
} else {
setCaddyStatus('unavailable');
}
if (routesResult.status === 'fulfilled' && routesResult.value.ok) {
try {
setCaddyRoutes(await routesResult.value.json());
const res = await authFetch('/api/caddy/routes');
if (res.ok) setCaddyRoutes(await res.json());
} catch {}
}
}
async function handleAddRoute() {
if (!newHostname.trim() || !newUpstream.trim()) return;
@ -918,7 +913,7 @@ export default function Settings({ currentUser: _currentUser }: SettingsProps) {
</span>
<button
type="button"
onClick={() => { setCaddyEnabled(v => !v); if (!caddyEnabled) loadCaddyRoutes(); }}
onClick={() => setCaddyEnabled((v: boolean) => !v)}
className={`relative w-10 h-5 rounded-full transition-all duration-200 focus:outline-none ${caddyEnabled ? 'bg-sky-600 shadow-[0_0_10px_rgba(2,132,199,0.4)]' : 'bg-slate-800 border border-slate-700'}`}
>
<span className={`absolute top-0.5 w-4 h-4 bg-white rounded-full shadow transition-all duration-200 ${caddyEnabled ? 'left-5' : 'left-0.5'}`} />