Skip to content

test(jobs): 用真实 Redis 双实例实测「一次 tick 只执行一次」 - #43

Merged
worable233 merged 1 commit into
mainfrom
test/jobs-redis-cluster
Oct 25, 2026
Merged

worable233 merged 1 commit into
mainfrom
test/jobs-redis-cluster

Conversation

@worable233

Copy link
Copy Markdown
Owner

对标 #12.5 验收门槛里的最后一条:「集群双实例只执行一次」。

在此之前这条只有推论 —— bullmq-backend.ts 的注释写着「BullMQ 保证一个 job 只被一个 worker 取走,upsertJobScheduler 每个 id 只有一份调度」。注释不是证据。

新增 3 例(真实 Redis,两个独立 backend = 两个副本)

  1. 两个副本声明同一个调度 → Redis 里只有一份。否则每个副本按自己的节奏各发一遍任务,用户会收到双份通知
  2. 两个副本同时运行 → 一次 tick 只执行一次。除了总数上限,还断言任意两次执行的间隔 > 400ms(间隔 1s 的调度不会出现「几乎同时两次」,那正是双取的特征)。同时断言执行次数 ≥ 2 —— 防的是「测试因为根本没跑而通过」
  3. 同一个 jobId 从两个副本入队 → 只执行一次

为什么需要独立 db

用例清理用 obliterate,会删掉整个队列。所以:

  • 只在 TEST_REDIS_URL 指向 db ≥ 1 时运行(本机验证过 …/6379 与 …/6379/0 都会被跳过,不会误清开发库)
  • CI 里加 TEST_REDIS_URL: redis://127.0.0.1:6379/9(redis service 本来就在)
  • 不设环境变量时整组跳过,不给本地开发引入常驻 Redis 依赖

验证

本机对着 sp-redis 跑 3 例全绿(4.9s);不设 / 设 db 0 两种写法均 3 skipped;eslint 干净。

对标 #12.5 验收门槛里的最后一条:「集群双实例只执行一次」。

在此之前这条只有**推论** —— `bullmq-backend.ts` 的注释写着「BullMQ 保证一个 job
只被一个 worker 取走,`upsertJobScheduler` 每个 id 只有一份调度」。注释不是证据。

新增 `apps/api/tests/integration/jobs-redis-cluster.test.ts`(3 例,真实 Redis):

1. **两个副本声明同一个调度 → Redis 里只有一份**。否则每个副本按自己的节奏各发
   一遍任务,用户会收到双份通知。
2. **两个副本同时运行 → 一次 tick 只执行一次**。除了总数上限,还断言任意两次执行
   的间隔 > 400ms(间隔 1s 的调度不会出现「几乎同时两次」,那正是双取的特征)。
   同时断言执行次数 ≥ 2 —— 防的是「测试因为根本没跑而通过」。
3. **同一个 `jobId` 从两个副本入队 → 只执行一次**。

## 为什么需要独立 db

用例清理用 `obliterate`,会删掉整个队列。所以:

- 只在 `TEST_REDIS_URL` 指向 **db ≥ 1** 时运行(本机验证过 `…/6379` 与 `…/6379/0`
  都会被跳过,不会误清开发库);
- CI 里加 `TEST_REDIS_URL: redis://127.0.0.1:6379/9`(redis service 本来就在)。

不设环境变量时整组跳过,不给本地开发引入常驻 Redis 依赖。

验证:本机对着 `sp-redis` 跑 3 例全绿(4.9s);不设 / 设 db 0 两种写法均 3 skipped;eslint 干净。
@worable233
worable233 force-pushed the test/jobs-redis-cluster branch from e340de6 to 02ac9b6 Compare October 25, 2026 10:43
@worable233
worable233 merged commit dccb9de into main Oct 25, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant