状态路径
Reset 完成后恢复调用前的运行状态。例如,在 RUNNING 时 reset,完成后仍为 RUNNING;在 PAUSED 时 reset,完成后仍为 PAUSED。变化的是 generation 和世界状态,tick 从零重新开始。
prepare 创建并检查运行依赖,start 开始推进世界,pause 在完整边界暂停,single_step 推进一步后仍保持 PAUSED,stop 结束活动运行,close 释放全部资源。图中展示常规状态路径,未展开异常与瞬时过渡状态。
Generation 是 reset 后的失效边界。 Reset 会创建新的 generation 并把 tick 重新置零。旧 generation 中排队的写操作、控制会话或订阅不能泄漏到新世界;读取结果也携带 generation,便于调用者识别过期数据。
同步与异步门面共享同一 Runtime。 FastSimApplication 是推荐的异步门面,适合嵌入 asyncio 应用、Server 和插件。FastSimRun 提供同步上下文与阻塞式生命周期操作,适合脚本和简单 CLI 集成。二者不构成两套 Runtime。
终结是一段有顺序的过程。 Stop 与 close 不只是关闭后端。控制源需要停止提交,未完成 Operation 需要得到终态,数据插件需要 flush,输出需要验证后原子发布,订阅与服务必须撤销。只有完成这些步骤,Run 才能被报告为完整结束。
状态机与运行不变量
- 物理世界只有一个权威所有者。
- Pause 不把世界停在半个控制/物理 tick 中间。
- Close 幂等且最终释放后台任务。
- 失败与取消必须保留结构化结果,不能伪装成成功停止。
公共方法见Application API 指南与Python SDK。
prepare 建立 Provider 世界、公共服务和插件实例,但不开始连续推进;start 进入运行;pause 在完整边界保留可检查世界;reset 使旧 generation 失效并建立新世界;stop 终结本次运行;close 回收 Application 拥有的全部资源。上下文退出会确保 close,但不能替代业务对 Operation 和终态的处理。
组合顺序与操作语义
生命周期是一个组合合同,而不是向所有对象广播同名函数。Runtime 先保证调用所需的 Core 服务与 Provider 前置条件,再调用依赖这些能力的插件 hook;停止时则先阻止新工作、使已有工作收敛,再逆向撤销服务与资源。
插件 hook 有明确超时和结构化失败。一个插件 prepare 失败后,已创建的其他实例仍需被关闭;close 中再次失败应记录,但不能阻止后续资源继续回收。
Pause、Stop 与 Close 的含义不同。 Pause 用于保留世界并检查,它不表示 Run 已完成,数据插件也不应因此发布最终产物。Stop 表示运行进入终态,触发 Operation 收敛、数据 flush 和终结事件。Close 则释放 Application 本身,可在 stop 后执行,也需要能够处理此前已经失败的状态。
若用户只想暂时查看一个画面,应 pause;若不再继续本次运行,应 stop;若进程或上层服务不再使用实例,应 close。把三者混成一个“停止按钮”会造成输出与资源语义不清。
Reset 必须清理整个旧 generation。 Reset 至少影响状态快照、控制目标、Operation、订阅、插件 scoped service、规划/运动学结果和 Provider 内部世界。旧 generation 的在途计算即使晚到,也不能发布到新 generation。
客户端在 reset 后需要重新读取状态、capabilities 与 targets,重新建立订阅,并用新 generation 发起控制。保留旧 Python 值对象本身是安全的,但继续把它作为当前世界事实使用是不正确的。
失败收敛与客户端责任
生命周期调用超时意味着该转换没有在调用方预算内确认完成;Runtime 仍需要进入已定义的恢复或关闭路径。Operation 等异步工作则具有独立取消合同:等待超时不自动取消,必须发送 cancel 并观察是否接受以及最终状态。
诊断时保存转换前后 Application snapshot、run ID、generation、插件 failure records 与 Provider 错误。只记录顶层 traceback 往往无法判断是 hook、服务撤销还是后端关闭失败。
调用方需要承担生命周期的一部分责任:
- 在 async 服务、UI 和 Web 程序中使用异步 Application,不嵌套同步门面。
- 每次 reset 后刷新 generation 相关缓存和订阅。
- 对长操作保存 Operation,按业务决定等待、取消或释放。
- 在
finally或上下文退出中保证 close,且不要假设 close 从不抛出聚合失败。 - 把最终状态与输出回执作为完成证据,不用“进程退出码为 0”替代全部语义。
下一步阅读Plugin 与能力边界理解插件如何进入同一生命周期,或按Python Application API实现调用方。