Ratan1729/code-execution
1
1// ─── Execution Queue ─────────────────────────2// Simple in-memory Promise-based queue3// Optimized for 1GB instance — no Redis needed4 5const config = require("../config");6const logger = require("../utils/logger.util");7 8class QueueService {9 constructor() {10 this.maxConcurrent = config.MAX_CONCURRENT;11 this.running = 0;12 this.waiting = [];13 this.totalProcessed = 0;14 this.totalFailed = 0;15 }16 17 /**18 * Enqueue a task for execution.19 * Returns a Promise that resolves with the task result.20 * If max concurrency is reached, the task waits in queue.21 */22 enqueue(task) {23 return new Promise((resolve, reject) => {24 this.waiting.push({ task, resolve, reject, enqueuedAt: Date.now() });25 logger.debug(26 `📋 Queue: ${this.running} running, ${this.waiting.length} waiting`,27 );28 this._process();29 });30 }31 32 /**33 * Process next task if capacity is available34 */35 async _process() {36 if (this.running >= this.maxConcurrent || this.waiting.length === 0) {37 return;38 }39 40 const { task, resolve, reject, enqueuedAt } = this.waiting.shift();41 const waitTime = Date.now() - enqueuedAt;42 this.running++;43 44 if (waitTime > 100) {45 logger.info(`⏳ Task waited ${waitTime}ms in queue`);46 }47 48 try {49 const result = await task();50 this.totalProcessed++;51 resolve(result);52 } catch (err) {53 this.totalFailed++;54 reject(err);55 } finally {56 this.running--;57 // Schedule next task processing58 setImmediate(() => this._process());59 }60 }61 62 /**63 * Get current queue status64 */65 getStatus() {66 return {67 running: this.running,68 waiting: this.waiting.length,69 maxConcurrent: this.maxConcurrent,70 totalProcessed: this.totalProcessed,71 totalFailed: this.totalFailed,72 };73 }74}75 76module.exports = new QueueService();77 