尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

异步接口别掩盖取消语义

异步接口别掩盖取消语义 异步接口别掩盖取消语义看到一个async fn调用方很容易形成直觉不再需要结果时丢掉 Future 就等于取消操作。这个理解只对了一半。Future 不再被轮询当前 Rust 代码会停止向前执行但已经发出的网络请求、交给线程池的阻塞任务或已经提交的数据库写入未必随之停止。接口若不说明这层差别取消和超时就会变成难查的状态问题。返回类型没有表达全部语义下面这个签名能看出成功值和错误类型却看不出取消后会发生什么async fn fetch_name(id: Id) - ResultString, FetchError如果函数只做一次可取消的网络读取Future 被丢弃后关闭连接语义相对简单。若它会先写缓存、再访问远端取消点落在两步之间时缓存可能已经变化。若底层 SDK 把任务投到独立线程Future 消失也可能只是没人接收结果线程仍会继续工作。公共接口的文档需要说明副作用在哪一步发生、取消是否向下传播以及资源最迟何时释放。还要区分取消、超时和业务失败。超时通常由调用方停止等待触发它不能证明服务端没有完成业务失败则是操作已经结束并返回了确定结果。把三者都压成同一个FetchError::Failed调用方就无法决定重试是否安全也无法解释为什么超时后数据仍发生变化。先判断操作能不能撤销纯查询通常可以在取消后放弃结果最多留下短暂的远端计算。带副作用的操作则要更谨慎。创建订单、发送通知、写入文件等动作一旦越过提交点取消只能停止后续工作不能假装前面没有发生。此时接口可以返回任务标识让调用方查询最终状态提交请求使用幂等键重试时也不会产生第二份副作用。如果业务确实支持撤销应把撤销设计成独立操作并说明它可能失败而不是把它藏在 Future 的析构里。析构不能等待异步网络往返进程崩溃时也未必有机会执行完整补偿。可靠的撤销需要持久状态和可重试的处理流程。子任务要跟着父任务收口异步函数内部启动子任务时最容易破坏取消语义。直接spawn后不保存句柄父 Future 即使被取消子任务仍会运行。代码评审要检查每个派生任务由谁等待、谁取消、错误返回到哪里。适合随请求结束的任务应纳入同一个作用域必须脱离请求运行的后台任务则交给有生命周期管理的组件不要悄悄悬空。资源清理也应围绕取消点设计。锁守卫、临时文件和连接借用要在 Future 被丢弃时可靠释放半成品文件可先写入临时路径完成后再原子替换流式协议需要让对端知道本地停止消费避免服务端继续发送到无人读取的连接。测试要主动丢弃 Future只测试正常await和错误返回覆盖不到取消。可以让函数停在每个关键等待点随后丢弃 Future检查子任务、连接、锁和临时文件的状态。对带写入的接口还要确认提交前取消不会产生结果提交后取消能够通过任务查询得到最终状态。再加入超时与重复请求验证调用方不会把“不知道结果”误判成“确定失败”。日志中应把cancelled、deadline_exceeded和业务错误分开并带上任务标识。否则大量“请求失败”既无法反映真实服务质量也无法找出取消后仍在运行的孤儿任务。异步接口的好坏不只看调用方式是否简洁。调用者必须知道停止等待会造成什么、哪些副作用已经不可逆、后续到哪里查询。把这些写进接口契约取消才是可用的控制能力而不是一个看起来自然、实际含糊的默认行为。
返回列表