Files
chorus-services-website/healthcheck.js
anthonyrawlins f343f89d24 Initial commit: CHORUS Services marketing website
Complete Next.js website with Docker containerization:
- Next.js 14 with TypeScript and Tailwind CSS
- Responsive design with modern UI components
- Hero section, features showcase, testimonials
- FAQ section with comprehensive content
- Contact forms and newsletter signup
- Docker production build with Nginx
- Health checks and monitoring support
- SEO optimization and performance tuning

Ready for integration as git submodule in main CHORUS project.

Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-01 22:45:06 +10:00

138 lines
3.8 KiB
JavaScript

#!/usr/bin/env node
/**
* CHORUS Services Website - Health Check Script
* Validates that both Nginx and Next.js are running correctly
* Used by Docker HEALTHCHECK instruction
*/
const http = require('http');
const process = require('process');
const NGINX_PORT = 80;
const NEXTJS_PORT = 3000;
const TIMEOUT = 5000; // 5 seconds
/**
* Make HTTP request to check service health
* @param {number} port - Port to check
* @param {string} path - Path to request
* @param {string} service - Service name for logging
* @returns {Promise<boolean>} - True if healthy
*/
function checkService(port, path, service) {
return new Promise((resolve) => {
const options = {
hostname: 'localhost',
port: port,
path: path,
method: 'GET',
timeout: TIMEOUT,
headers: {
'User-Agent': 'HealthCheck/1.0'
}
};
const req = http.request(options, (res) => {
const isHealthy = res.statusCode >= 200 && res.statusCode < 400;
if (isHealthy) {
console.log(`${service} is healthy (${res.statusCode})`);
} else {
console.error(`${service} returned status ${res.statusCode}`);
}
resolve(isHealthy);
});
req.on('error', (error) => {
console.error(`${service} error: ${error.message}`);
resolve(false);
});
req.on('timeout', () => {
console.error(`${service} timeout after ${TIMEOUT}ms`);
req.destroy();
resolve(false);
});
req.setTimeout(TIMEOUT);
req.end();
});
}
/**
* Check system resources and limits
* @returns {boolean} - True if resources are healthy
*/
function checkResources() {
try {
const memUsage = process.memoryUsage();
const memUsedMB = Math.round(memUsage.rss / 1024 / 1024);
const memLimit = 128; // 128MB limit as per docker-compose
if (memUsedMB > memLimit * 0.9) {
console.error(`✗ High memory usage: ${memUsedMB}MB (limit: ${memLimit}MB)`);
return false;
}
console.log(`✓ Memory usage: ${memUsedMB}MB`);
return true;
} catch (error) {
console.error(`✗ Resource check failed: ${error.message}`);
return false;
}
}
/**
* Main health check function
*/
async function main() {
console.log('CHORUS Website Health Check');
console.log('===========================');
const startTime = Date.now();
try {
// Check all services in parallel
const [nginxHealthy, nextjsHealthy, resourcesHealthy] = await Promise.all([
checkService(NGINX_PORT, '/health', 'Nginx'),
checkService(NEXTJS_PORT, '/', 'Next.js'),
Promise.resolve(checkResources())
]);
const allHealthy = nginxHealthy && nextjsHealthy && resourcesHealthy;
const duration = Date.now() - startTime;
console.log(`\nHealth check completed in ${duration}ms`);
if (allHealthy) {
console.log('✓ All services are healthy');
process.exit(0);
} else {
console.error('✗ One or more services are unhealthy');
process.exit(1);
}
} catch (error) {
console.error(`Health check failed: ${error.message}`);
process.exit(1);
}
}
// Handle process signals
process.on('SIGTERM', () => {
console.log('Health check interrupted by SIGTERM');
process.exit(1);
});
process.on('SIGINT', () => {
console.log('Health check interrupted by SIGINT');
process.exit(1);
});
// Run health check
main().catch((error) => {
console.error(`Unexpected error: ${error.message}`);
process.exit(1);
});