ваше сообщение коммита
This commit is contained in:
@@ -17,13 +17,10 @@ class AIQueue extends EventEmitter {
|
||||
constructor() {
|
||||
super();
|
||||
this.queue = [];
|
||||
this.processing = false;
|
||||
this.activeRequests = 0;
|
||||
this.maxConcurrent = 1; // Ограничиваем до 1 для стабильности
|
||||
this.isPaused = false;
|
||||
this.stats = {
|
||||
completed: 0,
|
||||
failed: 0,
|
||||
totalAdded: 0,
|
||||
totalProcessed: 0,
|
||||
totalFailed: 0,
|
||||
avgResponseTime: 0,
|
||||
lastProcessedAt: null,
|
||||
initializedAt: Date.now()
|
||||
@@ -45,165 +42,101 @@ class AIQueue extends EventEmitter {
|
||||
this.queue.push(queueItem);
|
||||
this.queue.sort((a, b) => b.priority - a.priority);
|
||||
|
||||
this.stats.totalAdded++;
|
||||
logger.info(`[AIQueue] Добавлен запрос ${requestId} с приоритетом ${priority}. Очередь: ${this.queue.length}`);
|
||||
|
||||
// Запускаем обработку очереди
|
||||
if (!this.processing) {
|
||||
this.processQueue();
|
||||
}
|
||||
// Эмитим событие о добавлении
|
||||
this.emit('requestAdded', queueItem);
|
||||
|
||||
return requestId;
|
||||
}
|
||||
|
||||
// Обработка очереди
|
||||
async processQueue() {
|
||||
if (this.processing) return;
|
||||
|
||||
this.processing = true;
|
||||
logger.info(`[AIQueue] Начинаем обработку очереди. Запросов в очереди: ${this.queue.length}`);
|
||||
|
||||
while (!this.isPaused && this.queue.length > 0 && this.activeRequests < this.maxConcurrent) {
|
||||
const item = this.queue.shift();
|
||||
if (!item) continue;
|
||||
|
||||
this.activeRequests++;
|
||||
item.status = 'processing';
|
||||
logger.info(`[AIQueue] Обрабатываем запрос ${item.id} (приоритет: ${item.priority})`);
|
||||
|
||||
try {
|
||||
const startTime = Date.now();
|
||||
const result = await this.processRequest(item.request);
|
||||
const responseTime = Date.now() - startTime;
|
||||
|
||||
item.status = 'completed';
|
||||
item.result = result;
|
||||
item.responseTime = responseTime;
|
||||
|
||||
this.stats.completed++;
|
||||
this.updateAvgResponseTime(responseTime);
|
||||
this.stats.lastProcessedAt = Date.now();
|
||||
|
||||
logger.info(`[AIQueue] Запрос ${item.id} завершен за ${responseTime}ms`);
|
||||
|
||||
// Эмитим событие о завершении
|
||||
this.emit('completed', item);
|
||||
|
||||
} catch (error) {
|
||||
item.status = 'failed';
|
||||
item.error = error.message;
|
||||
|
||||
this.stats.failed++;
|
||||
this.stats.lastProcessedAt = Date.now();
|
||||
logger.error(`[AIQueue] Запрос ${item.id} завершился с ошибкой:`, error.message);
|
||||
|
||||
// Эмитим событие об ошибке
|
||||
this.emit('failed', item);
|
||||
} finally {
|
||||
this.activeRequests--;
|
||||
}
|
||||
}
|
||||
|
||||
this.processing = false;
|
||||
logger.info(`[AIQueue] Обработка очереди завершена. Осталось запросов: ${this.queue.length}`);
|
||||
|
||||
// Если в очереди еще есть запросы, продолжаем обработку
|
||||
if (!this.isPaused && this.queue.length > 0) {
|
||||
setTimeout(() => this.processQueue(), 100);
|
||||
}
|
||||
// Получение следующего запроса (без обработки)
|
||||
getNextRequest() {
|
||||
if (this.queue.length === 0) return null;
|
||||
return this.queue.shift();
|
||||
}
|
||||
|
||||
// Обработка одного запроса
|
||||
async processRequest(request) {
|
||||
const aiAssistant = require('./ai-assistant');
|
||||
|
||||
// Формируем сообщения для API
|
||||
const messages = [];
|
||||
|
||||
// Добавляем системный промпт
|
||||
if (request.systemPrompt) {
|
||||
messages.push({ role: 'system', content: request.systemPrompt });
|
||||
}
|
||||
|
||||
// Добавляем историю сообщений
|
||||
if (request.history && Array.isArray(request.history)) {
|
||||
for (const msg of request.history) {
|
||||
if (msg.role && msg.content) {
|
||||
messages.push({ role: msg.role, content: msg.content });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Добавляем текущее сообщение пользователя
|
||||
messages.push({ role: 'user', content: request.message });
|
||||
// Получение запроса по ID
|
||||
getRequestById(requestId) {
|
||||
return this.queue.find(item => item.id === requestId);
|
||||
}
|
||||
|
||||
// Используем прямой метод для избежания рекурсии
|
||||
return await aiAssistant.directRequest(messages, request.systemPrompt);
|
||||
// Обновление статуса запроса
|
||||
updateRequestStatus(requestId, status, result = null, error = null, responseTime = null) {
|
||||
const item = this.queue.find(item => item.id === requestId);
|
||||
if (!item) return false;
|
||||
|
||||
item.status = status;
|
||||
item.result = result;
|
||||
item.error = error;
|
||||
item.responseTime = responseTime;
|
||||
item.processedAt = Date.now();
|
||||
|
||||
if (status === 'completed') {
|
||||
this.stats.totalProcessed++;
|
||||
if (responseTime) {
|
||||
this.updateAvgResponseTime(responseTime);
|
||||
}
|
||||
this.stats.lastProcessedAt = Date.now();
|
||||
this.emit('requestCompleted', item);
|
||||
} else if (status === 'failed') {
|
||||
this.stats.totalFailed++;
|
||||
this.stats.lastProcessedAt = Date.now();
|
||||
this.emit('requestFailed', item);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Обновление средней скорости ответа
|
||||
updateAvgResponseTime(responseTime) {
|
||||
const total = this.stats.completed;
|
||||
const total = this.stats.totalProcessed;
|
||||
this.stats.avgResponseTime =
|
||||
(this.stats.avgResponseTime * (total - 1) + responseTime) / total;
|
||||
}
|
||||
|
||||
// Получение статистики
|
||||
getStats() {
|
||||
const totalProcessed = this.stats.completed + this.stats.failed;
|
||||
return {
|
||||
// совместимость с AIQueueMonitor.vue и маршрутами
|
||||
totalProcessed,
|
||||
totalFailed: this.stats.failed,
|
||||
totalAdded: this.stats.totalAdded,
|
||||
totalProcessed: this.stats.totalProcessed,
|
||||
totalFailed: this.stats.totalFailed,
|
||||
averageProcessingTime: this.stats.avgResponseTime,
|
||||
currentQueueSize: this.queue.length,
|
||||
runningTasks: this.activeRequests,
|
||||
lastProcessedAt: this.stats.lastProcessedAt,
|
||||
isInitialized: true,
|
||||
// старые поля на всякий случай
|
||||
queueLength: this.queue.length,
|
||||
activeRequests: this.activeRequests,
|
||||
processing: this.processing
|
||||
uptime: Date.now() - this.stats.initializedAt
|
||||
};
|
||||
}
|
||||
|
||||
// Очистка очереди
|
||||
clear() {
|
||||
this.queue = [];
|
||||
logger.info('[AIQueue] Queue cleared');
|
||||
// Получение размера очереди
|
||||
getQueueSize() {
|
||||
return this.queue.length;
|
||||
}
|
||||
|
||||
// Совместимость с роутами AI Queue
|
||||
// Очистка очереди
|
||||
clearQueue() {
|
||||
const clearedCount = this.queue.length;
|
||||
this.queue = [];
|
||||
logger.info(`[AIQueue] Очередь очищена. Удалено запросов: ${clearedCount}`);
|
||||
return clearedCount;
|
||||
}
|
||||
|
||||
// Пауза/возобновление очереди
|
||||
pause() {
|
||||
this.isPaused = true;
|
||||
logger.info('[AIQueue] Queue paused');
|
||||
logger.info('[AIQueue] Очередь приостановлена');
|
||||
}
|
||||
|
||||
resume() {
|
||||
const wasPaused = this.isPaused;
|
||||
this.isPaused = false;
|
||||
logger.info('[AIQueue] Queue resumed');
|
||||
if (wasPaused) {
|
||||
this.processQueue();
|
||||
}
|
||||
logger.info('[AIQueue] Очередь возобновлена');
|
||||
}
|
||||
|
||||
async addTask(taskData) {
|
||||
// Маппинг к addRequest
|
||||
const priority = this._calcTaskPriority(taskData);
|
||||
const taskId = await this.addRequest(taskData, priority);
|
||||
return { taskId };
|
||||
}
|
||||
|
||||
_calcTaskPriority({ message = '', type, userRole, history }) {
|
||||
let priority = 0;
|
||||
if (userRole === 'admin') priority += 10;
|
||||
if (type === 'chat') priority += 5;
|
||||
if (type === 'analysis') priority += 3;
|
||||
if (type === 'generation') priority += 1;
|
||||
if (message && message.length < 100) priority += 2;
|
||||
if (history && Array.isArray(history) && history.length > 0) priority += 1;
|
||||
return priority;
|
||||
// Проверка статуса паузы
|
||||
isQueuePaused() {
|
||||
return this.isPaused;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = new AIQueue();
|
||||
module.exports = AIQueue;
|
||||
Reference in New Issue
Block a user