alles andere
This commit is contained in:
308
packages/orchestrator/src/orchestrator.ts
Normal file
308
packages/orchestrator/src/orchestrator.ts
Normal file
@@ -0,0 +1,308 @@
|
||||
import { PrismaClient } from '@prisma/client';
|
||||
import { WorkflowExecutor } from './workflows/workflow-executor';
|
||||
import { DecisionEngine } from './decision-engine/rules';
|
||||
import { AlertSystem } from './monitoring/alerts';
|
||||
import { MetricsCollector } from './monitoring/metrics';
|
||||
import { log } from './monitoring/logger';
|
||||
import { config } from './utils/config';
|
||||
import { businessInputSchema, validateBusinessIdea } from './utils/validators';
|
||||
|
||||
export class MetaOrchestrator {
|
||||
private db: PrismaClient;
|
||||
private workflowExecutor: WorkflowExecutor;
|
||||
private decisionEngine: DecisionEngine;
|
||||
private alerts: AlertSystem;
|
||||
private metrics: MetricsCollector;
|
||||
private isRunning: boolean = false;
|
||||
|
||||
constructor() {
|
||||
this.db = new PrismaClient();
|
||||
this.alerts = new AlertSystem(this.db);
|
||||
this.metrics = new MetricsCollector(this.db);
|
||||
this.workflowExecutor = new WorkflowExecutor(this.db, this.alerts);
|
||||
this.decisionEngine = new DecisionEngine(this.db, this.alerts, this.metrics);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the orchestrator
|
||||
*/
|
||||
async initialize(): Promise<void> {
|
||||
try {
|
||||
log.info('Initializing MetaOrchestrator...');
|
||||
|
||||
// Test database connection
|
||||
await this.db.$connect();
|
||||
log.info('Database connected');
|
||||
|
||||
// Start background processes
|
||||
this.startBackgroundProcesses();
|
||||
|
||||
this.isRunning = true;
|
||||
log.info('MetaOrchestrator initialized successfully');
|
||||
} catch (error) {
|
||||
log.error('Failed to initialize MetaOrchestrator', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new business and start its lifecycle
|
||||
*/
|
||||
async createBusiness(input: {
|
||||
name: string;
|
||||
idea: string;
|
||||
targetAudience?: string;
|
||||
budget?: number;
|
||||
}): Promise<{ id: string; name: string }> {
|
||||
try {
|
||||
// Validate input
|
||||
const validated = businessInputSchema.parse(input);
|
||||
|
||||
// Validate business idea quality
|
||||
const ideaValidation = validateBusinessIdea(validated.idea);
|
||||
if (!ideaValidation.valid) {
|
||||
throw new Error(`Invalid business idea: ${ideaValidation.issues.join(', ')}`);
|
||||
}
|
||||
|
||||
// Create business record
|
||||
const business = await this.db.business.create({
|
||||
data: {
|
||||
name: validated.name,
|
||||
idea: validated.idea,
|
||||
targetAudience: validated.targetAudience,
|
||||
budget: validated.budget,
|
||||
status: 'VALIDATING',
|
||||
},
|
||||
});
|
||||
|
||||
log.business.created(business.id, business.name, business.idea);
|
||||
|
||||
// Start lifecycle in background (non-blocking)
|
||||
this.executeBusinessLifecycle(business.id).catch((error) => {
|
||||
log.error('Business lifecycle execution failed', error, { businessId: business.id });
|
||||
});
|
||||
|
||||
return {
|
||||
id: business.id,
|
||||
name: business.name,
|
||||
};
|
||||
} catch (error) {
|
||||
log.error('Failed to create business', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the complete business lifecycle
|
||||
*/
|
||||
async executeBusinessLifecycle(businessId: string): Promise<void> {
|
||||
try {
|
||||
log.info('Starting business lifecycle', { businessId });
|
||||
|
||||
// PHASE 1: Market Validation (Sequential)
|
||||
log.info('Phase 1: Market Validation', { businessId });
|
||||
const validationResult = await this.workflowExecutor.run(businessId, 'MARKET_VALIDATION');
|
||||
|
||||
if (!validationResult.success || !validationResult.data?.viable) {
|
||||
log.info('Business validation failed - shutting down', { businessId });
|
||||
await this.shutdown(businessId, 'Market validation failed: not viable');
|
||||
return;
|
||||
}
|
||||
|
||||
// PHASE 2: MVP Development (Sequential)
|
||||
log.info('Phase 2: MVP Development', { businessId });
|
||||
const mvpResult = await this.workflowExecutor.run(businessId, 'MVP_DEVELOPMENT');
|
||||
|
||||
if (!mvpResult.success) {
|
||||
log.error('MVP development failed', undefined, { businessId });
|
||||
await this.shutdown(businessId, 'MVP development failed');
|
||||
return;
|
||||
}
|
||||
|
||||
// PHASE 3: Marketing Setup (Parallel)
|
||||
log.info('Phase 3: Marketing Setup (parallel workflows)', { businessId });
|
||||
const marketingResults = await this.workflowExecutor.runParallel(businessId, [
|
||||
'LANDING_PAGE_SEO',
|
||||
'PAID_ADS',
|
||||
'CONTENT_MARKETING',
|
||||
'EMAIL_AUTOMATION',
|
||||
'ANALYTICS_SETUP',
|
||||
]);
|
||||
|
||||
// Check if any critical marketing workflows failed
|
||||
const failures = marketingResults.filter((r) => !r.success);
|
||||
if (failures.length > 0) {
|
||||
log.warn('Some marketing workflows failed', {
|
||||
businessId,
|
||||
failureCount: failures.length,
|
||||
});
|
||||
// Continue anyway - marketing workflows are not critical
|
||||
}
|
||||
|
||||
// Update business status
|
||||
await this.db.business.update({
|
||||
where: { id: businessId },
|
||||
data: { status: 'OPTIMIZING' },
|
||||
});
|
||||
|
||||
// PHASE 4: Continuous Optimization Loop (Forever)
|
||||
log.info('Phase 4: Starting continuous optimization', { businessId });
|
||||
|
||||
// This runs forever until business is shutdown/paused
|
||||
await this.workflowExecutor.runForever(
|
||||
businessId,
|
||||
'OPTIMIZATION_LOOP',
|
||||
config.app.optimizationIntervalMinutes
|
||||
);
|
||||
|
||||
log.info('Business lifecycle completed', { businessId });
|
||||
} catch (error) {
|
||||
log.error('Business lifecycle error', error, { businessId });
|
||||
await this.alerts.systemError(
|
||||
`Business lifecycle failed for ${businessId}`,
|
||||
error instanceof Error ? error.stack : undefined
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Shutdown a business
|
||||
*/
|
||||
async shutdown(businessId: string, reason: string): Promise<void> {
|
||||
log.info('Shutting down business', { businessId, reason });
|
||||
|
||||
// Pause all campaigns
|
||||
await this.db.campaign.updateMany({
|
||||
where: { businessId },
|
||||
data: { active: false },
|
||||
});
|
||||
|
||||
// Update business status
|
||||
await this.db.business.update({
|
||||
where: { id: businessId },
|
||||
data: { status: 'SHUTDOWN' },
|
||||
});
|
||||
|
||||
// Send alert
|
||||
const business = await this.db.business.findUnique({
|
||||
where: { id: businessId },
|
||||
});
|
||||
|
||||
if (business) {
|
||||
await this.alerts.sendAlert({
|
||||
type: 'DECISION_EXECUTED',
|
||||
severity: 'WARNING',
|
||||
title: 'Business Shutdown',
|
||||
message: `Business "${business.name}" has been shut down.\n\nReason: ${reason}`,
|
||||
businessId,
|
||||
metadata: { reason },
|
||||
});
|
||||
}
|
||||
|
||||
log.info('Business shutdown complete', { businessId });
|
||||
}
|
||||
|
||||
/**
|
||||
* Start background processes (decision evaluation)
|
||||
*/
|
||||
private startBackgroundProcesses(): void {
|
||||
// Run decision evaluation periodically
|
||||
setInterval(async () => {
|
||||
try {
|
||||
await this.evaluateAllBusinessDecisions();
|
||||
} catch (error) {
|
||||
log.error('Decision evaluation error', error);
|
||||
}
|
||||
}, config.app.decisionEvaluationIntervalMinutes * 60 * 1000);
|
||||
|
||||
log.info('Background processes started', {
|
||||
decisionEvaluationInterval: config.app.decisionEvaluationIntervalMinutes,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluate decisions for all active businesses
|
||||
*/
|
||||
private async evaluateAllBusinessDecisions(): Promise<void> {
|
||||
const activeBusinesses = await this.db.business.findMany({
|
||||
where: {
|
||||
status: {
|
||||
in: ['RUNNING_ADS', 'OPTIMIZING', 'SCALING'],
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
log.info(`Evaluating decisions for ${activeBusinesses.length} businesses`);
|
||||
|
||||
for (const business of activeBusinesses) {
|
||||
try {
|
||||
await this.decisionEngine.evaluateBusinessDaily(business.id);
|
||||
} catch (error) {
|
||||
log.error('Failed to evaluate business decisions', error, {
|
||||
businessId: business.id,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get business status
|
||||
*/
|
||||
async getBusinessStatus(businessId: string) {
|
||||
const business = await this.db.business.findUnique({
|
||||
where: { id: businessId },
|
||||
include: {
|
||||
workflows: {
|
||||
orderBy: { createdAt: 'desc' },
|
||||
take: 10,
|
||||
},
|
||||
campaigns: true,
|
||||
decisions: {
|
||||
orderBy: { createdAt: 'desc' },
|
||||
take: 5,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
if (!business) {
|
||||
throw new Error('Business not found');
|
||||
}
|
||||
|
||||
const metrics = await this.metrics.getBusinessMetrics(businessId);
|
||||
const healthScore = await this.metrics.getHealthScore(businessId);
|
||||
|
||||
return {
|
||||
...business,
|
||||
metrics,
|
||||
healthScore,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* List all businesses
|
||||
*/
|
||||
async listBusinesses() {
|
||||
return await this.db.business.findMany({
|
||||
orderBy: { createdAt: 'desc' },
|
||||
include: {
|
||||
_count: {
|
||||
select: {
|
||||
workflows: true,
|
||||
campaigns: true,
|
||||
decisions: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Graceful shutdown
|
||||
*/
|
||||
async close(): Promise<void> {
|
||||
log.info('Shutting down MetaOrchestrator...');
|
||||
this.isRunning = false;
|
||||
await this.db.$disconnect();
|
||||
log.info('MetaOrchestrator shutdown complete');
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user