fix: 隔离 Queue 重试内部 Job identity
This commit is contained in:
@@ -13,6 +13,7 @@ export interface DispatchQueueTaskOptions {
|
||||
}
|
||||
|
||||
export async function dispatchQueueTask(options: DispatchQueueTaskOptions): Promise<QueueDispatchResult> {
|
||||
assertPublicQueueDispatchInput(options.input);
|
||||
const task = await options.store.getQueueTask(options.taskId);
|
||||
assertDispatchable(task);
|
||||
|
||||
@@ -140,7 +141,6 @@ export function buildQueueRunnerJobInput(task: QueueTaskRecord, commandId: strin
|
||||
copyString("image", "image");
|
||||
copyString("namespace", "namespace");
|
||||
copyString("attemptId", "attemptId");
|
||||
copyString("runnerJobId", "runnerJobId");
|
||||
copyString("runnerId", "runnerId");
|
||||
copyString("sourceCommit", "sourceCommit");
|
||||
copyString("serviceAccountName", "serviceAccountName");
|
||||
@@ -153,6 +153,12 @@ export function buildQueueRunnerJobInput(task: QueueTaskRecord, commandId: strin
|
||||
return jobInput;
|
||||
}
|
||||
|
||||
function assertPublicQueueDispatchInput(input: JsonRecord): void {
|
||||
if (Object.prototype.hasOwnProperty.call(input, "runnerJobId")) {
|
||||
throw new AgentRunError("schema-invalid", "queue dispatch does not accept caller-provided runnerJobId", { httpStatus: 400, details: { unexpected: ["runnerJobId"], valuesPrinted: false } });
|
||||
}
|
||||
}
|
||||
|
||||
function stringFrom(record: JsonRecord, key: string): string {
|
||||
const value = record[key];
|
||||
if (typeof value !== "string" || value.length === 0) throw new AgentRunError("infra-failed", `runner job response missing ${key}`, { httpStatus: 502 });
|
||||
|
||||
@@ -39,11 +39,13 @@ export async function retryQueueTask(options: RetryQueueTaskOptions): Promise<Qu
|
||||
runnerJob = await createKubernetesRunnerJob({
|
||||
store: options.store,
|
||||
runId: run.id,
|
||||
input: buildQueueRunnerJobInput(reservation.task, command.id, {
|
||||
attemptId: attempt.attemptId,
|
||||
input: {
|
||||
...buildQueueRunnerJobInput(reservation.task, command.id, {
|
||||
attemptId: attempt.attemptId,
|
||||
idempotencyKey: `queue:${reservation.task.id}:attempt:${attempt.attemptId}:runner-job`,
|
||||
}),
|
||||
runnerJobId: attempt.runnerJobId,
|
||||
idempotencyKey: `queue:${reservation.task.id}:attempt:${attempt.attemptId}:runner-job`,
|
||||
}),
|
||||
},
|
||||
defaults: options.defaults,
|
||||
});
|
||||
} catch (error) {
|
||||
|
||||
@@ -76,6 +76,14 @@ console.log(JSON.stringify({ apiVersion: manifest.apiVersion, kind: manifest.kin
|
||||
});
|
||||
try {
|
||||
const client = new ManagerClient(server.baseUrl);
|
||||
const injectionTask = await client.post("/api/v1/queue/tasks", taskInput(context.workspace, "queue-q5-runner-job-id-injection")) as QueueTaskRecord;
|
||||
await assert.rejects(
|
||||
() => client.post(`/api/v1/queue/tasks/${injectionTask.id}/dispatch`, { attemptId: "attempt_public_injection", runnerJobId: "rjob_public_injection" }),
|
||||
/does not accept caller-provided runnerJobId/u,
|
||||
);
|
||||
assert.equal((await client.get(`/api/v1/queue/tasks/${injectionTask.id}`) as QueueTaskRecord).state, "pending");
|
||||
assert.equal((await attempts(client, injectionTask.id)).count, 0);
|
||||
|
||||
const failed = await createTerminalTask(client, context.workspace, "failed", "queue-q5-failed");
|
||||
const before = await attempts(client, failed.task.id);
|
||||
assert.equal(before.count, 1);
|
||||
@@ -215,6 +223,7 @@ console.log(JSON.stringify({ apiVersion: manifest.apiVersion, kind: manifest.kin
|
||||
tests: [
|
||||
"retry-server-dry-run-zero-write",
|
||||
"initial-dispatch-attempt-history",
|
||||
"public-dispatch-rejects-runner-job-identity-injection",
|
||||
"retry-rejects-task-patch",
|
||||
"retry-same-key-concurrency",
|
||||
"retry-job-failure-keeps-task-terminal",
|
||||
|
||||
Reference in New Issue
Block a user