Skip to main content

Documentation Index

Fetch the complete documentation index at: https://tech.illasoft.com/llms.txt

Use this file to discover all available pages before exploring further.

概述

kira-queue 是一个轻量 PGMQ worker,消费 Supabase Postgres 的 pgmq_public.* 队列,执行异步邮件发送和账户删除工作。单文件 176 行(kira-queue/index.ts),三条 worker 并发运行。

部署形态

平台Fly.io,单机
入口bun run dev
无对外端口(纯后台 worker)
观测Better Stack heartbeat

订阅的队列

队列消息格式处理动作
pgmq_public.daily_email{ userId }POST {API_URL}/mail/daily
pgmq_public.account_deletion{ userId }readDELETE /user?password=...&userId=... → POST /mail/account-deletionarchive
pgmq_public.account_deletion_reminder{ userId }pop → POST /mail/account-deletion
  • 轮询频率:30 秒
  • Daily + Reminder 用 pgmq.pop(at-most-once)
  • Account Deletion 用 pgmq.read + 成功后显式 pgmq.archive(at-least-once,避免因 /user DELETE 失败丢消息)

环境变量

SUPABASE_URL       # Supabase 项目 URL
SUPABASE_KEY       # service_role key(能走 pgmq_public RPC)
API_URL            # kira-be HTTP 地址(默认 http://localhost:8080)
HEARTBEAT_URL      # Better Stack heartbeat URL(每 30s ping 一次)

端到端流程:账户删除

[用户点击"删除账号"]

kira-be  POST /support/delete-account
   ├─ 记录删除原因 (support_delete_reasons)
   ├─ pgmq.send(account_deletion, {userId}, sleep=30*86400)      ← 30 天后可取
   ├─ pgmq.send(account_deletion_reminder, {userId}, sleep=27*86400) ← 27 天后提醒
   └─ POST /mail/account-deletion (scheduled 邮件立即发送)

[27 天后]
kira-queue  pgmq.pop(account_deletion_reminder)
   └─ POST /mail/account-deletion (reminder 邮件)

[30 天后]
kira-queue  pgmq.read(account_deletion)
   ├─ 查询 auth.users 取邮箱 + user_profiles 取语言
   ├─ DELETE /user?password=xK9m...&userId=xxx
   │    ├─ Stripe customers 删除(US + SG)
   │    ├─ PostHog user 删除
   │    ├─ Supabase Storage 用户文件清理(async)
   │    └─ auth.users + user_profiles 行删除
   ├─ POST /mail/account-deletion (deleted 邮件)
   └─ pgmq.archive(account_deletion, msgId)
取消删除:用户在 30 天内可调用 /support/cancel-delete-account,它会 pgmq.delete 对应两条消息,并发送 cancelled 邮件。

代码结构

kira-queue/
├── index.ts         # 单文件入口,三个 async worker
├── fly.toml
├── Dockerfile
└── package.json
三个 worker 通过 Promise.all([dailyMailQueue(), accountDeletionQueue(), accountDeletionReminderQueue()]) 并发启动。任一抛出未捕获错误会导致整个进程退出(Fly 会重启)。

Caveat

硬编码密码

DELETE /user 的 password 在 kira-queue/index.ts:56 硬编码为 xK9mP2vL7nQ4wR8s。kira-be 侧也是相同的硬编码比对。建议后续改为环境变量,两端同步替换。

单机运行约束

account_deletion 使用 pgmq.read(非 exclusive),如果部署多实例可能同时拉到同一条消息 → 双重删除。Fly.io 配置固定为单机(min_machines_running = 1,不能扩 replicas)。

失败重试

HTTP 调用 kira-be 失败时,pgmq.read 的消息没有 archive,默认 visibility timeout 后会被重新取出。如果 kira-be 持续不可用,消息会累积。

相关文档