|
|
@@ -88,6 +88,14 @@ export interface QueueStatus {
|
|
|
size: number;
|
|
|
}
|
|
|
|
|
|
+export interface HealthStatus {
|
|
|
+ status: 'ok' | 'error' | 'degraded';
|
|
|
+ message: string;
|
|
|
+ timestamp: string;
|
|
|
+ uptime?: number;
|
|
|
+ version?: string;
|
|
|
+}
|
|
|
+
|
|
|
class ApiClient {
|
|
|
// Get base URL dynamically at runtime to ensure server config is loaded
|
|
|
private getBaseUrl(): string {
|
|
|
@@ -146,6 +154,73 @@ class ApiClient {
|
|
|
return response.json();
|
|
|
}
|
|
|
|
|
|
+ // Enhanced health check with multiple endpoints and better error handling
|
|
|
+ async checkHealth(): Promise<HealthStatus> {
|
|
|
+ const endpoints = ['/health', '/status', '/'];
|
|
|
+
|
|
|
+ for (const endpoint of endpoints) {
|
|
|
+ try {
|
|
|
+ const response = await fetch(`${this.getBaseUrl()}${endpoint}`, {
|
|
|
+ method: 'GET',
|
|
|
+ headers: {
|
|
|
+ 'Content-Type': 'application/json',
|
|
|
+ },
|
|
|
+ // Add timeout to prevent hanging requests
|
|
|
+ signal: AbortSignal.timeout(5000),
|
|
|
+ });
|
|
|
+
|
|
|
+ if (response.ok) {
|
|
|
+ const data = await response.json();
|
|
|
+
|
|
|
+ // Normalize different possible response formats
|
|
|
+ const healthStatus: HealthStatus = {
|
|
|
+ status: 'ok',
|
|
|
+ message: 'API is running',
|
|
|
+ timestamp: new Date().toISOString(),
|
|
|
+ uptime: data.uptime,
|
|
|
+ version: data.version || data.build || data.git_version,
|
|
|
+ };
|
|
|
+
|
|
|
+ // Handle different response formats
|
|
|
+ if (data.status) {
|
|
|
+ if (data.status === 'healthy' || data.status === 'running' || data.status === 'ok') {
|
|
|
+ healthStatus.status = 'ok';
|
|
|
+ healthStatus.message = data.message || 'API is running';
|
|
|
+ } else if (data.status === 'degraded') {
|
|
|
+ healthStatus.status = 'degraded';
|
|
|
+ healthStatus.message = data.message || 'API is running in degraded mode';
|
|
|
+ } else {
|
|
|
+ healthStatus.status = 'error';
|
|
|
+ healthStatus.message = data.message || 'API status is unknown';
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return healthStatus;
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ // Continue to next endpoint if this one fails
|
|
|
+ console.warn(`Health check failed for endpoint ${endpoint}:`, error);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // If all endpoints fail
|
|
|
+ throw new Error('All health check endpoints are unavailable');
|
|
|
+ }
|
|
|
+
|
|
|
+ // Alternative simple connectivity check
|
|
|
+ async checkConnectivity(): Promise<boolean> {
|
|
|
+ try {
|
|
|
+ const response = await fetch(`${this.getBaseUrl()}`, {
|
|
|
+ method: 'HEAD',
|
|
|
+ signal: AbortSignal.timeout(3000),
|
|
|
+ });
|
|
|
+ return response.ok || response.status < 500; // Accept any non-server-error response
|
|
|
+ } catch (error) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
// Generation endpoints
|
|
|
async generateImage(params: GenerationRequest): Promise<JobInfo> {
|
|
|
return this.request<JobInfo>('/generate/text2img', {
|