All files / src/lib health-check.ts

0% Statements 0/78
0% Branches 0/1
0% Functions 0/1
0% Lines 0/78

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138                                                                                                                                                                                                                                                                                   
/**
 * Health Check Library
 *
 * Provides Tauri health check command wrappers and utilities
 * for monitoring the health status of the OpenFang backend.
 */
 
import { invoke } from '@tauri-apps/api/core';
import { isTauriRuntime } from './tauri-gateway';
 
// === Types ===
 
export type HealthStatus = 'healthy' | 'unhealthy' | 'unknown';
 
export interface HealthCheckResult {
  status: HealthStatus;
  message?: string;
  timestamp: number;
  details?: Record<string, unknown>;
}
 
export interface OpenFangHealthResponse {
  healthy: boolean;
  message?: string;
  details?: Record<string, unknown>;
}
 
// === Health Check Functions ===
 
/**
 * Perform a single health check via Tauri command.
 * Returns a structured result with status, message, and timestamp.
 */
export async function performHealthCheck(): Promise<HealthCheckResult> {
  const timestamp = Date.now();
 
  if (!isTauriRuntime()) {
    return {
      status: 'unknown',
      message: 'Not running in Tauri environment',
      timestamp,
    };
  }
 
  try {
    const response = await invoke<OpenFangHealthResponse>('openfang_health_check');
 
    return {
      status: response.healthy ? 'healthy' : 'unhealthy',
      message: response.message,
      timestamp,
      details: response.details,
    };
  } catch (error) {
    const errorMessage = error instanceof Error ? error.message : String(error);
    return {
      status: 'unhealthy',
      message: `Health check failed: ${errorMessage}`,
      timestamp,
    };
  }
}
 
/**
 * Create a periodic health check scheduler.
 * Returns cleanup function to stop the interval.
 */
export function createHealthCheckScheduler(
  callback: (result: HealthCheckResult) => void,
  intervalMs: number = 30000 // Default: 30 seconds
): () => void {
  let intervalId: ReturnType<typeof setInterval> | null = null;
  let isChecking = false;
 
  const check = async () => {
    // Prevent overlapping checks
    if (isChecking) return;
    isChecking = true;
 
    try {
      const result = await performHealthCheck();
      callback(result);
    } catch (error) {
      console.error('[HealthCheck] Scheduled check failed:', error);
      callback({
        status: 'unknown',
        message: error instanceof Error ? error.message : 'Unknown error',
        timestamp: Date.now(),
      });
    } finally {
      isChecking = false;
    }
  };
 
  // Perform initial check immediately
  check();
 
  // Schedule periodic checks
  intervalId = setInterval(check, intervalMs);
 
  // Return cleanup function
  return () => {
    if (intervalId !== null) {
      clearInterval(intervalId);
      intervalId = null;
    }
  };
}
 
// === Utility Functions ===
 
/**
 * Get a human-readable label for a health status.
 */
export function getHealthStatusLabel(status: HealthStatus): string {
  switch (status) {
    case 'healthy':
      return '健康';
    case 'unhealthy':
      return '异常';
    case 'unknown':
    default:
      return '未知';
  }
}
 
/**
 * Format a timestamp for display.
 */
export function formatHealthCheckTime(timestamp: number): string {
  const date = new Date(timestamp);
  return date.toLocaleTimeString('zh-CN', {
    hour: '2-digit',
    minute: '2-digit',
    second: '2-digit',
  });
}