Skip to content

fix(messaging): converge mark-read receipt on unique-index race#1617

Merged
xuyushun441-sys merged 2 commits into
mainfrom
fix/notification-receipt-unique-race
Jun 6, 2026
Merged

fix(messaging): converge mark-read receipt on unique-index race#1617
xuyushun441-sys merged 2 commits into
mainfrom
fix/notification-receipt-unique-race

Conversation

@xuyushun441-sys
Copy link
Copy Markdown
Contributor

问题

点开消息通知时服务端报 UNIQUE constraint failed: sys_notification_receipt.notification_id, sys_notification_receipt.user_id, sys_notification_receipt.channel,mark-read 失败。

根因

MessagingService.upsertReadReceipt 用先查后写(check-then-act):先 findOne(notification_id, user_id, channel) 的 receipt,落空就 insert 一条 state:'read'。这中间存在竞态窗口——只要有第二个写入者抢先建了那一行,第二个 insert 就撞上 UNIQUE(notification_id, user_id, channel) 索引:

  • 前端点击常连发两次 mark-read(点击 + 打开),两个请求都 findOne 落空、都 insert;
  • 投递时那条 best-effort 的 delivered receipt 写入是异步的,可能与点击并发或刚好在其后落库。

修复

  • upsertReadReceipt:insert 撞唯一索引时不再抛出,而是重新 findOne 把已存在的那行翻成 read(输了竞态就回退成 update)。
  • 新增跨驱动 isUniqueViolation()(SQLite / Postgres 23505 / MySQL ER_DUP_ENTRY),只对真正的唯一约束冲突回退,不吞其它错误。
  • 加回归测试 markRead survives a unique-index race on the receipt insert

验证

  • pnpm vitest run src/messaging-service.test.ts → 28 passed
  • pnpm build 通过

🤖 Generated with Claude Code

markRead's upsertReadReceipt did findOne-then-insert (check-then-act),
so a concurrent mark-read or the best-effort `delivered` write could win
the UNIQUE(notification_id, user_id, channel) index between the read and
the write, throwing `UNIQUE constraint failed` when clicking a
notification. Catch the unique violation and fall back to flipping the
now-present row to `read`. Add a cross-driver isUniqueViolation helper
(SQLite / Postgres 23505 / MySQL ER_DUP_ENTRY) and a regression test.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@vercel
Copy link
Copy Markdown

vercel Bot commented Jun 6, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
spec Ready Ready Preview, Comment Jun 6, 2026 1:43pm

Request Review

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@github-actions github-actions Bot added documentation Improvements or additions to documentation tooling labels Jun 6, 2026
@xuyushun441-sys xuyushun441-sys merged commit c70eec1 into main Jun 6, 2026
12 checks passed
@xuyushun441-sys xuyushun441-sys deleted the fix/notification-receipt-unique-race branch June 6, 2026 13:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/s tests tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants