Cookwala / حزمة التطوير والسيناريوهات / 042
Resume a waiting run with If-Match set to the current seq
When the device waits for a person, the person confirms by resuming. The resume carries If-Match with the seq read from the status, so two people cannot both answer the same question.
اقرأ أولًا: /docs/CORE/ /docs/HUB/
الخطوات
Start a shakshuka run with a person present.
startExecutionThe arm cuts; the run then waits for a person to heat the pan.
Read the status and keep its seq.
getExecutionResume with the seq just read. The hub accepts and the run continues: the person is heating the pan.
resumeExecutionOne simulated minute of heating passes.
The next step, sautéing the onion, is again one a person performs on this device, so the run waits once more with a higher seq.
getExecution
النتيجة
You have resumed a run with the right precondition. Next: scenario 043 shows what happens with a stale seq.
سطر الأوامر
cookwala hub --recipes examples --speed 200
jq '. + {"x-hub-human-present": true}' examples/core/execute-request.json | curl -s -X POST http://localhost:7878/v1/executions -H 'Content-Type: application/json' -H 'Idempotency-Key: ex-2026-10-04-001-a' -d @-
curl -si http://localhost:7878/v1/executions/ex-2026-10-04-001
curl -s -X POST http://localhost:7878/v1/executions/ex-2026-10-04-001/resume -H 'If-Match: 6' -H 'Idempotency-Key: resume-0001'المخرجات المسجلة
الحالة: ok
[1] startExecution: {"core": "0.2.0", "kind": "ExecutionStatus", "id": "ex-042-resume", "seq": 0, "state": "accepted", "request": "ex-042-resume", "updatedAt": "2026-10-07T00:54:17Z", "x-hub-plan": [{"node": "n1", "op": "cw.op.cut", "by": "device", "verifiedBy": "sensor", "rung": "cw.sense.vision"}, {"node": "n2", "op": "cw.op.cut", "by": "device", "verifiedBy": "sensor", "rung": "cw.sense.vision"}, {"node": "n3", "op": "cw.op.cut", "by": "device", "verifiedBy": "sensor", "rung": "cw.sense.vision"}, {"node": "n4", "op": "cw.op.heat", "by": "human", "verifiedBy": "human"}, {"node": "n5", "op": "cw.op.saute", "by":…
[3] getExecution: {"core": "0.2.0", "kind": "ExecutionStatus", "id": "ex-042-resume", "seq": 6, "state": "needs_human", "request": "ex-042-resume", "updatedAt": "2026-10-07T00:54:19Z", "x-hub-plan": [{"node": "n1", "op": "cw.op.cut", "by": "device", "verifiedBy": "sensor", "rung": "cw.sense.vision"}, {"node": "n2", "op": "cw.op.cut", "by": "device", "verifiedBy": "sensor", "rung": "cw.sense.vision"}, {"node": "n3", "op": "cw.op.cut", "by": "device", "verifiedBy": "sensor", "rung": "cw.sense.vision"}, {"node": "n4", "op": "cw.op.heat", "by": "human", "verifiedBy": "human"}, {"node": "n5", "op": "cw.op.saute", "b…
[4] resumeExecution: {"core": "0.2.0", "kind": "ExecutionStatus", "id": "ex-042-resume", "seq": 7, "state": "running", "request": "ex-042-resume", "updatedAt": "2026-10-07T00:54:21Z", "x-hub-plan": [{"node": "n1", "op": "cw.op.cut", "by": "device", "verifiedBy": "sensor", "rung": "cw.sense.vision"}, {"node": "n2", "op": "cw.op.cut", "by": "device", "verifiedBy": "sensor", "rung": "cw.sense.vision"}, {"node": "n3", "op": "cw.op.cut", "by": "device", "verifiedBy": "sensor", "rung": "cw.sense.vision"}, {"node": "n4", "op": "cw.op.heat", "by": "human", "verifiedBy": "human"}, {"node": "n5", "op": "cw.op.saute", "by": …
[6] getExecution: {"core": "0.2.0", "kind": "ExecutionStatus", "id": "ex-042-resume", "seq": 8, "state": "needs_human", "request": "ex-042-resume", "updatedAt": "2026-10-07T00:54:21Z", "x-hub-plan": [{"node": "n1", "op": "cw.op.cut", "by": "device", "verifiedBy": "sensor", "rung": "cw.sense.vision"}, {"node": "n2", "op": "cw.op.cut", "by": "device", "verifiedBy": "sensor", "rung": "cw.sense.vision"}, {"node": "n3", "op": "cw.op.cut", "by": "device", "verifiedBy": "sensor", "rung": "cw.sense.vision"}, {"node": "n4", "op": "cw.op.heat", "by": "human", "verifiedBy": "human"}, {"node": "n5", "op": "cw.op.saute", "b…الكود
التشغيل: python scenarios/out/042-resume-with-the-current-seq/python.py
# Scenario 042: Resume a waiting run with If-Match set to the current seq
# When the device waits for a person, the person confirms by resuming. The resume carries If-Match with the seq read from the status, so two people cannot both answer the same question.
# Run a hub first: python hub/cookwala_hub.py --recipes examples
import json, os
from cookwala.client import CookwalaClient, CookwalaProblem
def load(path):
with open(path, encoding="utf-8") as f:
return json.load(f)
def pick(obj, path):
for part in path.replace("]", "").replace("[", ".").split("."):
obj = obj[int(part)] if part.isdigit() else (len(obj) if part == "length" else obj.get(part))
return obj
c = CookwalaClient(os.environ.get("COOKWALA_HUB", "http://localhost:7878"))
# Step 1: Start a shakshuka run with a person present.
try:
started = c.start_execution({"core": "0.2.0", "kind": "ExecuteRequest", "id": "ex-042-resume", "recipe": "cw:cookwala.ai:example-shakshuka", "recipeHash": "sha256:2ea6fab93cc673fc6784f9bc9fe401d2387bb7779dc537df97286b73807c8841", "servings": 4, "requestedBy": "agent:planner-1", "idempotencyKey": "ex-042-resume-a"}, "ex-042-resume-key", True)
except CookwalaProblem as p:
started = p.body # a refusal is a result, not a crash
print("refused:", p.refusal)
assert pick(started, "state") == "accepted", pick(started, "state")
print("ok", "state", "=", "accepted")
# Step 2: The arm cuts; the run then waits for a person to heat the pan.
import time; time.sleep(4)
# Step 3: Read the status and keep its seq.
status = c.get_execution("ex-042-resume")
assert pick(status, "state") == "needs_human", pick(status, "state")
print("ok", "state", "=", "needs_human")
assert pick(status, "seq") == 6, pick(status, "seq")
print("ok", "seq", "=", 6)
# Step 4: Resume with the seq just read. The hub accepts and the run continues: the person is heating the pan.
try:
resumed = c.resume_execution("ex-042-resume", pick(status, "seq"))
except CookwalaProblem as p:
resumed = p.body # a refusal is a result, not a crash
print("refused:", p.refusal)
assert pick(resumed, "state") == "running", pick(resumed, "state")
print("ok", "state", "=", "running")
assert pick(resumed, "seq") == 7, pick(resumed, "seq")
print("ok", "seq", "=", 7)
# Step 5: One simulated minute of heating passes.
import time; time.sleep(2)
# Step 6: The next step, sautéing the onion, is again one a person performs on this device, so the run waits once more with a higher seq.
next = c.get_execution("ex-042-resume")
assert pick(next, "state") == "needs_human", pick(next, "state")
print("ok", "state", "=", "needs_human")
assert pick(next, "seq") == 8, pick(next, "seq")
print("ok", "seq", "=", 8)
assert pick(next, "humanNeeded.why") == "a person performs cw.op.saute", pick(next, "humanNeeded.why")
print("ok", "humanNeeded.why", "=", "a person performs cw.op.saute")
print("scenario complete")