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
- Backend API Specification
- Frontend Implementation
- Service Methods
- Usage Examples
- Use Cases
- Error Handling
- Testing
- Troubleshooting
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
-
Start the backend:
cd cloud/maplepress-backend task dev -
Test with curl:
curl -X GET http://localhost:8000/healthExpected response:
{ "status": "healthy" } -
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:
- Verify backend is running:
curl http://localhost:8000/health - Check
VITE_API_BASE_URLin.envfile - Verify no CORS issues in browser console
- Check firewall/network settings
Issue: "Backend service is temporarily unavailable"
Symptoms: 503 status code
Solutions:
- Backend may be starting up - wait a few seconds
- Check backend logs:
docker logs mapleopentech_backend - Verify backend services (Cassandra, Redis) are running
- Restart backend:
task end && task dev
Issue: Health check timeout
Symptoms: Slow or no response
Solutions:
- Check backend server load
- Verify network latency
- Check if backend is overloaded
- Consider increasing timeout in
waitUntilHealthy()
Issue: Always returns unhealthy
Symptoms: isHealthy() always returns false
Solutions:
- Check browser console for errors
- Verify API base URL is correct
- Check CORS configuration
- 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