 85bf1341f3
			
		
	
	85bf1341f3
	
	
	
		
			
			Frontend Enhancements: - Complete React TypeScript frontend with modern UI components - Distributed workflows management interface with real-time updates - Socket.IO integration for live agent status monitoring - Agent management dashboard with cluster visualization - Project management interface with metrics and task tracking - Responsive design with proper error handling and loading states Backend Infrastructure: - Distributed coordinator for multi-agent workflow orchestration - Cluster management API with comprehensive agent operations - Enhanced database models for agents and projects - Project service for filesystem-based project discovery - Performance monitoring and metrics collection - Comprehensive API documentation and error handling Documentation: - Complete distributed development guide (README_DISTRIBUTED.md) - Comprehensive development report with architecture insights - System configuration templates and deployment guides The platform now provides a complete web interface for managing the distributed AI cluster with real-time monitoring, workflow orchestration, and agent coordination capabilities. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
		
			
				
	
	
		
			105 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			105 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| class Queue {
 | |
|     constructor() {
 | |
|         this.order = [];
 | |
|         this.scheduled = new Set();
 | |
|     }
 | |
|     add(process) {
 | |
|         if (!this.scheduled.has(process)) {
 | |
|             this.scheduled.add(process);
 | |
|             this.order.push(process);
 | |
|             return true;
 | |
|         }
 | |
|     }
 | |
|     remove(process) {
 | |
|         const index = this.order.indexOf(process);
 | |
|         if (index !== -1) {
 | |
|             this.order.splice(index, 1);
 | |
|             this.scheduled.delete(process);
 | |
|         }
 | |
|     }
 | |
|     clear() {
 | |
|         this.order.length = 0;
 | |
|         this.scheduled.clear();
 | |
|     }
 | |
| }
 | |
| function createRenderStep(runNextFrame) {
 | |
|     /**
 | |
|      * We create and reuse two queues, one to queue jobs for the current frame
 | |
|      * and one for the next. We reuse to avoid triggering GC after x frames.
 | |
|      */
 | |
|     let thisFrame = new Queue();
 | |
|     let nextFrame = new Queue();
 | |
|     let numToRun = 0;
 | |
|     /**
 | |
|      * Track whether we're currently processing jobs in this step. This way
 | |
|      * we can decide whether to schedule new jobs for this frame or next.
 | |
|      */
 | |
|     let isProcessing = false;
 | |
|     let flushNextFrame = false;
 | |
|     /**
 | |
|      * A set of processes which were marked keepAlive when scheduled.
 | |
|      */
 | |
|     const toKeepAlive = new WeakSet();
 | |
|     const step = {
 | |
|         /**
 | |
|          * Schedule a process to run on the next frame.
 | |
|          */
 | |
|         schedule: (callback, keepAlive = false, immediate = false) => {
 | |
|             const addToCurrentFrame = immediate && isProcessing;
 | |
|             const queue = addToCurrentFrame ? thisFrame : nextFrame;
 | |
|             if (keepAlive)
 | |
|                 toKeepAlive.add(callback);
 | |
|             if (queue.add(callback) && addToCurrentFrame && isProcessing) {
 | |
|                 // If we're adding it to the currently running queue, update its measured size
 | |
|                 numToRun = thisFrame.order.length;
 | |
|             }
 | |
|             return callback;
 | |
|         },
 | |
|         /**
 | |
|          * Cancel the provided callback from running on the next frame.
 | |
|          */
 | |
|         cancel: (callback) => {
 | |
|             nextFrame.remove(callback);
 | |
|             toKeepAlive.delete(callback);
 | |
|         },
 | |
|         /**
 | |
|          * Execute all schedule callbacks.
 | |
|          */
 | |
|         process: (frameData) => {
 | |
|             /**
 | |
|              * If we're already processing we've probably been triggered by a flushSync
 | |
|              * inside an existing process. Instead of executing, mark flushNextFrame
 | |
|              * as true and ensure we flush the following frame at the end of this one.
 | |
|              */
 | |
|             if (isProcessing) {
 | |
|                 flushNextFrame = true;
 | |
|                 return;
 | |
|             }
 | |
|             isProcessing = true;
 | |
|             [thisFrame, nextFrame] = [nextFrame, thisFrame];
 | |
|             // Clear the next frame queue
 | |
|             nextFrame.clear();
 | |
|             // Execute this frame
 | |
|             numToRun = thisFrame.order.length;
 | |
|             if (numToRun) {
 | |
|                 for (let i = 0; i < numToRun; i++) {
 | |
|                     const callback = thisFrame.order[i];
 | |
|                     callback(frameData);
 | |
|                     if (toKeepAlive.has(callback)) {
 | |
|                         step.schedule(callback);
 | |
|                         runNextFrame();
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
|             isProcessing = false;
 | |
|             if (flushNextFrame) {
 | |
|                 flushNextFrame = false;
 | |
|                 step.process(frameData);
 | |
|             }
 | |
|         },
 | |
|     };
 | |
|     return step;
 | |
| }
 | |
| 
 | |
| export { createRenderStep };
 |