doatlas-2 / artifacts /api-server /src /lib /competition-state.ts
Iostream-Li's picture
Add files using upload-large-folder tool
5871090 verified
/**
* Task #226 — competition driver 的 in-memory 进程状态单例。
*
* 这层故意是 in-memory 而不是 DB:driver 是 single-instance background
* worker(整 process 内只允许一个 run 同时进行 — 由 admin /start 端点的
* 单飞锁拦截),状态读取频率高(前端 5s 轮询),DB 走一遍没必要。
*
* 当 api-server 重启 → 内存被清,状态会从 'idle' 重新开始;但已落地的
* task_ledger / network_version_metrics / submission_feedback_ledger 仍
* 在 DB,driver 下次手动触发时会按 plan_competition_<runId> 续跑。
*
* 路由层用 getCompetitionState / setCompetitionState / patchCompetitionState
* 三个口子拿和写,没有别的入口 — 严格封装。
*/
export type CompetitionStatus =
| "idle"
| "running"
| "completed"
| "failed";
export interface CompetitionRunState {
/** 当前 run 的 id,idle 时为 null。 */
runId: string | null;
status: CompetitionStatus;
startedAt: string | null;
finishedAt: string | null;
/** 已完成的 task 数(含从 ledger 续跑当 done 算上的)。 */
completed: number;
/** 失败 task 数。 */
failed: number;
/** 本 run 的总 task 数(loadManifest 后才知道,之前为 0)。 */
total: number;
/** 已完成 task 的均值 EF1%(仅 done 行), driver 实时算的。 */
meanEf1Percent: number;
/** 完成后 result.zip 的绝对路径, idle/running 时 null。 */
resultZipPath: string | null;
/** 飞轮 in-vivo 触发后产生的事件计数(promote+rolledback 等)。 */
flywheelEvents: number;
/** 错误信息(failed 状态下非空)。 */
lastError: string | null;
/** 一行人类可读 note,UI 用来显示当前在做什么。 */
note: string;
}
const idle: CompetitionRunState = {
runId: null,
status: "idle",
startedAt: null,
finishedAt: null,
completed: 0,
failed: 0,
total: 0,
meanEf1Percent: 0,
resultZipPath: null,
flywheelEvents: 0,
lastError: null,
note: "",
};
let current: CompetitionRunState = { ...idle };
export function getCompetitionState(): CompetitionRunState {
return { ...current };
}
export function setCompetitionState(next: Partial<CompetitionRunState> & { status: CompetitionStatus }): CompetitionRunState {
current = { ...idle, ...next };
return { ...current };
}
export function patchCompetitionState(
patch: Partial<CompetitionRunState>,
): CompetitionRunState {
current = { ...current, ...patch };
return { ...current };
}
export function resetCompetitionStateForTest(): void {
current = { ...idle };
}