monorepo/web/maplepress-frontend/docs/API/HEALTH_API.md

16 KiB

Health Check API Integration

This document describes the integration between the MaplePress frontend and the Health Check API endpoint.

Table of Contents


Overview

The Health Check API is a simple, unauthenticated endpoint that verifies the MaplePress backend service is running and operational. It's commonly used for:

  • Monitoring: Service availability checks
  • Load Balancers: Health probe endpoints
  • Startup Verification: Ensuring backend is ready before initializing frontend
  • API Connectivity: Testing network connectivity to backend

Key Features

  • No Authentication Required: Public endpoint
  • Simple Response: Returns { "status": "healthy" }
  • Fast Response: Lightweight check with minimal processing
  • Always Available: Does not depend on database or external services

Backend API Specification

Endpoint

GET /health

Authentication

None required - This is a public endpoint.

Request Headers

No headers required.

Request Parameters

None.

Response (200 OK)

{
  "status": "healthy"
}

Response Fields

Field Type Description
status string Health status - always "healthy" when service is running

Error Responses

  • 503 Service Unavailable: Backend service is down or unreachable
  • Network errors: Connection refused, timeout, etc.

Backend Implementation

Handler File: cloud/maplepress-backend/internal/interface/http/handler/healthcheck/healthcheck_handler.go

func (h *Handler) Handle(w http.ResponseWriter, r *http.Request) {
    response := map[string]string{
        "status": "healthy",
    }
    httpresponse.OK(w, response)
}

Frontend Implementation

Service File

Location: src/services/API/HealthService.js

Dependencies

import ApiClient from "./ApiClient";

Architecture

The HealthService follows the same three-layer architecture as other API services:

┌─────────────────────────────────────┐
│     React Components (UI)           │
│  - Dashboard, Status Indicators     │
└─────────────┬───────────────────────┘
              │
              ↓
┌─────────────────────────────────────┐
│     HealthService (API Layer)       │
│  - checkHealth()                    │
│  - isHealthy()                      │
│  - waitUntilHealthy()               │
│  - getDetailedStatus()              │
└─────────────┬───────────────────────┘
              │
              ↓
┌─────────────────────────────────────┐
│     ApiClient (HTTP Layer)          │
│  - GET /health                      │
└─────────────┬───────────────────────┘
              │
              ↓
┌─────────────────────────────────────┐
│     Backend API                     │
│  GET /health → { status: "healthy" }│
└─────────────────────────────────────┘

Service Methods

1. checkHealth()

Check if the backend service is healthy.

Signature:

async function checkHealth(): Promise<Object>

Returns:

{
  status: "healthy"
}

Throws: Error if service is unreachable or unhealthy

Example:

import HealthService from './services/API/HealthService';

try {
  const health = await HealthService.checkHealth();
  if (health.status === 'healthy') {
    console.log('✅ Backend is healthy');
  }
} catch (error) {
  console.error('❌ Backend is down:', error.message);
}

2. isHealthy()

Simple boolean check for backend health.

Signature:

async function isHealthy(): Promise<boolean>

Returns: true if backend is healthy, false otherwise

Example:

const healthy = await HealthService.isHealthy();

if (healthy) {
  console.log('✅ Backend is ready');
} else {
  console.error('❌ Backend is not available');
}

Use Case: Quick status checks, conditional rendering


3. waitUntilHealthy()

Wait for the backend to become healthy (with retries).

Signature:

async function waitUntilHealthy(options?: Object): Promise<boolean>

Parameters:

{
  maxAttempts: number,    // Maximum retry attempts (default: 30)
  retryDelayMs: number    // Delay between attempts in ms (default: 1000)
}

Returns: true if backend became healthy, false if timeout

Example:

// Wait up to 10 seconds (10 attempts x 1 second)
const ready = await HealthService.waitUntilHealthy({
  maxAttempts: 10,
  retryDelayMs: 1000
});

if (ready) {
  console.log('✅ Backend is ready!');
  // Proceed with app initialization
} else {
  console.error('❌ Backend did not become ready in time');
  // Show error message to user
}

Use Case: Application startup, waiting for backend deployment


4. getDetailedStatus()

Get detailed health status with timing information.

Signature:

async function getDetailedStatus(): Promise<Object>

Returns:

{
  healthy: boolean,        // Whether backend is healthy
  status: string,          // "healthy" or "unhealthy"
  responseTimeMs: number,  // Response time in milliseconds
  timestamp: Date,         // When check was performed
  error?: string           // Error message if unhealthy
}

Example:

const status = await HealthService.getDetailedStatus();

console.log(`Backend Status: ${status.status}`);
console.log(`Response Time: ${status.responseTimeMs}ms`);
console.log(`Checked At: ${status.timestamp.toISOString()}`);

if (!status.healthy) {
  console.error(`Error: ${status.error}`);
}

Use Case: Monitoring dashboards, performance tracking, diagnostics


Usage Examples

Example 1: Application Startup Check

Check backend health before initializing the app:

// In App.jsx or main.jsx
import { useEffect, useState } from 'react';
import HealthService from './services/API/HealthService';

function App() {
  const [backendReady, setBackendReady] = useState(false);
  const [error, setError] = useState(null);

  useEffect(() => {
    async function checkBackend() {
      try {
        const healthy = await HealthService.isHealthy();
        setBackendReady(healthy);

        if (!healthy) {
          setError('Backend service is not available');
        }
      } catch (err) {
        setError(err.message);
      }
    }

    checkBackend();
  }, []);

  if (error) {
    return <div className="error">Backend Error: {error}</div>;
  }

  if (!backendReady) {
    return <div className="loading">Connecting to backend...</div>;
  }

  return <div>App content...</div>;
}

Example 2: Status Indicator Component

Show real-time backend status:

import { useEffect, useState } from 'react';
import HealthService from '../services/API/HealthService';

function BackendStatusIndicator() {
  const [status, setStatus] = useState(null);

  useEffect(() => {
    // Check status every 30 seconds
    const checkStatus = async () => {
      const detail = await HealthService.getDetailedStatus();
      setStatus(detail);
    };

    checkStatus();
    const interval = setInterval(checkStatus, 30000);

    return () => clearInterval(interval);
  }, []);

  if (!status) {
    return <span>Checking...</span>;
  }

  return (
    <div className={`status-indicator ${status.healthy ? 'healthy' : 'unhealthy'}`}>
      <span className="status-dot"></span>
      <span className="status-text">
        Backend: {status.status} ({status.responseTimeMs}ms)
      </span>
    </div>
  );
}

Example 3: Deployment Health Check

Wait for backend after deployment:

import HealthService from './services/API/HealthService';

async function waitForBackend() {
  console.log('Waiting for backend to become ready...');

  const ready = await HealthService.waitUntilHealthy({
    maxAttempts: 60,      // Wait up to 1 minute
    retryDelayMs: 1000    // Check every second
  });

  if (ready) {
    console.log('✅ Backend is ready!');
    return true;
  } else {
    console.error('❌ Backend deployment timeout');
    return false;
  }
}

// Usage in deployment script
if (await waitForBackend()) {
  // Proceed with app initialization
} else {
  // Show deployment error message
}

Example 4: Error Recovery

Retry failed API calls after backend recovers:

import HealthService from './services/API/HealthService';
import SiteService from './services/API/SiteService';

async function fetchSitesWithRetry() {
  try {
    // Try to fetch sites
    const sites = await SiteService.listSites();
    return sites;
  } catch (error) {
    console.error('Failed to fetch sites:', error);

    // Check if backend is healthy
    const healthy = await HealthService.isHealthy();

    if (!healthy) {
      console.log('Backend is down, waiting for recovery...');

      // Wait for backend to recover
      const recovered = await HealthService.waitUntilHealthy({
        maxAttempts: 10,
        retryDelayMs: 2000
      });

      if (recovered) {
        console.log('Backend recovered, retrying...');
        return await SiteService.listSites();
      }
    }

    throw error;
  }
}

Use Cases

1. Monitoring & Observability

  • Service uptime monitoring
  • Response time tracking
  • Health dashboard indicators
  • Alerting on service degradation

2. Load Balancer Integration

  • Health probe endpoint for AWS/Azure/GCP load balancers
  • Kubernetes liveness/readiness probes
  • Docker healthcheck configuration

3. Application Lifecycle

  • Startup health verification
  • Graceful degradation on backend issues
  • Post-deployment verification
  • Environment validation (dev/staging/prod)

4. User Experience

  • Show connection status to users
  • Prevent API calls when backend is down
  • Display maintenance mode messages
  • Automatic retry on recovery

5. Development & Testing

  • Verify backend is running before tests
  • E2E test prerequisites
  • Local development environment checks
  • CI/CD pipeline health gates

Error Handling

Network Errors

try {
  await HealthService.checkHealth();
} catch (error) {
  if (error.message.includes('network') || error.message.includes('fetch')) {
    // Network connectivity issue
    console.error('Cannot reach backend - check network');
  }
}

Service Unavailable

try {
  await HealthService.checkHealth();
} catch (error) {
  if (error.message.includes('503') || error.message.includes('unavailable')) {
    // Backend is down or restarting
    console.error('Backend service is unavailable');
  }
}

Timeout Handling

// With timeout wrapper
async function checkHealthWithTimeout(timeoutMs = 5000) {
  const timeoutPromise = new Promise((_, reject) =>
    setTimeout(() => reject(new Error('Health check timeout')), timeoutMs)
  );

  try {
    return await Promise.race([
      HealthService.checkHealth(),
      timeoutPromise
    ]);
  } catch (error) {
    console.error('Health check failed or timed out:', error.message);
    return { status: 'unhealthy' };
  }
}

Testing

Manual Testing

  1. Start the backend:

    cd cloud/maplepress-backend
    task dev
    
  2. Test with curl:

    curl -X GET http://localhost:8000/health
    

    Expected response:

    { "status": "healthy" }
    
  3. Test from frontend:

    // In browser console
    import HealthService from './services/API/HealthService.js';
    
    const health = await HealthService.checkHealth();
    console.log(health); // { status: "healthy" }
    

Automated Testing

// Example test (using Jest or Vitest)
import HealthService from '../services/API/HealthService';

describe('HealthService', () => {
  it('should return healthy status when backend is up', async () => {
    const health = await HealthService.checkHealth();
    expect(health.status).toBe('healthy');
  });

  it('should return true for isHealthy()', async () => {
    const healthy = await HealthService.isHealthy();
    expect(healthy).toBe(true);
  });

  it('should include response time in detailed status', async () => {
    const status = await HealthService.getDetailedStatus();
    expect(status).toHaveProperty('responseTimeMs');
    expect(status.responseTimeMs).toBeGreaterThan(0);
  });
});

Troubleshooting

Issue: "Unable to connect to backend service"

Symptoms: Network or fetch errors

Solutions:

  1. Verify backend is running: curl http://localhost:8000/health
  2. Check VITE_API_BASE_URL in .env file
  3. Verify no CORS issues in browser console
  4. Check firewall/network settings

Issue: "Backend service is temporarily unavailable"

Symptoms: 503 status code

Solutions:

  1. Backend may be starting up - wait a few seconds
  2. Check backend logs: docker logs mapleopentech_backend
  3. Verify backend services (Cassandra, Redis) are running
  4. Restart backend: task end && task dev

Issue: Health check timeout

Symptoms: Slow or no response

Solutions:

  1. Check backend server load
  2. Verify network latency
  3. Check if backend is overloaded
  4. Consider increasing timeout in waitUntilHealthy()

Issue: Always returns unhealthy

Symptoms: isHealthy() always returns false

Solutions:

  1. Check browser console for errors
  2. Verify API base URL is correct
  3. Check CORS configuration
  4. Test endpoint directly with curl

Best Practices

1. Use During Initialization

Always check backend health during app startup:

useEffect(() => {
  HealthService.isHealthy().then(healthy => {
    if (!healthy) {
      showBackendError();
    }
  });
}, []);

2. Periodic Health Checks

For long-running apps, check periodically:

// Every 5 minutes
setInterval(async () => {
  const healthy = await HealthService.isHealthy();
  updateStatusIndicator(healthy);
}, 300000);

3. Handle Failures Gracefully

Don't throw errors to users - handle them gracefully:

const healthy = await HealthService.isHealthy().catch(() => false);
if (!healthy) {
  showOfflineMode();
}

4. Log Response Times

Monitor performance over time:

const status = await HealthService.getDetailedStatus();
analytics.track('backend_health', {
  responseTime: status.responseTimeMs,
  healthy: status.healthy
});

Integration with Other Services

The HealthService can be combined with other services for robust error handling:

import HealthService from './services/API/HealthService';
import AuthManager from './services/Manager/AuthManager';

async function safeLogin(email, password) {
  // Check backend health first
  const healthy = await HealthService.isHealthy();

  if (!healthy) {
    throw new Error('Backend is currently unavailable. Please try again later.');
  }

  // Proceed with login
  return await AuthManager.login({ email, password });
}

Summary

The Health Check API provides a simple, reliable way to verify backend availability:

  • Simple Integration: One GET request, no auth required
  • Multiple Helper Methods: checkHealth(), isHealthy(), waitUntilHealthy(), getDetailedStatus()
  • Error Handling: Comprehensive error detection and user-friendly messages
  • Flexible Usage: Startup checks, monitoring, status indicators, deployment verification
  • Production Ready: Tested against backend implementation

For questions or issues, refer to the Troubleshooting section or check the main README.


Last Updated: October 30, 2024 Frontend Version: 0.0.0 Backend API Version: 1.0.0