Repository navigation
refactor(api): the main app's raw fetch tail goes through fetchWithAuth, and ApiClient gains an opt-in circuit breaker for polled dashboards (#12363) - #18398
Conversation
…te ChatManager (#11682) ApiCircuitBreaker.js had zero importers but circuit breaking is absent from ApiClient, so it is ported to utils/apiCircuitBreaker.ts and exposed as the opt-in RequestOptions.circuitBreaker. ChatManager.js (zero importers) is superseded by the chat store/ChatRepository. ApiClient error extraction moves to utils/apiErrorInfo.ts, keeping ApiClient.ts under its recorded size.
…uth (#12363) Onboarding status check (router), GlobalWebSocketService health ping, LiveEventService steering POST, HealthMonitor and ApiEndpointMapper keep their URL, method, body, credentials and timeout handling and now carry the bearer token and org header. Lowers the router and GlobalWebSocketService size ceilings.
…t ratchet (#12363) Adds a reasoned per-file exception list to the existing guard, scans .js for raw fetch, fails on a stale entry, and lowers the main-app raw_fetch baseline from 17 to 0 unlisted files.
…callers, thresholds from SSOT (#11682) usePrometheusMetrics (dashboard/services/alerts/metrics pollers) and useServiceMessages.fetchLatest opt in; ApiClient.get no longer retries a CircuitBreakerError. Thresholds move to ssot-config timeout config (VITE_CIRCUIT_FAILURE_THRESHOLD / VITE_CIRCUIT_RECOVERY_MS, defaults 3 / 30000). usePrometheusMetrics' local fetch() is renamed refresh() (public key stays fetch), so its raw-fetch allowlist entry is dropped (#12363).
…eaker, like the other monitoring pollers (#12363)
|
Warning Review limit reachedYou've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. Next included review available in 39 minutes. View limit details
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
Review (Sonnet) at a972d24: approve once one line is dropped. Required: Security: all five sites moved to Checked and fine:
LOWs, non-blocking:
|
✅ SSOT Configuration Compliance: Passing🎉 No new hardcoded values of either class — Known backlog in |
Refs #12363
Refs #11682
Refs #18241
Single-issue rationale
This is slice S3 of the one-ApiClient work under step 3 (#18241). It is the main app's raw-fetch tail, plus the zero-importer HTTP modules. The other slices are separate on purpose:
useUserStore.ts, which is in open PR feat(shell): Refined UI step 2: top nav and icon cluster, Minimal/Full mode, Appearance settings, one brand mark (#18240) #18373.#12363 and #11682 stay open. #12363 still needs its generated-types phase and the SLM axios slice (S4). #11682 still has its own fold steps for the Vision and FeatureFlags clients.
Thinking Path
The owner rule is one canonical client per app (ADR-008), reused and never duplicated. In the main app that client is
utils/ApiClient.ts, andfetchWithAuthis its helper.The owner's decision for the zero-importer modules was: "assess each, wire useful parts in; otherwise remove with zero-caller evidence". The results:
ChatManager.js: 0 importers (static imports, dynamicimport(),require,import.meta.glob, docs, stories, tests). It was a localStorage chat cache with 3 raw fetches, superseded by the chat store andChatRepository. Removed.ApiCircuitBreaker.js: 0 importers, butApiClienthad timeout and retry and no circuit breaking. The breaker is ported toutils/apiCircuitBreaker.tsand is opt-in per request viaRequestOptions.circuitBreaker. Its thresholds come from the SSOT config. It is wired into the polled monitoring callers. Its fake-503EnhancedFetchcache was a duplicate and is dropped.models/repositories/ApiRepository.ts: kept. The plan's "0 importers" was wrong:KnowledgeRepositoryandSystemRepositoryextend it.What Changed
Circuit breaker
utils/apiCircuitBreaker.tsopens after N failures (thrown errors or 502/503/504), stays open for the recovery window, then allows one half-open probe.ApiClient.rawRequesthonourscircuitBreaker: '<key>', andApiClient.getstops retrying onCircuitBreakerError. Requests that don't set the option behave as before.ssot-config.ts(timeout.circuitFailureThresholdfromVITE_CIRCUIT_FAILURE_THRESHOLD, default 3;timeout.circuitRecoveryMsfromVITE_CIRCUIT_RECOVERY_MS, default 30000). The defaults are those of the old module.usePrometheusMetrics: dashboard, services and alerts pollers, plususeSystemMetrics,useServicesHealthanduseAlerts; keymonitoring.useServiceMessages.fetchLatest: keyservice-messages.useErrorMonitoring's seven GETs: keyerror-monitoring.useSystemStatus(it goes throughapiEndpointMapper.fetchWithFallback, which has its own fallback), and interactive or POST callers._extractErrorInfomoved toutils/apiErrorInfo.ts.ApiClient.tsgoes from 842 to 834 lines, and its ceiling is lowered in both baseline files.Raw fetch sites moved onto
fetchWithAuth, with behaviour deltas:router/index.tsonboarding statusX-Organization-Id. Credentials, Accept and fail-open handling unchanged.GlobalWebSocketService.quickHealthCheckLiveEventService.sendSteeringMessageHealthMonitor.checkBackendHealthApiEndpointMapperfetchWithAuthwas used rather thanapiClient.rawRequest, which would have added the 401 logout redirect to health pings.slmClient.tsstays a raw fetch: it targets the SLM origin with its own token, and must not send the main-app JWT.Ratchet:
repo_tests/frontend_api_contract_ratchet_test.pygains_RAW_FETCH_EXCEPTIONS, a per-file allowlist where each entry carries a one-line reason.AppConfig.js,ServiceDiscovery.js,ssot-config.ts;DesktopInterface,AutobotWidget,RumAgent,thumbnailWorker,VideoProcessor,useConnectionTester;ApiClient,fetchWithAuth,slmClient;useTimeoutJSDoc..js. TheusePrometheusMetricslocalfetchis renamedrefresh, and the returned key staysfetch, so callers are unchanged.raw_fetchgoes from 17 to 0 unlisted.clientsstays at 8. SLM constants are unchanged; that's slice S4.Docs (#11682):
docs/developer/FRONTEND_API_CLIENTS.mdexplains when to use which client:ApiClient,fetchWithAuth, the circuit breaker, the domain clients,ApiService,BatchApiService,WorkflowBuilderApiClientandSlmClient.ApiClient.tslinks to it.Verification
npm run type-check(autobot-frontend) at heada972d24241: rc=0, 0error TS, 193 s. Pushed withAUTOBOT_PREPUSH_ALLOW_TIMEOUT=1(owner-approved). The hook's vue-tsc timed out at its 159 s budget under machine load (load average about 10), so I ran it manually above. In the hook, vitest and pytest passed.npx vitest run: 3716 passed, 1 failed. The failure,WorkflowCanvas.orgMode, passed 21/21 when run alone; it's in the test(frontend): four vitest files fail in the full run but pass in isolation #18254 family.useActionQueue(a 10 s timeout under load), passed 4/4 alone.pollerCircuitBreaker.test.ts: 3/3. For each wired caller, the call after the first failed one makes no network request.apiCircuitBreaker.spec.ts(7),ApiClient.circuitBreaker.spec.ts(2, with a contrast case without the option),rawFetchMigration.test.ts(3).pytest repo_tests/frontend_api_contract_ratchet_test.py frontend_file_size_ratchet_test.py frontend_fragmentation_ratchet_test.py symbol_fork_ratchet_17312_test.pyat heada972d24241: 106 passed.Model Used
Claude Opus 5.5 (coordinating). Sonnet subagents did the planning and the implementation.
🤖 Generated with Claude Code