mirror of
https://github.com/QwenLM/qwen-code.git
synced 2026-10-24 07:49:59 +00:00
test(managed-agent): reuse a same-key cancel (FG11d)
This commit is contained in:
parent
d625f663b9
commit
acdab642b7
6 changed files with 56 additions and 12 deletions
7
.github/workflows/sdk-java.yml
vendored
7
.github/workflows/sdk-java.yml
vendored
|
|
@ -775,8 +775,9 @@ jobs:
|
|||
# the fork to 10621 s and Verify to 188 minutes; the FG12d
|
||||
# cancel-before-dispatch cell adds 18 s, moving the fork to 10639 s; the
|
||||
# FG11d retry-reuse cell adds 11 s, moving the fork to 10650 s; the FG11d
|
||||
# settled-outcome cell adds 9 s, moving the fork to 10659 s, wrapping
|
||||
# fork + 600 s plus margin (11259 s of fork plus wrap);
|
||||
# settled-outcome cell adds 9 s, moving the fork to 10659 s; the FG11d
|
||||
# cancel-retry cell adds 12 s, moving the fork to 10671 s, wrapping
|
||||
# fork + 600 s plus margin (11271 s of fork plus wrap);
|
||||
# the Broker fault gates use 20,
|
||||
# and admission plus O4 keep per-fork ceilings) plus ~13 minutes for the
|
||||
# uncapped setup steps (Checkout.. cgroup delegation, the report
|
||||
|
|
@ -881,7 +882,7 @@ jobs:
|
|||
# fork leaves no per-test failure lines, so the main-CI failure
|
||||
# analyzer can only file an undiagnosable per-commit issue (#13503).
|
||||
# hosted-process-ci.test.js pins this ordering; the fork budget is
|
||||
# 10659 s, so the step wraps to fork + 600 s plus margin (188 min).
|
||||
# 10671 s, so the step wraps to fork + 600 s plus margin (188 min).
|
||||
timeout-minutes: 188
|
||||
env:
|
||||
MAVEN_ARGS: '--settings ${{ runner.temp }}/setup-java-m2/settings.xml --toolchains ${{ runner.temp }}/setup-java-m2/toolchains.xml'
|
||||
|
|
|
|||
|
|
@ -65,6 +65,9 @@ asserts:
|
|||
arriving after settlement is refused with `409 task_action_unavailable`
|
||||
(`The task does not accept a cancellation now.`), and the run stays
|
||||
`completed` with its occurrence `fired`;
|
||||
- a cancel retried under the same key reuses its committed operation and changes
|
||||
nothing — delivered: the second request answers the cancelled task, the run
|
||||
stays `cancelled` and the occurrence settles once;
|
||||
- a retry under the same key reuses the original operation and run — delivered:
|
||||
the second `POST /runs` answers the run it already made, records no second
|
||||
occurrence and starts no second Turn. That a parked cancel is never
|
||||
|
|
|
|||
|
|
@ -50,12 +50,14 @@ retire、retire 之后无 slot fire),FG11b 钉住账本周围的存储故障
|
|||
- 被取消的 run 依据其已提交的证明进入 `cancelled`,occurrence 恰好结算一次;
|
||||
- schedule、未来 slot、兄弟 run 与前台工作不受影响;
|
||||
- 在任何尝试之前被取消的排队 input 结算且不调用模型。自然完成的 run 保留其结果
|
||||
已交付:结算之后到达的取消被 `409 task_action_unavailable`(`The task does
|
||||
not accept a cancellation now.`)拒绝,run 保持 `completed`、occurrence 保持
|
||||
已交付:结算之后到达的取消被 `409 task_action_unavailable`(`The task does not
|
||||
accept a cancellation now.`)拒绝,run 保持 `completed`、occurrence 保持
|
||||
`fired`;
|
||||
- `cancel-stops-only-the-target` 已交付:把 wake turn 扣在模型上时,公开 task
|
||||
cancel 让 task 与 run 在一秒内结算为 `cancelled`,schedule 保持 `live`;反之在
|
||||
收到 `202` 后立刻释放模型,turn 会先跑完——本格避开的正是这个顺序。
|
||||
- 同一 key 重试取消复用其已提交的 operation 且不产生新动作——已交付:第二次请求
|
||||
返回已取消的 task,run 保持 `cancelled`、occurrence 恰好结算一次;
|
||||
- 同一 key 的重试复用原 operation 与 run——已交付:第二次 `POST /runs` 返回它
|
||||
已经创建的 run,不产生第二个 occurrence,也不起第二个 Turn。被扣住的 cancel
|
||||
绝不重投仍未覆盖。
|
||||
|
|
|
|||
|
|
@ -579,8 +579,11 @@
|
|||
measured 5.3 s): healthy 10050 s, fork 10650 s,
|
||||
Verify 188 minutes. The FG11d settled-outcome
|
||||
cell adds 9 s (2x its measured 4.5 s): healthy
|
||||
10059 s, fork 10659 s, Verify 188 minutes. -->
|
||||
<forkedProcessTimeoutInSeconds>10659</forkedProcessTimeoutInSeconds>
|
||||
10059 s, fork 10659 s, Verify 188 minutes. The
|
||||
FG11d cancel-retry cell adds 12 s (2x its
|
||||
measured 5.8 s): healthy 10071 s, fork 10671 s,
|
||||
Verify 188 minutes. -->
|
||||
<forkedProcessTimeoutInSeconds>10671</forkedProcessTimeoutInSeconds>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
|
|
|
|||
|
|
@ -1467,6 +1467,39 @@ class HostedAutomationFaultGatesIT {
|
|||
request("DELETE", "/v1/agent-automations/" + id, null, "fg11d-settled-retire", 202);
|
||||
}
|
||||
|
||||
// FG11d: retrying a cancel under the same key reuses its operation. The
|
||||
// second request answers the already-cancelled task, records nothing new and
|
||||
// starts no Turn.
|
||||
@Test
|
||||
@Timeout(600)
|
||||
void fg11dCancelRetryReusesItsOperationOnMySql() throws Exception {
|
||||
boot("fg11d");
|
||||
String session = createSession("cancel-retry");
|
||||
String id = request("POST", "/v1/agent-automations",
|
||||
definition(session, "FG11A_HOLD", "0 0 1 1 *"), "fg11d-cancel-retry-base", 202).path("id").asText();
|
||||
String run = request("POST", "/v1/agent-automations/" + id + "/runs", null, "fg11d-cancel-retry-run", 202)
|
||||
.path("id").asText();
|
||||
waiting().atMost(Duration.ofSeconds(60)).until(() -> modelPrompts.stream()
|
||||
.anyMatch(prompt -> prompt.contains("manual:fg11d-cancel-retry-run")));
|
||||
JsonNode task = request("GET", "/v1/agents/sessions/" + session + "/tasks", null, null, 200)
|
||||
.path("data").path(0);
|
||||
assertThat(task.path("kind").asText()).as("the newest task is the run's").isEqualTo("automation_run");
|
||||
String taskId = task.path("id").asText();
|
||||
request("POST", "/v1/agents/sessions/" + session + "/tasks/" + taskId + "/cancel", null,
|
||||
"fg11d-cancel-retry", 202);
|
||||
waiting().atMost(Duration.ofSeconds(120)).untilAsserted(() -> assertThat(runState(run))
|
||||
.as("the run is cancelled").isEqualTo("cancelled"));
|
||||
// The retry reuses the committed cancel instead of acting twice.
|
||||
request("POST", "/v1/agents/sessions/" + session + "/tasks/" + taskId + "/cancel", null,
|
||||
"fg11d-cancel-retry", 202);
|
||||
assertThat(runState(run)).as("the retry changes nothing").isEqualTo("cancelled");
|
||||
assertThat(jdbc.queryForMap("SELECT outcome FROM ma_schedule_occurrence WHERE tenant_id = ?"
|
||||
+ " AND schedule_id = ? AND occurrence_key = ?", tenant, id, "manual:fg11d-cancel-retry-run"))
|
||||
.as("the occurrence settles once").containsEntry("outcome", "fired");
|
||||
heldModel.countDown();
|
||||
request("DELETE", "/v1/agent-automations/" + id, null, "fg11d-cancel-retry-retire", 202);
|
||||
}
|
||||
|
||||
private void boot(String letter) throws Exception {
|
||||
assertThat(System.getProperty("mysql.url")).as("FG11 requires real MySQL").startsWith("jdbc:mysql:");
|
||||
this.letter = letter;
|
||||
|
|
|
|||
|
|
@ -766,13 +766,14 @@ describe('Hosted real-process gates', () => {
|
|||
// 18 s (2x its measured 9.1 s), so the fork moves to 10639; the FG11d
|
||||
// retry-reuse cell adds 11 s (2x its measured 5.3 s), moving the fork to
|
||||
// 10650 and the step stays 188 minutes; the FG11d settled-outcome cell adds
|
||||
// 9 s (2x its measured 4.5 s), moving the fork to 10659 and the step
|
||||
// stays 188 minutes):
|
||||
// 9 s (2x its measured 4.5 s), moving the fork to 10659; the FG11d
|
||||
// cancel-retry cell adds 12 s (2x its measured 5.8 s), moving the fork to
|
||||
// 10671 and the step stays 188 minutes):
|
||||
// the relational check above tolerates
|
||||
// anything up to step*60, so the value is pinned literally here —
|
||||
// an unnoticed raise has no other red to land on.
|
||||
if (profile === 'hosted-harness-mysql') {
|
||||
expect(forkSeconds).toBe(10659);
|
||||
expect(forkSeconds).toBe(10671);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
|
@ -858,12 +859,13 @@ describe('Hosted real-process gates', () => {
|
|||
// FG12d cancel-before-dispatch cell adds 18s (2x its measured 9.1s), so it
|
||||
// becomes 10039s; the retry-reuse cell adds 11s (2x its measured 5.3s), so it
|
||||
// becomes 10050s; the settled-outcome cell adds 9s (2x its measured 4.5s),
|
||||
// so it becomes 10059s. The largest
|
||||
// so it becomes 10059s; the cancel-retry cell adds 12s (2x its measured 5.8s),
|
||||
// so it becomes 10071s. The largest
|
||||
// ceiling (600s) plus
|
||||
// that healthy sum still fits the fork. A larger ceiling lets failsafe
|
||||
// kill the fork mid-run, and the classes left unrun never report, failing
|
||||
// the gate undiagnosably (#13780).
|
||||
const hostedForkHealthySeconds = 10059;
|
||||
const hostedForkHealthySeconds = 10071;
|
||||
const hostedForkSeconds = () =>
|
||||
Number(
|
||||
read('packages/managed-agent-server/pom.xml')
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue