Cloudflare D1(SQLite) · NOTIFICATION_DB(apps/server/wrangler.jsonc) · apps/server/src/routes/notifications

NOTIFICATION_DB

Berth 的「推送收发室」:记着哪台手机、替哪个账户、收哪种推送,以及每条推送有没有发出去、Expo 回执怎么说。

不存钱、不存交易:成交 / 订单 / 仓位的权威在 Hyperliquid(ADR-0083 / ADR-0174),推送只带 templateKey + 安全参数 + 不透明 ID,点开后客户端仍直连 HL;用户与登录设备归 USER_DB。

5 张表 34 个字段 2 个聚合 5 个迁移 语义层已对齐 · sha256:cd72152630b432b0

板块颜色贯穿全文

种类目录

「有哪几种推送」

push_kinds
推送种类目录

设备与订阅

「推给哪台手机、替谁收、收哪种」

push_devices
推送设备
push_subscriptions
推送订阅

投递与回执

「这条推送发没发、到没到」

push_deliveries
推送意图(投递去重)
push_delivery_tickets
逐设备投递回执

全库约定

业务流程跟着流程看表怎么变

🔔 手机开通 Bot 推送,之后收到一条

  1. App 带 users 会话开通 bot:校验种类在 push_kinds 登记过 → 一个 batch 里 upsert push_devices、撤同种旧订阅、插 push_subscriptions
    容量上限由触发器在同一条 INSERT 里裁决
  2. 服务端回一次性管理凭据,库里只存哈希;之后换 token / 撤订都只认它
  3. apps/bot 往 Queue 投意图 → 消费者按 intent_id 去重写 push_deliveries
  4. 逐台先占 push_delivery_tickets 行再调 Expo,记下 ticket;15 分钟后 cron 查回执
    DeviceNotRegistered → 设备写 disabled_at,不再投递

➕ 加一种新推送(如 social)

  1. 写一条迁移:INSERT INTO push_kinds 登记种类
    不再重建订阅 / 投递表(BERTH-1924)
  2. 代码里补 PUSH_KINDS 与发送逻辑;两边都有才可开通 / 投递

设计要点

📚 会增长的枚举用参照表0003 / 0004 为加种类各重建了一次订阅与投递表;0005 改成 push_kinds 参照表后,加种类只要一条 INSERT。
🧮 容量上限放在触发器里D1 没有交互式事务,并发开通只能在同一条 INSERT 里原子裁决;应用层的检查只为给出可读的拒绝。
🙅 宁缺不重每台设备先占回执行再调 Expo;崩溃或结果不明的那台不重发,避免重复推送。