消息、任务、产物与流式恢复:练习答案
练习解答
以下是完整离线文件,保存为answer.py后运行python answer.py;先建立与正文一致的初始状态,再验证变体。
使用正文 advance:
python
terminal={'completed','failed','canceled','rejected'}
def advance(current,event):
if current in terminal:raise ValueError('terminal task cannot restart')
if event not in {'working','input-required'}|terminal:raise ValueError('unknown state')
return event
state='submitted'
state=advance(state,'working')
state=advance(state,'input-required')
state=advance(state,'working')
state=advance(state,'completed')
assert state=='completed'
try:advance(state,'working')
except ValueError:pass
else:raise AssertionError('restarted terminal task')
print('state boundary passed')
assert advance(advance('working','input-required'),'working')=='working'
try:advance(advance('working','failed'),'working')
except ValueError:pass
else:raise AssertionError('terminal task revived')迟到事件需要按任务版本/快照规则处理;终态保护防止 UI 因旧消息倒退为进行中。真实客户端还应识别重复终态与更新序列,不把所有重复都升级成服务失败。
持久任务变体
正文durable.py中保留正常完成的第一条路径,将第二个任务从 pending=await send(c,'another task') 改为下面两行,其余取消与查询逻辑不变:
python
pending=await send(c,'another task')
pending=await send(c,'sku:B',pending)
assert pending.status.state==TaskState.TASK_STATE_INPUT_REQUIRED在cancelled断言之后追加:
python
assert (await c.get_task(GetTaskRequest(id=pending.id))).status.state==TaskState.TASK_STATE_CANCELED另复制正文为replace_artifact.py,仅将第二个add_artifact的append=True改为False,并把结果断言中的A:3改为3。完整运行应通过;若保留A:3断言应失败。这说明协议的append标志控制归并,客户端自行字符串拼接会产生不存在的产物。