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>
This commit is contained in:
138
healthcheck.js
Normal file
138
healthcheck.js
Normal file
@@ -0,0 +1,138 @@
|
||||
#!/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);
|
||||
});
|
||||
Reference in New Issue
Block a user