claude-flow-novice
Version:
Claude Flow Novice - Advanced orchestration platform for multi-agent AI workflows with CFN Loop architecture Includes Local RuVector Accelerator and all CFN skills for complete functionality.
227 lines (226 loc) • 7.95 kB
JavaScript
/**
* Redis-based File Processing Coordinator
* Coordinates distributed file processing with Redis pub/sub and state management
*/ import EventEmitter from 'events';
import crypto from 'crypto';
let RedisCoordinator = class RedisCoordinator extends EventEmitter {
options;
redis = null;
subscriber = null;
publisher = null;
heartbeatTimer = null;
nodeId;
isInitialized = false;
state = {
activeNodes: new Map(),
taskQueue: [],
processingTasks: new Map(),
completedTasks: new Map(),
metrics: {
totalProcessed: 0,
totalErrors: 0,
throughput: 0,
lastUpdate: Date.now()
}
};
performanceMetrics = {
startTime: null,
lastHeartbeat: null,
messagesProcessed: 0,
bytesProcessed: 0,
errorCount: 0
};
constructor(options = {}){
super();
// Merge default and provided options with type safety
this.options = {
redis: {
host: options.redis?.host || process.env.REDIS_HOST || 'localhost',
port: options.redis?.port || parseInt(process.env.REDIS_PORT || '6379'),
password: options.redis?.password || process.env.REDIS_PASSWORD || null,
db: options.redis?.db || parseInt(process.env.REDIS_DB || '0'),
...options.redis
},
swarmId: options.swarmId || 'file-processing-optimization',
heartbeatInterval: options.heartbeatInterval || 5000,
maxRetries: options.maxRetries || 3,
...options
};
this.nodeId = this.generateNodeId();
}
// Rest of the implementation remains the same, with additional type annotations...
/**
* Handle incoming Redis messages
*/ handleMessage(channel, data) {
this.performanceMetrics.messagesProcessed++;
const channelParts = channel.split(':');
const messageType = channelParts[channelParts.length - 1];
switch(messageType){
case 'tasks':
this.handleTaskMessage(data);
break;
case 'status':
this.handleStatusMessage(data);
break;
case 'metrics':
this.handleMetricsMessage(data);
break;
case 'heartbeat':
this.handleHeartbeatMessage(data);
break;
case 'coordination':
this.handleCoordinationMessage(data);
break;
default:
console.warn(`Unknown message type: ${messageType}`);
}
this.emit('message', {
type: messageType,
channel,
data
});
}
// Implement type-safe methods for task, status, metrics, heartbeat handling
handleTaskMessage(data) {
const { action, task, nodeId } = data;
switch(action){
case 'assign':
if (task.nodeId === this.nodeId) {
this.state.processingTasks.set(task.id, task);
this.emit('task-assigned', task);
}
break;
}
}
handleStatusMessage(data) {
const { nodeId, status, metrics } = data;
if (status === 'online') {
this.state.activeNodes.set(nodeId, {
nodeId,
status,
metrics,
lastSeen: Date.now()
});
} else if (status === 'offline') {
this.state.activeNodes.delete(nodeId);
}
this.emit('node-status', {
nodeId,
status,
metrics
});
}
/**
* Handle incoming metrics messages from other nodes
*/ handleMetricsMessage(data) {
const { nodeId, metrics } = data;
// Update node performance metrics
const nodeMetrics = this.state.activeNodes.get(nodeId);
if (nodeMetrics) {
nodeMetrics.metrics = {
...nodeMetrics.metrics,
...metrics
};
}
// Update aggregate metrics
this.state.metrics.lastUpdate = Date.now();
// Log performance insights
console.log(`Metrics received from node ${nodeId}:`, metrics);
// Optional: Trigger performance optimization if needed
this.emit('node-metrics', {
nodeId,
metrics
});
}
/**
* Handle incoming heartbeat messages from other nodes
*/ handleHeartbeatMessage(data) {
const { nodeId, timestamp } = data;
// Update last seen time for the node
const nodeState = this.state.activeNodes.get(nodeId);
if (nodeState) {
nodeState.lastSeen = Math.max(nodeState.lastSeen, timestamp);
}
// Update performance metrics
this.performanceMetrics.lastHeartbeat = timestamp;
// Log heartbeat
console.log(`Heartbeat received from node ${nodeId} at ${new Date(timestamp)}`);
this.emit('node-heartbeat', {
nodeId,
timestamp
});
}
/**
* Handle coordination messages for cluster management
*/ handleCoordinationMessage(data) {
const { action, payload } = data;
switch(action){
case 'elect-leader':
this.handleLeaderElection(payload);
break;
case 'rebalance':
this.handleWorkRebalance(payload);
break;
case 'shutdown':
this.handleShutdownRequest(payload);
break;
default:
console.warn(`Unknown coordination action: ${action}`);
}
this.emit('coordination-message', {
action,
payload
});
}
handleLeaderElection(payload) {
console.log('Processing leader election:', payload);
// Basic leader election logic
const candidateId = payload['candidateId'];
const candidateScore = payload['score'];
if (candidateId === this.nodeId) {
console.log('This node is a candidate for leadership');
// Add logic to determine leadership based on metrics/score
}
}
handleWorkRebalance(payload) {
console.log('Rebalancing work distribution:', payload);
const taskDistribution = payload['taskDistribution'];
// Redistribute tasks based on payload
Object.entries(taskDistribution).forEach(([nodeId, taskCount])=>{
if (nodeId === this.nodeId) {
console.log(`Adjusting task load to ${taskCount}`);
// Add task redistribution logic
}
});
}
handleShutdownRequest(payload) {
console.log('Processing shutdown request:', payload);
const reason = payload['reason'];
const gracePeriod = payload['gracePeriod'] || 5000; // Default 5s
console.log(`Graceful shutdown in progress. Reason: ${reason}`);
// Initiate graceful shutdown sequence
setTimeout(()=>{
console.log('Shutdown complete');
this.emit('shutdown-complete');
}, gracePeriod);
}
// Additional helper methods with explicit type annotations
async publishTask(action, task) {
if (!this.isInitialized) {
throw new Error('Redis coordinator not initialized');
}
const message = {
action,
task,
nodeId: this.nodeId,
timestamp: Date.now()
};
await this.publisher?.publish(`${this.options.swarmId}:tasks`, JSON.stringify(message));
}
// Other methods remain the same, with similar type annotations added
generateNodeId() {
return `node-${crypto.randomBytes(8).toString('hex')}`;
}
};
export default RedisCoordinator;
//# sourceMappingURL=redis-coordinator.js.map