Private
Public Access
1
0

fix: resolve maintenance windows race condition and N+1 query
Some checks failed
CI Pipeline / Rust Format Check (pull_request) Failing after 3s
CI Pipeline / Clippy Lints (pull_request) Failing after 1s
CI Pipeline / Rust Unit Tests (pull_request) Failing after 2s
CI Pipeline / Security Audit (pull_request) Failing after 1s
CI Pipeline / Frontend Lint & Type Check (pull_request) Failing after 4s
CI Pipeline / Build .deb & Release (pull_request) Has been skipped

- Add GET /api/v1/maintenance-windows bulk endpoint to eliminate N+1
  per-host API calls (1 request instead of N+1)
- Fix two-phase state update race: setHosts() was called before
  setWindowsByHost(), causing React to render hosts with empty windows
- Add AbortController to cancel stale fetch requests on unmount/re-fetch
- Batch state updates atomically (React 18 auto-batching)
- Replace silent catch{} with proper error handling
- Add refreshData() wrapper for mutation handlers and Refresh button

Backend: maintenance_windows.rs - new list_all_windows handler +
all_windows_router(), mounted in main.rs
Frontend: client.ts - new listAll() API method
Frontend: MaintenanceWindowsPage.tsx - rewritten fetchData
This commit is contained in:
2026-05-22 03:17:34 +00:00
parent 2cc3d0db40
commit 3925cb48c1
4 changed files with 104 additions and 23 deletions

View File

@ -5,6 +5,7 @@ import type {
CreateHostRequest,
CreateJobRequest,
CreateMaintenanceWindowRequest,
MaintenanceWindow,
UpdateMaintenanceWindowRequest,
Certificate,
IssuedCert,
@ -176,6 +177,10 @@ export const patchesApi = {
// ── Maintenance Windows API ───────────────────────────────────────────────────
export const maintenanceWindowsApi = {
/** Bulk: fetch ALL maintenance windows across every host in one request. */
listAll: () =>
apiClient.get<{ windows: MaintenanceWindow[] }>('/maintenance-windows'),
/** Per-host: fetch windows for a single host. */
list: (hostId: string) =>
apiClient.get(`/hosts/${hostId}/maintenance-windows`),
create: (hostId: string, body: CreateMaintenanceWindowRequest) =>