import { Injectable, inject } from '@angular/core'; import { SERVER_HEALTH_CHECK_TIMEOUT_MS } from '../constants/server-directory.infrastructure.constants'; import type { ServerEndpoint, ServerEndpointHealthResult, ServerHealthCheckPayload } from '../../domain/models/server-directory.model'; import { ServerEndpointCompatibilityService } from './server-endpoint-compatibility.service'; @Injectable({ providedIn: 'root' }) export class ServerEndpointHealthService { private readonly endpointCompatibility = inject(ServerEndpointCompatibilityService); async probeEndpoint( endpoint: Pick, clientVersion: string | null ): Promise { const startTime = Date.now(); try { const response = await fetch(`${endpoint.url}/api/health`, { method: 'GET', signal: AbortSignal.timeout(SERVER_HEALTH_CHECK_TIMEOUT_MS) }); const latency = Date.now() - startTime; if (response.ok) { const payload = await response.json() as ServerHealthCheckPayload; const versionCompatibility = this.endpointCompatibility.evaluateServerVersion( payload.serverVersion, clientVersion ); const serverInstanceId = typeof payload.serverInstanceId === 'string' && payload.serverInstanceId.trim().length > 0 ? payload.serverInstanceId.trim() : undefined; const serverTag = typeof payload.serverTag === 'string' && payload.serverTag.trim().length > 0 ? payload.serverTag.trim() : undefined; if (!versionCompatibility.isCompatible) { return { status: 'incompatible', latency, serverTag, versions: { serverInstanceId, serverVersion: versionCompatibility.serverVersion, clientVersion } }; } return { status: 'online', latency, serverTag, versions: { serverInstanceId, serverVersion: versionCompatibility.serverVersion, clientVersion } }; } return { status: 'offline' }; } catch { try { const response = await fetch(`${endpoint.url}/api/servers`, { method: 'GET', signal: AbortSignal.timeout(SERVER_HEALTH_CHECK_TIMEOUT_MS) }); const latency = Date.now() - startTime; if (response.ok) { return { status: 'online', latency }; } } catch { /* both checks failed */ } return { status: 'offline' }; } } }