autosnippet
Version:
Extract code patterns into a knowledge base for AI coding assistants
134 lines (133 loc) • 6.68 kB
JavaScript
/**
* TierScheduler.js — 维度分层并行调度器
*
* 内部 Agent 和外部 Agent 共享此调度模型。
* 按维度间信息依赖关系分 3 层执行:
* - Tier 1: 基础数据层 (project-profile, 语言条件扫描) — 可并行
* - Tier 2: 规范+架构+模式 (code-standard, architecture, code-pattern) — 依赖 Tier 1
* - Tier 3: 流转+实践+总结 (event-and-data-flow, best-practice, agent-guidelines) — 依赖 Tier 2
*
* 每层内部可并行 (受 concurrency 限制),层间串行。
* 未在任何 Tier 中定义的维度会自动归入 Tier 1(并行执行)。
*
* 调用方:
* - orchestrator.js (内部 Agent) — fillDimensionsV3() 按 Tier 分层调度 AI pipeline
* - MissionBriefingBuilder.js (外部 Agent) — executionPlan 中的 Tier 层序展示
*
* @module TierScheduler
*/
import { buildTierPlan } from '#domain/dimension/index.js';
import Logger from '#infra/logging/Logger.js';
import { createLimit } from '#shared/concurrency.js';
const logger = Logger.getInstance();
// ──────────────────────────────────────────────────────────────────
// 分层定义 — 从统一注册表动态生成
// ──────────────────────────────────────────────────────────────────
/**
* 默认分层来自 DimensionRegistry.buildTierPlan(),
* 该函数根据每个维度的 tierHint 自动分配。
*/
const DEFAULT_TIERS = buildTierPlan();
// ──────────────────────────────────────────────────────────────────
// TierScheduler
// ──────────────────────────────────────────────────────────────────
export class TierScheduler {
#tiers;
/** @param [tiers] 自定义分层 (默认使用 DEFAULT_TIERS) */
constructor(tiers = DEFAULT_TIERS) {
this.#tiers = tiers;
}
/**
* 分层执行维度
*
* @param executeDimension async (dimId) => DimensionResult
* @param [options.concurrency=3] Tier 内最大并行数
* @param [options.onTierComplete] (tierIndex, tierResults) => void
* @param [options.shouldAbort] () => boolean 外部中止信号
* @param [options.activeDimIds] 实际要执行的维度 ID 列表(过滤不在列表中的维度)
* @param [options.tierHints] dimId → 1-based tier index(Enhancement Pack 维度声明的首选 Tier)
* @returns dimId → result
*/
async execute(executeDimension, options = {}) {
const { concurrency = 3, onTierComplete, shouldAbort, activeDimIds, tierHints } = options;
const results = new Map();
// 如果提供了 activeDimIds,根据它构建实际要执行的 tiers
// 未在任何 tier 中定义的维度: 优先使用 tierHints 归入指定 Tier,否则默认归入 Tier 1
let effectiveTiers = this.#tiers;
if (activeDimIds) {
const activeSet = new Set(activeDimIds);
const scheduled = new Set(this.#tiers.flat());
const unscheduled = activeDimIds.filter((id) => !scheduled.has(id));
effectiveTiers = this.#tiers.map((tier) => tier.filter((id) => activeSet.has(id)));
if (unscheduled.length > 0) {
// 按 tierHint 分配到对应 Tier,无 hint 的默认归入 Tier 1
const byTier = new Map(); // 0-based tier index → dimId[]
for (const id of unscheduled) {
const hint = tierHints?.[id];
const tierIdx = typeof hint === 'number' && hint >= 1 && hint <= effectiveTiers.length ? hint - 1 : 0;
if (!byTier.has(tierIdx)) {
byTier.set(tierIdx, []);
}
byTier.get(tierIdx).push(id);
}
for (const [tierIdx, ids] of byTier) {
effectiveTiers[tierIdx] = [...effectiveTiers[tierIdx], ...ids];
}
logger.info(`[TierScheduler] Unscheduled dims distributed: ${[...byTier.entries()].map(([t, ids]) => `Tier ${t + 1}=[${ids.join(', ')}]`).join(', ')}`);
}
// 移除空 tier
effectiveTiers = effectiveTiers.filter((t) => t.length > 0);
}
for (let tierIndex = 0; tierIndex < effectiveTiers.length; tierIndex++) {
const tier = effectiveTiers[tierIndex];
if (shouldAbort?.()) {
logger.warn(`[TierScheduler] Aborted before Tier ${tierIndex + 1}`);
break;
}
logger.info(`[TierScheduler] ── Tier ${tierIndex + 1}/${this.#tiers.length}: [${tier.join(', ')}] (concurrency=${concurrency})`);
const tierResults = await this.#executeTier(tier, executeDimension, concurrency, shouldAbort);
for (const [dimId, result] of tierResults) {
results.set(dimId, result);
}
onTierComplete?.(tierIndex, tierResults);
}
return results;
}
/** 执行单个 Tier 内的所有维度 (p-limit 并发控制) */
async #executeTier(dimensionIds, executeDimension, concurrency, shouldAbort) {
const limit = createLimit(concurrency);
const results = new Map();
await Promise.all(dimensionIds.map((dimId) => limit(async () => {
if (shouldAbort?.()) {
return;
}
try {
const result = await executeDimension(dimId);
results.set(dimId, result);
}
catch (err) {
const errMsg = err instanceof Error ? err.message : String(err);
logger.error(`[TierScheduler] Dimension "${dimId}" failed: ${errMsg}`);
results.set(dimId, { error: errMsg, candidateCount: 0 });
}
})));
return results;
}
/**
* 获取维度所在的 Tier 索引
* @returns 0-based tier index, -1 if not found
*/
getTierIndex(dimId) {
for (let i = 0; i < this.#tiers.length; i++) {
if (this.#tiers[i].includes(dimId)) {
return i;
}
}
return -1;
}
/** 获取分层定义 */
getTiers() {
return this.#tiers;
}
}
export default TierScheduler;