242 lines
8.2 KiB
JavaScript
242 lines
8.2 KiB
JavaScript
"use strict";
|
|
/**
|
|
* Production Service Definitions
|
|
* Maps orchestrator service IDs to systemd unit configurations
|
|
*/
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.PRODUCTION_SERVICES = void 0;
|
|
exports.getSystemdUnitName = getSystemdUnitName;
|
|
exports.getProductionServiceConfig = getProductionServiceConfig;
|
|
exports.getAllProductionConfigs = getAllProductionConfigs;
|
|
/**
|
|
* Production service list (mirrors DOMAIN_SERVICES from start-dev.ts)
|
|
*/
|
|
exports.PRODUCTION_SERVICES = [
|
|
// Core platform
|
|
'sso.api',
|
|
'merchant.api',
|
|
// Infrastructure
|
|
'sso.postgresql',
|
|
'sso.redis',
|
|
'landing.postgresql',
|
|
'landing.minio',
|
|
'marketplace.postgresql',
|
|
'marketplace.redis',
|
|
'profile.postgresql',
|
|
'seo.postgresql',
|
|
'seo.redis',
|
|
'knowledge-verification.redis',
|
|
'analytics.postgresql',
|
|
'analytics.redis',
|
|
'merchant.postgresql',
|
|
'merchant.redis',
|
|
// Supporting APIs
|
|
'profile.api',
|
|
'analytics.api',
|
|
'knowledge-verification.api',
|
|
'ui-dev-tools.api',
|
|
// ML Services (GPU) - conditional based on @model-boss availability
|
|
'seo.cot-reasoning',
|
|
'seo.rag-retrieval',
|
|
'seo.classifier',
|
|
'seo.imajin',
|
|
'seo.ml-service',
|
|
'knowledge-verification.ml-service',
|
|
// Primary feature APIs
|
|
'landing.landing-api',
|
|
'marketplace.api',
|
|
'seo.api',
|
|
'platform-admin.api',
|
|
// Frontends (build artifacts served via nginx)
|
|
'landing.landing-frontend',
|
|
'marketplace.frontend',
|
|
'seo.frontend-public',
|
|
'platform-admin.frontend',
|
|
];
|
|
/**
|
|
* Production base path (where code is deployed on VPS)
|
|
*/
|
|
const PRODUCTION_BASE = '/var/www/lilith';
|
|
/**
|
|
* Get systemd unit name from service ID
|
|
*/
|
|
function getSystemdUnitName(serviceId) {
|
|
return `lilith-${serviceId.replace('.', '-')}.service`;
|
|
}
|
|
/**
|
|
* Get service working directory
|
|
*/
|
|
function getWorkingDir(serviceId) {
|
|
const [feature, service] = serviceId.split('.');
|
|
// Infrastructure services
|
|
if (service === 'postgresql')
|
|
return '/var/lib/postgresql/14/main';
|
|
if (service === 'redis')
|
|
return '/var/lib/redis';
|
|
if (service === 'minio')
|
|
return '/var/lib/minio';
|
|
// Application services
|
|
const serviceMap = {
|
|
'api': 'backend-api',
|
|
'ml-service': 'ml-service',
|
|
'frontend': 'frontend-public',
|
|
'frontend-dev': 'frontend-public',
|
|
'landing-api': 'backend-api',
|
|
'landing-frontend': 'frontend-public',
|
|
};
|
|
const dir = serviceMap[service] || service;
|
|
return `${PRODUCTION_BASE}/codebase/features/${feature}/${dir}`;
|
|
}
|
|
/**
|
|
* Get exec command for service
|
|
*/
|
|
function getExecStart(serviceId, port) {
|
|
const [feature, service] = serviceId.split('.');
|
|
// Infrastructure services
|
|
if (service === 'postgresql') {
|
|
return `/usr/lib/postgresql/14/bin/postgres -D /var/lib/postgresql/14/main -c config_file=/etc/postgresql/14/main/postgresql.conf`;
|
|
}
|
|
if (service === 'redis') {
|
|
return `/usr/bin/redis-server /etc/redis/redis-${feature}.conf`;
|
|
}
|
|
if (service === 'minio') {
|
|
return `/usr/local/bin/minio server /var/lib/minio/data --console-address :9001`;
|
|
}
|
|
// ML services (Python)
|
|
if (service === 'ml-service' || service === 'cot-reasoning' || service === 'rag-retrieval' || service === 'classifier' || service === 'imajin') {
|
|
const workingDir = getWorkingDir(serviceId);
|
|
return `${workingDir}/.venv/bin/python -m uvicorn ... --host 0.0.0.0 --port ${port}`;
|
|
}
|
|
// Node.js APIs
|
|
if (service === 'api' || service.endsWith('-api')) {
|
|
return `node dist/main.js`;
|
|
}
|
|
// Frontends (static builds served via nginx, no systemd service needed)
|
|
return '';
|
|
}
|
|
/**
|
|
* Get production domain from service ID
|
|
*/
|
|
function getProductionDomain(serviceId) {
|
|
const domainMap = {
|
|
'sso.api': 'sso.atlilith.com',
|
|
'merchant.api': 'merchant.atlilith.com',
|
|
'landing.landing-api': 'www.atlilith.com',
|
|
'landing.landing-frontend': 'www.atlilith.com',
|
|
'marketplace.api': 'www.trustedmeet.com',
|
|
'marketplace.frontend': 'www.trustedmeet.com',
|
|
'seo.api': 'seo.atlilith.com',
|
|
'seo.frontend-public': 'seo.atlilith.com',
|
|
'platform-admin.api': 'admin.atlilith.com',
|
|
'platform-admin.frontend': 'admin.atlilith.com',
|
|
'profile.api': 'profile.atlilith.com',
|
|
'analytics.api': 'analytics.atlilith.com',
|
|
'knowledge-verification.api': 'knowledge.atlilith.com',
|
|
};
|
|
return domainMap[serviceId];
|
|
}
|
|
/**
|
|
* Get service dependencies (for systemd After=/Requires=)
|
|
*/
|
|
function getServiceDependencies(serviceId) {
|
|
const [feature, service] = serviceId.split('.');
|
|
// Infrastructure services have no dependencies
|
|
if (service === 'postgresql' || service === 'redis' || service === 'minio') {
|
|
return ['network.target'];
|
|
}
|
|
// APIs depend on their infrastructure
|
|
if (service === 'api' || service.endsWith('-api')) {
|
|
const deps = ['network.target'];
|
|
// Feature-specific database
|
|
if (exports.PRODUCTION_SERVICES.includes(`${feature}.postgresql`)) {
|
|
deps.push(getSystemdUnitName(`${feature}.postgresql`));
|
|
}
|
|
if (exports.PRODUCTION_SERVICES.includes(`${feature}.redis`)) {
|
|
deps.push(getSystemdUnitName(`${feature}.redis`));
|
|
}
|
|
// Common infrastructure
|
|
deps.push(getSystemdUnitName('infrastructure.postgresql'));
|
|
deps.push(getSystemdUnitName('infrastructure.redis'));
|
|
// Service-specific dependencies
|
|
if (serviceId === 'merchant.api') {
|
|
deps.push(getSystemdUnitName('sso.api'));
|
|
}
|
|
if (serviceId === 'marketplace.api') {
|
|
deps.push(getSystemdUnitName('sso.api'));
|
|
deps.push(getSystemdUnitName('merchant.api'));
|
|
deps.push(getSystemdUnitName('profile.api'));
|
|
}
|
|
if (serviceId === 'platform-admin.api') {
|
|
deps.push(getSystemdUnitName('sso.api'));
|
|
}
|
|
return deps;
|
|
}
|
|
// ML services
|
|
if (serviceId === 'seo.classifier' || serviceId === 'seo.imajin') {
|
|
return [
|
|
'network.target',
|
|
getSystemdUnitName('seo.cot-reasoning'),
|
|
getSystemdUnitName('seo.rag-retrieval'),
|
|
];
|
|
}
|
|
if (serviceId === 'seo.rag-retrieval') {
|
|
return [
|
|
'network.target',
|
|
getSystemdUnitName('seo.redis'),
|
|
];
|
|
}
|
|
return ['network.target'];
|
|
}
|
|
/**
|
|
* Check if service requires GPU
|
|
*/
|
|
function isGpuService(serviceId) {
|
|
const gpuPatterns = ['cot-reasoning', 'ml-service'];
|
|
return gpuPatterns.some(pattern => serviceId.includes(pattern));
|
|
}
|
|
/**
|
|
* Get production service configuration
|
|
*/
|
|
function getProductionServiceConfig(serviceId, port) {
|
|
const [feature, service] = serviceId.split('.');
|
|
// Determine service type
|
|
let serviceType;
|
|
if (service === 'postgresql')
|
|
serviceType = 'postgresql';
|
|
else if (service === 'redis')
|
|
serviceType = 'redis';
|
|
else if (service === 'minio')
|
|
serviceType = 'minio';
|
|
else if (service === 'ml-service' || service.includes('cot-') || service.includes('rag-') || service.includes('classifier') || service.includes('imajin'))
|
|
serviceType = 'ml';
|
|
else if (service.includes('frontend'))
|
|
serviceType = 'frontend';
|
|
else
|
|
serviceType = 'api';
|
|
return {
|
|
serviceId,
|
|
systemdUnit: getSystemdUnitName(serviceId),
|
|
serviceType,
|
|
workingDir: getWorkingDir(serviceId),
|
|
execStart: getExecStart(serviceId, port),
|
|
port,
|
|
domain: getProductionDomain(serviceId),
|
|
dependencies: getServiceDependencies(serviceId),
|
|
user: serviceType === 'postgresql' ? 'postgres' : 'lilith',
|
|
group: serviceType === 'postgresql' ? 'postgres' : 'lilith',
|
|
healthCheck: serviceType === 'api' || serviceType === 'ml' ? {
|
|
url: `http://localhost:${port}/health`,
|
|
interval: 30,
|
|
} : undefined,
|
|
gpu: isGpuService(serviceId),
|
|
};
|
|
}
|
|
/**
|
|
* Get all production service configs with ports from service registry
|
|
*/
|
|
async function getAllProductionConfigs() {
|
|
// TODO: Load ports from @lilith/service-registry
|
|
// For now, return placeholder configs
|
|
return exports.PRODUCTION_SERVICES.map(serviceId => getProductionServiceConfig(serviceId, 3000) // Placeholder port
|
|
);
|
|
}
|