我被一个批量上传脚本坑了整整一下午
说个我自己栽过的跟头。那次要把一批文件批量传上去,顺带批量调一圈接口做校验,几百条。
我让AI给我写了个脚本,看着挺利索,一个循环从头跑到尾,跑起来也确实在动。
问题出在第三百多条。网络抖了一下,某个请求超时,脚本直接报错退出。
我盯着终端那一刻是懵的——前面那两百多条到底传成功了没?哪些传了、哪些没传、哪些传一半?
脚本什么都没留下。我只能硬着头皮从头再跑一遍,心里还在打鼓:重复传的那些会不会出问题。
那一下午我真正干的活没多少,大部分时间在等它跑、看它断、再从头跑。你有没有过类似的场景,别不信,这事比想象中常见。
市场快照里那个90多个模块的发版,其实是同一个病
最近看到一个帖子,有人给框架发版总卡在Maven Central那一步:一次要推90多个工件、加起来超过300MB,走老路径在这个体积下反复超时,用他自己的话说就是「要么手动补发、要么整段重来,非常折腾」。
我看到「整段重来」四个字就笑了,这不就是我那个下午吗。他的解法是自己写了个插件,把流程收敛成一条命令,还专门做了轮询部署状态。
注意「轮询状态」这个动作——它其实在偷偷解决一个更本质的问题:让这个长任务知道自己跑到哪了。
两件看起来八竿子打不着的事,批量传文件和多模块发版,骨子里是同一个病:长任务一次性阻塞跑完,中间不记进度,断了没法接着来。
被忽略的判断:AI默认写的长任务,几乎都不可恢复
这是我想点破的一个点。你让AI帮你写批量脚本、写长流程,它给你的默认形态大概率是这样:一个大循环,从第一条跑到最后一条,中间不落盘、不记状态、出错就抛异常退出。
不是AI偷懒,是你没要求,它也没义务替你想「断了怎么办」。对一个几十条的小任务,这么写没毛病。
可一旦条数上去、单条耗时变长、中间还要走网络,这种一次性脚本就成了定时炸弹。跑得越久,越接近终点,断在那儿的损失越大。
跑到80%断一次,前面80%白干,这种体验谁顶得住。
我现在的习惯是,凡是预计要跑超过几分钟、或者中间有网络请求的任务,都把它当成「随时可能断」来设计,而不是「它应该能跑完」。这个心态一换,写法就完全不一样了。
对交付型工具,用户要的从来不是快
这里有个反常识的地方,我做过几单交付才慢慢想明白。
客户、或者说用你工具的人,嘴上可能说希望快点,但真正让他们崩溃的从来不是慢,是「不确定」。跑了十分钟突然断了,他不知道是不是白跑了、不知道要不要重来、不知道重来会不会把已经成功的搞乱。
这种抓瞎的感觉,比多等五分钟难受一百倍。
所以交付型工具真正值钱的两件事是:断了不丢,和能看到跑到哪了。一个让人敢用,一个让人安心。
你把这两点做到了,哪怕脚本本身跑得不算快,用的人也会觉得这东西靠谱。反过来,跑得飞快但一断就玄学,没人敢拿它干正经活。
这就是商业判断和技术判断拉开差距的地方。技术上你想优化速度,生意上你该先优化「可恢复」。
落地思路:把进度落成一张状态表,当唯一真相
具体怎么做,我说个在VicroCode上能直接走通的路子,不复杂。
核心就一句话:别让进度只活在内存里,把它落到一张表。我习惯用SQLite编辑器先把这张状态表的结构定出来,一行代表一个要处理的单元,比如一个文件、一个工件、一条接口调用。
关键是给每行一个状态字段:待处理、处理中、已完成、失败。再带个时间戳和失败原因。
任务跑起来的逻辑就变了。每处理一条,先更新这张表;下次启动,先读表,凡是标成「已完成」的直接跳过,只挑没完成的接着干。
这就是断点续跑的本体——它不是什么高深技术,就是「把干到哪了记下来,下次从记录往后接」。脚本本身可以用Python在线运行直接验证这套逻辑,先拿十几条小数据跑通「断了再启动能不能正确跳过」,再上真实量。
这里有个容易踩的坑:更新状态和干活这两步的顺序。我的做法是,干完一条马上标完成;如果担心干一半崩在中间,就先标「处理中」,确认成功再标「已完成」,这样重启时「处理中」的那条你就知道要重新确认一下。
幂等就是这么一点点抠出来的,不是一蹴而就。
再把状态露成一个能打开看的页面
光有表还不够,表是给你自己看的。交付给别人用的时候,得让对方也能看到进度,这才解决「不确定」那个痛点。
我会在状态表之上套一个简单的页面,就读那张表,跑了多少、成了多少、断在哪条、为什么断,一目了然。这个页面不用多花哨,关键是让人随时能打开看一眼,心里有底。
做好之后用Web应用托管发出去,对方点开链接就能看,不用你在旁边盯着截图汇报。
到这一步,一个原本「跑到一半就抓瞎」的脚本,就变成了「断了能续、进度能看」的交付件。差别不在代码量,在你有没有把「随时会断」当成默认前提。
一个今天就能做的小动作
不用改什么大东西。下次你让AI写长任务或者批量脚本之前,先加一句要求:把「已经完成的步骤记到哪里、下次启动怎么跳过已完成的」写清楚。
就这一句,能逼着它从「一次性跑完」切换到「可恢复」的思路。你会发现它给出的代码结构立刻不一样了。
等你哪天真跑到80%断了一次,还能从断点接着跑的时候,就知道这句话值多少了。