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

vercelBot commented Jun 6, 2026

Copy link
Copy Markdown

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

ProjectDeploymentActionsUpdated (UTC)
specReadyReadyPreview, CommentJun 6, 2026 1:43pm

Request Review

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@github-actionsgithub-actionsBot added documentation Improvements or additions to documentation tooling labels Jun 6, 2026
@xuyushun441-sys
xuyushun441-sys merged commit c70eec1 into mainJun 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 freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationsize/steststooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@xuyushun441-sys@os-zhuang