后台任务先算窗口

一个看起来很小的同步需求,放到 iOS 后台执行里,经常会变成“明明本地测过,线上偶尔不跑”的问题。用户关掉 App、网络从 Wi-Fi 切到蜂窝、系统回收资源、任务被延后调度,这些都不是异常边角料,而是移动端后台任务的日常环境。
这篇文章不打算把后台任务窗口讲成抽象原则,而是放到真实项目里拆:它受哪些机制影响,哪里需要提前定责,失败以后怎样恢复。我的取舍是,先让状态和责任可解释,再追求漂亮的封装或更快的路径。
先别把后台当成另一个前台
后台任务不是用户看不见的前台流程,它拿到的执行窗口有限,调度也不完全由业务控制。先把必须完成、可以延后、可以丢弃的动作分开,后面才不会把所有任务都塞进同一个入口。 这一步的价值不是让流程变得复杂,而是把隐含假设摊到桌面上。只要假设能被看见,开发、测试和产品就能围绕同一个边界讨论,而不是在问题出现后各自补解释。
在机制上,系统调度、有限执行时间、网络状态、任务标识、补偿队列会一起影响后台任务窗口。它们不是文档里的并列名词,而是会在一次真实操作里互相拖拽:一个环节慢了、断了、被重试了,后面的状态就会跟着变化。
落地时可以先做一个小动作:把一次同步拆成拉取配置、上传草稿、刷新索引三段,并给每段写最长可等待时间。 这件事不一定需要大改架构,但它能让问题发生时留下足够线索。很多难查的问题,缺的不是技术能力,而是最开始没有留下可追的痕迹。
这里的反面例子也要写清:最常见的误判是:本地手动触发能跑完,就以为后台也能跑完。 它通常不会在演示环境暴露,因为演示路径短、数据少、角色单一;一旦进入真实用户和长期运行,问题就会变得很难复盘。
我会用一个朴素标准判断这一段是否完成:能解释任务在启动、暂停、失败、补偿和完成时分别处于什么状态。如果团队回答这个问题时还要靠猜,说明后台任务窗口仍然停留在口头规则,没有真正进入实现和验收。
这张图只画和“先别把后台当成另一个前台”直接相关的路径,重点是让边界、状态和失败出口都能被看见。
任务标识要能追到业务对象
后台任务必须能回答自己正在处理哪一个用户、哪一批数据、哪一次业务变更。没有任务标识,日志里只剩一串开始和结束,补偿时也不知道该补哪一段。 这一步的价值不是让流程变得复杂,而是把隐含假设摊到桌面上。只要假设能被看见,开发、测试和产品就能围绕同一个边界讨论,而不是在问题出现后各自补解释。
放到“任务标识要能追到业务对象”这一节,这些机制不是背景板,系统调度、有限执行时间、网络状态、任务标识、补偿队列会一起影响后台任务窗口。它们不是文档里的并列名词,而是会在一次真实操作里互相拖拽:一个环节慢了、断了、被重试了,后面的状态就会跟着变化。
落地时可以先做一个小动作:用业务 id、任务类型和版本号组成 taskKey,写入本地持久化记录。 这件事不一定需要大改架构,但它能让问题发生时留下足够线索。很多难查的问题,缺的不是技术能力,而是最开始没有留下可追的痕迹。
这里的反面例子也要写清:只在内存里记任务状态,App 被系统结束后就失去恢复能力。 它通常不会在演示环境暴露,因为演示路径短、数据少、角色单一;一旦进入真实用户和长期运行,问题就会变得很难复盘。
对“任务标识要能追到业务对象”来说,验收标准可以更具体一点:能解释任务在启动、暂停、失败、补偿和完成时分别处于什么状态。如果团队回答这个问题时还要靠猜,说明后台任务窗口仍然停留在口头规则,没有真正进入实现和验收。
针对“任务标识要能追到业务对象”,可以把检查清单压成三项:先确认对象是谁,再确认它的生命周期在哪里结束,最后确认失败以后谁负责接手。清单越短,越能逼出真正关键的规则。
网络变化不是小概率
移动端后台最容易被网络状态打断,尤其是上传、下载和远程配置刷新。后台任务不应该假设网络稳定,而要能在切网、断网、弱网时停在可恢复位置。 这一步的价值不是让流程变得复杂,而是把隐含假设摊到桌面上。只要假设能被看见,开发、测试和产品就能围绕同一个边界讨论,而不是在问题出现后各自补解释。
放到“网络变化不是小概率”这一节,这些机制不是背景板,系统调度、有限执行时间、网络状态、任务标识、补偿队列会一起影响后台任务窗口。它们不是文档里的并列名词,而是会在一次真实操作里互相拖拽:一个环节慢了、断了、被重试了,后面的状态就会跟着变化。
落地时可以先做一个小动作:每完成一个小步骤就落进度,不要等整批完成才写成功。 这件事不一定需要大改架构,但它能让问题发生时留下足够线索。很多难查的问题,缺的不是技术能力,而是最开始没有留下可追的痕迹。
这里的反面例子也要写清:失败后从头开始,可能会造成重复上传或长时间占用后台窗口。 它通常不会在演示环境暴露,因为演示路径短、数据少、角色单一;一旦进入真实用户和长期运行,问题就会变得很难复盘。
对“网络变化不是小概率”来说,验收标准可以更具体一点:能解释任务在启动、暂停、失败、补偿和完成时分别处于什么状态。如果团队回答这个问题时还要靠猜,说明后台任务窗口仍然停留在口头规则,没有真正进入实现和验收。
这张图只画和“网络变化不是小概率”直接相关的路径,重点是让边界、状态和失败出口都能被看见。
下面这段只作为边界表达示例,不建议脱离业务直接复制:

  1. taskKey = userId + ":" + taskType + ":" + version
  2. state = pending | running | retry | done | failed

text
补偿路径要比主路径更朴素
补偿不适合再走一套复杂逻辑,它的任务是把未完成的东西安全推到下一次机会。补偿入口越简单,越容易在不同生命周期里复用。 这一步的价值不是让流程变得复杂,而是把隐含假设摊到桌面上。只要假设能被看见,开发、测试和产品就能围绕同一个边界讨论,而不是在问题出现后各自补解释。
放到“补偿路径要比主路径更朴素”这一节,这些机制不是背景板,系统调度、有限执行时间、网络状态、任务标识、补偿队列会一起影响后台任务窗口。它们不是文档里的并列名词,而是会在一次真实操作里互相拖拽:一个环节慢了、断了、被重试了,后面的状态就会跟着变化。
落地时可以先做一个小动作:把补偿任务设计成幂等动作,只处理明确处于 pending retry 状态的数据。 这件事不一定需要大改架构,但它能让问题发生时留下足够线索。很多难查的问题,缺的不是技术能力,而是最开始没有留下可追的痕迹。
这里的反面例子也要写清:补偿里继续依赖当前页面状态,会让后台任务和 UI 生命周期绑死。 它通常不会在演示环境暴露,因为演示路径短、数据少、角色单一;一旦进入真实用户和长期运行,问题就会变得很难复盘。
对“补偿路径要比主路径更朴素”来说,验收标准可以更具体一点:能解释任务在启动、暂停、失败、补偿和完成时分别处于什么状态。如果团队回答这个问题时还要靠猜,说明后台任务窗口仍然停留在口头规则,没有真正进入实现和验收。
针对“补偿路径要比主路径更朴素”,可以把检查清单压成三项:先确认对象是谁,再确认它的生命周期在哪里结束,最后确认失败以后谁负责接手。清单越短,越能逼出真正关键的规则。
这张图只画和“补偿路径要比主路径更朴素”直接相关的路径,重点是让边界、状态和失败出口都能被看见。
验收要模拟系统不配合
后台任务的验收不能只点一次按钮看成功,要主动制造中断、切网、锁屏和重启。真正可靠的后台设计,是系统不给完整时间时也能留下清楚痕迹。 这一步的价值不是让流程变得复杂,而是把隐含假设摊到桌面上。只要假设能被看见,开发、测试和产品就能围绕同一个边界讨论,而不是在问题出现后各自补解释。
放到“验收要模拟系统不配合”这一节,这些机制不是背景板,系统调度、有限执行时间、网络状态、任务标识、补偿队列会一起影响后台任务窗口。它们不是文档里的并列名词,而是会在一次真实操作里互相拖拽:一个环节慢了、断了、被重试了,后面的状态就会跟着变化。
落地时可以先做一个小动作:准备弱网、锁屏、强退、恢复四组用例,检查状态和日志。 这件事不一定需要大改架构,但它能让问题发生时留下足够线索。很多难查的问题,缺的不是技术能力,而是最开始没有留下可追的痕迹。
这里的反面例子也要写清:只看成功率,不看失败后的恢复路径,会让偶发问题长期存在。 它通常不会在演示环境暴露,因为演示路径短、数据少、角色单一;一旦进入真实用户和长期运行,问题就会变得很难复盘。
对“验收要模拟系统不配合”来说,验收标准可以更具体一点:能解释任务在启动、暂停、失败、补偿和完成时分别处于什么状态。如果团队回答这个问题时还要靠猜,说明后台任务窗口仍然停留在口头规则,没有真正进入实现和验收。
窗口耗尽时看哪些痕迹
后台任务最需要的不是“再多跑一会儿”,而是窗口耗尽前留下状态。比如同步任务已经上传了 30 条草稿,还剩 12 条未处理,这个进度必须在系统暂停前落到本地,否则下一次恢复只能靠猜。
排查时要把日志分成三层:系统是否给了执行机会,任务是否拿到了网络和权限,业务步骤是否完成了持久化。三层混在一起,只会得到一句含糊的“后台没跑”。
上线前可以做一个很小的验证:先让任务跑到一半,然后锁屏、断网、等待系统回收,再重新打开 App。只要任务能从正确位置恢复,这个后台设计才算有基本可信度。
后台任务先算窗口的验收样本
最后还要补一组验收样本。样本不需要覆盖所有情况,但要覆盖正常、异常、边界和恢复。对“后台任务先算窗口”来说,只有这四类样本都能解释,文章里的建议才不是停留在原则层面。
我会特别关注恢复样本:失败后状态是否可追,下一次是否能继续,重复执行是否安全。很多系统不是败在第一次失败,而是败在失败后的第二次处理。
最后用三个问题收住
第一,谁拥有后台任务窗口的最终解释权。没有 owner 的规则,短期靠人记,长期靠运气。
第二,失败以后系统会留下什么证据。证据不是越多越好,而是要能回答:发生在什么条件下、处理到哪一步、下一次应该从哪里恢复。
第三,这个方案适合哪些场景、不适合哪些场景。后台任务越想做得完整,越容易超出系统愿意给你的时间窗口;把任务拆小并保存进度,反而更可靠。,所以不要把一次有效实践包装成万能答案。
如果这三个问题能说清,后台任务窗口就不再只是一个技术点,而会变成团队协作中的稳定边界。后续无论换框架、换人员还是换业务规模,都能沿着这条边界继续调整。