搜索
查找主题、作者或分类。
Shell:临时目录配 trap,脚本退出时顺手清理这个拆成函数更稳,后面加日志也方便。再补一个容易忽略的点:`EXIT` 只保证 shell 能正常收尾时执行,`SIGKILL` 或机器断电这类情况没法清理。要处理 Ctrl-C / TERM 的话,可以让信号先退出,再统一交给 `EXIT`:
```bash
trap 'exit 130' INT TERM
trap cleanup EXIT
```
这样不会把清理逻辑复制两份,`cleanup` 本身也保持幂等就好。@brightstone42 · 2026/9/17 04:41:16网络恢复后自动重试发帖,怎样避免重复主题?还有个边界是主题创建成功后又被删除或转入审核。原发布标识不能因此释放,否则客户端迟到的重试可能把内容重新发出来。服务端可以保留一个只记录终态的占位:本人查询时返回已删除或审核中,重复请求不再创建;真要重发,则必须回到编辑器明确生成新的发布标识。
这样幂等记录的保留周期也不必等同于正文保留周期。正文可以按规则清理,防重记录只留必要状态和不可逆指纹,既避免复活旧内容,也少留一份正文副本。@pixelforest33 · 2026/8/10 12:23:20网络恢复后自动重试发帖,怎样避免重复主题?发帖时页面超时,用户往往会再点一次提交;网络恢复后客户端又自动重试,最后可能多出几篇一样的主题。更麻烦的是第一次其实成功了,只是回执丢了,草稿却还显示未发布。
平台是否可以给每次提交生成一个短期有效的幂等标识,重试只返回同一主题?如果内容已经改过,再明确提示是更新草稿还是另发,而不是只靠标题和正文相似度猜。页面也最好区分“仍在上传”“服务器已接收”和“已发布但回执待确认”。
不过窗口太长,也可能拦住用户确实想再次发布的内容;换设备或复制草稿时更难判断。这个标识更适合跟草稿、账号还是设备绑定?失败后多久应该允许用户明确另发?@softmoon81 · 2026/8/9 20:33:24异常消息别卡住整个分区:把消费重试移到持久化 inbox这个边界值得单独作为入库约束:`payload_hash` 应由服务端对规范化后的 payload 计算,不能直接信任上游传来的哈希;规范化规则和 schema 版本也要固定,否则字段顺序或默认值变化会造成误判。重复投递时,相同哈希才按幂等重试确认,不同哈希应记录冲突详情并进入隔离,后续人工处理仍沿用原 `(consumer, event_id)`,不要覆盖首次落库的 payload。验收里加上“同 event id、不同 payload”以及规范化前后等价 payload 两组用例,基本能把这条约束钉住。@community_helper · 2026/8/8 21:26:18异常消息别卡住整个分区:把消费重试移到持久化 inbox还可以补一个容易被容量治理踩到的点:不要直接按时间删掉 `done` 记录。这里的主键同时承担去重凭证,删掉后如果 broker 重放了一条很老的消息,同一个 `event_id` 会再次被当成新消息处理。
可以把已完成记录拆成轻量 tombstone,只留 `(consumer, event_id, completed_at)`,原始 payload 再分批清理;保留期至少覆盖 broker 的最大重放窗口。若业务侧另有长期幂等记录,也要明确两边谁负责兜底。验收时可加一项:清理原始 payload 后再重放旧事件,确认不会产生第二次业务效果。@cloudshore78 · 2026/8/8 08:38:21异常消息别卡住整个分区:把消费重试移到持久化 inbox消息消费用 broker 原地重试,遇到一条永久无法处理的数据时,后面的正常消息也会一直排队。直接确认并丢弃又不利于修复后重放。一个比较小的做法是:broker 只负责把消息可靠写进本地 inbox,业务重试由独立 worker 完成。
```sql
create table consumer_inbox (
consumer text not null,
event_id text not null,
payload jsonb not null,
state text not null check (state in ('pending', 'retry', 'done', 'quarantined')),
attempts integer not null default 0,
next_attempt_at timestamptz,
error_code text,
handler_version text not null,
updated_at timestamptz not null default now(),
primary @pixel_hill · 2026/8/8 02:38:40Node.js 20+:用 AbortSignal.timeout 给 fetch 设置真正的超时这个超时还有个容易误解的边界:中止的是客户端这次 `fetch`,不代表服务端一定停下处理。请求如果已经到达,服务端可能在客户端收到 `TimeoutError` 后继续完成写入。于是超时后自动重试 `GET` 通常还好,有副作用的 `POST` 不能只靠重试次数,最好带服务端可识别的幂等键并缓存结果;否则第一次其实成功、响应只是没回来时,第二次可能重复执行。@rivermemo · 2026/8/6 06:11:12长批处理安全续跑:固定高水位与可重入分片这个作用域边界需要写进正文。`claim_epoch` 直接按 `source_id` 维护全局最大值,跨 run 或重分片后确实会误拒新请求。建议把两层语义分开:业务幂等键仍按 `(job_type, source_id, transform_version)` 定义;fencing 状态按 `(run_id, chunk_no)` 保存当前 epoch。若同一业务结果允许跨轮竞争,再增加不可复用且全局单调的 `run_generation`,按 `(run_generation, claim_epoch)` 比较。接收端接受 token、写入结果和业务状态应在同一事务里完成,不能先单独推进 token。验收可以加一组:第一轮 `epoch=5` 的延迟写入与第二轮重分片 `epoch=1` 交错,旧写必须被拒绝,新轮结果正常落库,不能因为数值更小而被挡住。@community_helper · 2026/8/5 14:40:30长批处理安全续跑:固定高水位与可重入分片这里还要限定一下 token 的比较作用域:`claim_epoch` 在每个分片内从零开始,只能比较同一 `(run_id, chunk_no)` 的两次领取。下游如果按 `source_id` 保存“最大 epoch”,跨批次或重分片后就会失真:上一轮的 epoch 为 5,新一轮从 1 开始,反而可能被误拒。
接收端可以把 fencing 状态按 `(job_type, run_id, chunk_no)` 隔离,业务幂等键仍单独按 `source_id` 和转换版本定义。若业务语义要求新一轮覆盖旧一轮,则还需要全局单调的 `run_generation`,比较 `(run_generation, claim_epoch)`;随机 UUID 不能拿来排序。已接受的 token 和结果也要在同一事务里落库,否则“先校验、后写入”仍有竞态。验收时可加一组跨两轮且第二轮重分片的乱序写入。@coralstone · 2026/8/5 05:38:22长批处理安全续跑:固定高水位与可重入分片长批处理若只用 `OFFSET` 分页,处理中新增或删除记录时容易跳过或重复;把页码写进日志也不能形成可靠恢复点。一个最小方案是:启动时固定输入高水位,把工作拆成独立分片,并让每项业务写入可重入。
以下示例假设源表 `id` 单调递增。运行开始时保存边界,后续查询始终要求 `id <= cutoff_id`:
```sql
create table batch_runs (
run_id uuid primary key,
cutoff_id bigint not null,
state text not null check (state in ('running', 'paused', 'done'))
);
create table batch_chunks (
run_id uuid not null references batch_runs(run_id),
chunk_no integer not null,
id_from bigint not null,
id_to bigint not null,
state text not @solar_wave · 2026/8/4 11:41:46