feat: 完整游戏运维功能
This commit is contained in:
@@ -96,8 +96,21 @@ interface RuntimeTaskRunOptions<T> {
|
||||
|
||||
export interface RuntimeTrackedJob {
|
||||
id: string;
|
||||
state: "queued" | "accepted" | "running" | "succeeded" | "failed" | "cancelled";
|
||||
state: "queued" | "accepted" | "running" | "retrying" | "succeeded" | "failed" | "cancelled";
|
||||
progress: { percent: number; message?: string };
|
||||
attempt?: number;
|
||||
retryPolicy?: { maxAttempts: number };
|
||||
nextAttemptAt?: string;
|
||||
cancelReason?: string;
|
||||
reconcileOutcome?: string;
|
||||
}
|
||||
|
||||
export interface RuntimeTrackedJobProjection {
|
||||
status: RuntimeTaskStatus;
|
||||
percent: number;
|
||||
currentStageKey: string;
|
||||
stageStatus: Record<string, RuntimeTaskStageStatus>;
|
||||
message: string;
|
||||
}
|
||||
|
||||
interface RuntimeTrackedTaskOptions<T> {
|
||||
@@ -242,20 +255,15 @@ export function useRuntimeTaskController() {
|
||||
|
||||
while (true) {
|
||||
const job = await poll(started.jobId);
|
||||
const message = job.progress.message?.trim() || job.state;
|
||||
const stageIndex = trackedStageIndex(stages, message, job.progress.percent);
|
||||
const stage = stages[stageIndex] ?? stages[0];
|
||||
const stageStatus = Object.fromEntries(
|
||||
stages.map((item, index) => [item.key, index < stageIndex || job.state === "succeeded" ? "completed" : index === stageIndex ? "running" : "pending"])
|
||||
) as Record<string, RuntimeTaskStageStatus>;
|
||||
const projection = projectRuntimeTrackedJob(stages, job);
|
||||
setTask((current) =>
|
||||
current
|
||||
? {
|
||||
...current,
|
||||
percent: Math.max(current.percent, Math.min(99, job.progress.percent)),
|
||||
currentStageKey: stage?.key ?? current.currentStageKey,
|
||||
stageStatus,
|
||||
logs: current.logs[current.logs.length - 1] === message ? current.logs : appendRuntimeLog(current.logs, message)
|
||||
percent: job.state === "succeeded" ? 100 : Math.max(current.percent, projection.percent),
|
||||
currentStageKey: projection.currentStageKey || current.currentStageKey,
|
||||
stageStatus: projection.stageStatus,
|
||||
logs: current.logs[current.logs.length - 1] === projection.message ? current.logs : appendRuntimeLog(current.logs, projection.message)
|
||||
}
|
||||
: current
|
||||
);
|
||||
@@ -275,14 +283,15 @@ export function useRuntimeTaskController() {
|
||||
return started.value;
|
||||
}
|
||||
if (job.state === "failed" || job.state === "cancelled") {
|
||||
const error = message || (job.state === "cancelled" ? "构建已取消" : "构建失败");
|
||||
const error = projection.message || (job.state === "cancelled" ? "构建已取消" : "构建失败");
|
||||
setTask((current) =>
|
||||
current
|
||||
? {
|
||||
...current,
|
||||
status: "failed",
|
||||
error,
|
||||
stageStatus: { ...stageStatus, [stage?.key ?? firstStage]: "failed" },
|
||||
currentStageKey: projection.currentStageKey || firstStage,
|
||||
stageStatus: projection.stageStatus,
|
||||
logs: appendRuntimeLog(current.logs, error)
|
||||
}
|
||||
: current
|
||||
@@ -484,6 +493,27 @@ function trackedStageIndex(stages: RuntimeTaskStage[], message: string, percent:
|
||||
return Math.min(index, Math.max(0, stages.length - 1));
|
||||
}
|
||||
|
||||
export function projectRuntimeTrackedJob(stages: RuntimeTaskStage[], job: RuntimeTrackedJob): RuntimeTrackedJobProjection {
|
||||
const retryLabel = job.state === "retrying" ? `等待第 ${Math.min((job.attempt ?? 0) + 1, job.retryPolicy?.maxAttempts ?? (job.attempt ?? 0) + 1)} 次尝试${job.nextAttemptAt ? `(${new Date(job.nextAttemptAt).toLocaleString()})` : ""}` : "";
|
||||
const message = job.cancelReason?.trim() || job.progress.message?.trim() || retryLabel || job.reconcileOutcome?.trim() || job.state;
|
||||
const stageIndex = trackedStageIndex(stages, message, job.progress.percent);
|
||||
const currentStageKey = stages[stageIndex]?.key ?? stages[0]?.key ?? "start";
|
||||
const terminalFailure = job.state === "failed" || job.state === "cancelled";
|
||||
const stageStatus = Object.fromEntries(
|
||||
stages.map((item, index) => [
|
||||
item.key,
|
||||
job.state === "succeeded" || index < stageIndex ? "completed" : index === stageIndex ? (terminalFailure ? "failed" : "running") : "pending"
|
||||
])
|
||||
) as Record<string, RuntimeTaskStageStatus>;
|
||||
return {
|
||||
status: job.state === "succeeded" ? "succeeded" : terminalFailure ? "failed" : "running",
|
||||
percent: job.state === "succeeded" ? 100 : Math.min(99, Math.max(0, job.progress.percent)),
|
||||
currentStageKey,
|
||||
stageStatus,
|
||||
message
|
||||
};
|
||||
}
|
||||
|
||||
function appendRuntimeLog(logs: string[], line: string): string[] {
|
||||
return [...logs, line].slice(-8);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user