155 lines
3.8 KiB
JavaScript
Raw Normal View History

// exe-engine/src/controller/scheduler-v2.js
// EXE-Engine · 调度器 v2
// 优先队列 + 依赖图的增强调度
// PRJ-EXE-001 · Phase 1 · ZY-EXE-P1-005
// 版权:国作登字-2026-A-00037559
'use strict';
const { randomUUID } = require('crypto');
// 优先级数值映射数值越小优先级越高high=0 最先出队)
const PRIORITY_MAP = { high: 0, normal: 1, low: 2 };
/**
* 调度器 v2
*
* 本体论锚定调度器 = 笔的时间管理器
* 哪些字先写哪些字后写哪些字要等前面的字写完才能写
* 调度器用优先队列和依赖图来决定
*/
class SchedulerV2 {
/**
* @param {object} deps
* @param {AgentController} deps.agentController Agent 调度器
* @param {number} [deps.maxConcurrency=3] 最大并发数
*/
constructor(deps = {}) {
this._agentController = deps.agentController || null;
this._maxConcurrency = deps.maxConcurrency || 3;
// 待处理队列
this._queue = [];
// 已完成任务 { taskId: result }
this._completed = new Map();
// 失败任务 { taskId: error }
this._failed = new Map();
// 正在执行的任务
this._running = new Set();
}
/**
* 入队任务
* @param {object} task
* @param {string} [task.taskId] 任务 ID自动生成
* @param {string} task.agentId Agent ID
* @param {string} [task.priority='normal'] 优先级
* @param {string[]} [task.dependsOn=[]] 依赖任务 ID 列表
* @param {object} task.payload 任务载荷
* @returns {string} taskId
*/
enqueue(task) {
const taskId = task.taskId || `task-${randomUUID().slice(0, 8)}`;
const entry = {
taskId,
agentId: task.agentId,
priority: task.priority || 'normal',
dependsOn: task.dependsOn || [],
payload: task.payload || {},
status: 'pending',
enqueuedAt: new Date().toISOString()
};
this._queue.push(entry);
// 按优先级排序(同优先级保持 FIFO
this._queue.sort((a, b) => {
const pa = PRIORITY_MAP[a.priority] ?? 1;
const pb = PRIORITY_MAP[b.priority] ?? 1;
return pa - pb;
});
return taskId;
}
/**
* 出队返回优先级最高且依赖已满足的任务
* @returns {object|null}
*/
dequeue() {
for (let i = 0; i < this._queue.length; i++) {
const task = this._queue[i];
if (this._areDependenciesMet(task)) {
this._queue.splice(i, 1);
task.status = 'running';
this._running.add(task.taskId);
return task;
}
}
return null;
}
/**
* 标记任务完成
* @param {string} taskId
* @param {*} result 执行结果
*/
complete(taskId, result) {
this._completed.set(taskId, {
result,
completedAt: new Date().toISOString()
});
this._running.delete(taskId);
}
/**
* 标记任务失败
* @param {string} taskId
* @param {string} error 错误信息
*/
fail(taskId, error) {
this._failed.set(taskId, {
error,
failedAt: new Date().toISOString()
});
this._running.delete(taskId);
}
/**
* 获取当前队列状态
* @returns {object[]}
*/
getQueue() {
return [...this._queue];
}
/**
* 获取调度器指标
* @returns {object}
*/
getStatus() {
return {
pending: this._queue.length,
running: this._running.size,
completed: this._completed.size,
failed: this._failed.size,
maxConcurrency: this._maxConcurrency
};
}
// ── 内部方法 ──
/**
* 检查任务依赖是否全部满足
* @param {object} task
* @returns {boolean}
*/
_areDependenciesMet(task) {
if (!task.dependsOn || task.dependsOn.length === 0) return true;
return task.dependsOn.every(depId => this._completed.has(depId));
}
}
module.exports = SchedulerV2;