953ba951db
CI / checks (pull_request) Failing after 13m18s
Adds GET /api/clouds/:cloud/diagnostics and a Diagnostics page in the General nav. The report combines, in one call: - runtime reachability, latency, version and edition from /_floci/health - every service the runtime emulates, with the console pages backed by it - per-console-service probes (the existing status check) - EC2 instance containers from /_floci/diagnose - console uptime, sign-in mode and active session count Each source is optional, so a down runtime still yields a partial report.
117 lines
4.1 KiB
TypeScript
117 lines
4.1 KiB
TypeScript
import {useQuery} from '@tanstack/react-query'
|
|
import {
|
|
getCloudDiagnostics,
|
|
getCloudResource,
|
|
getCloudServiceStatus,
|
|
getCloudStatus,
|
|
listCloudResources,
|
|
listCloudServices,
|
|
listClouds,
|
|
} from '@/api/cloudProxyClient'
|
|
import type {CloudProvider, CloudServiceDescriptor, CloudServiceType, CloudStatus} from '@/types/cloud'
|
|
|
|
/**
|
|
* Shared cloud queries.
|
|
*
|
|
* These live under api/ rather than in a feature folder because the app shell
|
|
* (nav, connection indicator) needs them as much as the console home does.
|
|
* Key strings are unchanged so existing caches still share.
|
|
*/
|
|
export const cloudQueryKeys = {
|
|
clouds: ['clouds'] as const,
|
|
services: (cloud: CloudProvider) => ['cloud-services', cloud] as const,
|
|
status: (cloud: CloudProvider) => ['cloud-status', cloud] as const,
|
|
diagnostics: (cloud: CloudProvider) => ['cloud-diagnostics', cloud] as const,
|
|
serviceStatus: (cloud: CloudProvider, service: CloudServiceType) =>
|
|
['cloud-service-status', cloud, service] as const,
|
|
resources: (cloud: CloudProvider, service: CloudServiceType) =>
|
|
['cloud-console-resources', cloud, service] as const,
|
|
resource: (cloud: CloudProvider, service: CloudServiceType, id: string) =>
|
|
['cloud-resource', cloud, service, id] as const,
|
|
}
|
|
|
|
export function useCloudsQuery() {
|
|
return useQuery({
|
|
queryKey: cloudQueryKeys.clouds,
|
|
queryFn: ({signal}) => listClouds(signal),
|
|
})
|
|
}
|
|
|
|
export function useCloudServicesQuery(cloud: CloudProvider) {
|
|
return useQuery({
|
|
queryKey: cloudQueryKeys.services(cloud),
|
|
queryFn: ({signal}) => listCloudServices(cloud, signal),
|
|
// The catalog only changes when the API restarts, so this is effectively
|
|
// free on every navigation while still driving the whole nav.
|
|
staleTime: 60_000,
|
|
})
|
|
}
|
|
|
|
export function useCloudStatusQuery(cloud: CloudProvider, options: {refetchInterval?: number} = {}) {
|
|
return useQuery({
|
|
queryKey: cloudQueryKeys.status(cloud),
|
|
queryFn: ({signal}) => getCloudStatus(cloud, signal),
|
|
refetchInterval: options.refetchInterval ?? 10_000,
|
|
})
|
|
}
|
|
|
|
/** Full runtime report; polled slowly because it probes every console service. */
|
|
export function useCloudDiagnosticsQuery(cloud: CloudProvider) {
|
|
return useQuery({
|
|
queryKey: cloudQueryKeys.diagnostics(cloud),
|
|
queryFn: ({signal}) => getCloudDiagnostics(cloud, signal),
|
|
refetchInterval: 30_000,
|
|
})
|
|
}
|
|
|
|
/** Health of the single service being viewed, rather than of the whole cloud. */
|
|
export function useCloudServiceStatusQuery(
|
|
cloud: CloudProvider,
|
|
service: CloudServiceType,
|
|
options: {enabled?: boolean} = {},
|
|
) {
|
|
return useQuery({
|
|
queryKey: cloudQueryKeys.serviceStatus(cloud, service),
|
|
queryFn: ({signal}) => getCloudServiceStatus(cloud, service, signal),
|
|
refetchInterval: 10_000,
|
|
enabled: options.enabled ?? true,
|
|
})
|
|
}
|
|
|
|
export function useCloudConsoleResourcesQuery({
|
|
cloud,
|
|
service,
|
|
services,
|
|
status,
|
|
}: {
|
|
cloud: CloudProvider
|
|
service: CloudServiceType
|
|
services?: CloudServiceDescriptor[]
|
|
status?: CloudStatus
|
|
}) {
|
|
return useQuery({
|
|
queryKey: cloudQueryKeys.resources(cloud, service),
|
|
queryFn: ({signal}) => listCloudResources(cloud, service, undefined, signal),
|
|
enabled: hasAvailableService(services, service) && status?.runtime === 'reachable',
|
|
})
|
|
}
|
|
|
|
export function useCloudResourceQuery(
|
|
cloud: CloudProvider,
|
|
service: CloudServiceType,
|
|
id?: string,
|
|
) {
|
|
return useQuery({
|
|
queryKey: cloudQueryKeys.resource(cloud, service, id ?? ''),
|
|
queryFn: ({signal}) => getCloudResource(cloud, service, id!, signal),
|
|
enabled: Boolean(id),
|
|
// A list refresh returns summary rows. Keep the inspected resource cached
|
|
// until the user selects a different state machine.
|
|
staleTime: Infinity,
|
|
})
|
|
}
|
|
|
|
function hasAvailableService(services: CloudServiceDescriptor[] | undefined, service: CloudServiceType): boolean {
|
|
return services?.some((item) => item.service === service && item.availability === 'available') ?? false
|
|
}
|