Files
junhong_cmp_fiber/openspec/specs/worker-role-management/spec.md
huang 3a2e3f2571
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 8m8s
浅浅升级一下
2026-05-06 14:41:14 +08:00

5.4 KiB
Raw Blame History

worker-role-management Specification

Purpose

TBD - created by archiving change split-worker-roles. Update Purpose after archive.

Requirements

Requirement: Worker 角色配置

系统 SHALL 支持 allleaderconsumer 三种 Worker 运行角色,并在启动时根据配置决定当前进程职责。角色值 MUST 使用小写英文字符串,非法角色 MUST 使配置加载失败并返回明确错误。

Scenario: 默认兼容模式

  • WHEN 未设置 JUNHONG_WORKER_ROLE
  • THEN Worker 使用默认角色 all
  • AND 启动行为与变更前单实例 worker 保持一致

Scenario: 非法角色启动失败

  • WHEN 设置 JUNHONG_WORKER_ROLE=scheduler
  • THEN config.Load() 返回配置校验错误
  • AND Worker 不进入 Redis、PostgreSQL 或 Asynq 启动流程

Scenario: 实例名称可为空

  • WHEN 未设置 JUNHONG_WORKER_INSTANCE_NAME
  • THEN Worker 可以正常启动
  • AND 启动日志中的实例名称为空或显示默认占位值

Requirement: 按角色启停 Worker 模块

系统 SHALL 将 Worker 启动流程拆分为共享依赖初始化和角色模块启停两部分。所有角色 MUST 启动 Asynq Worker Server只有 allleader SHALL 启动主动调度与初始化模块。

共享模块

  • Redis 客户端
  • PostgreSQL 连接
  • Storage 服务(可选)
  • Gateway 客户端(可选)
  • Asynq Client
  • BootstrapWorker
  • Asynq Worker Server
  • PollingConfigManager
  • PollingQueueManager
  • PollingBase
  • PollingLifecycleService
  • TaskHandler 及全部任务 Handler 注册

单例模块

  • PollingInitializer
  • PollingScheduler
  • Asynq Scheduler

Scenario: all 角色启动全部模块

  • WHEN worker.role=all
  • THEN Worker 启动 Asynq Worker Server
  • AND 启动 PollingInitializer
  • AND 启动 PollingScheduler
  • AND 启动 Asynq Scheduler

Scenario: leader 角色启动全部模块

  • WHEN worker.role=leader
  • THEN Worker 启动 Asynq Worker Server
  • AND 启动 PollingInitializer
  • AND 启动 PollingScheduler
  • AND 启动 Asynq Scheduler
  • AND 日志表达该实例承担单例主动调度职责

Scenario: consumer 角色只启动任务消费模块

  • WHEN worker.role=consumer
  • THEN Worker 启动 Asynq Worker Server
  • AND 注册全部任务 Handler
  • AND 不启动 PollingInitializer
  • AND 不启动 PollingScheduler
  • AND 不启动 Asynq Scheduler

Requirement: consumer 保留轮询任务运行依赖

consumer 角色虽然不主动调度,但系统 SHALL 保留轮询任务 Handler 所需依赖,使其可以正常消费 Leader 投递的轮询任务并在任务完成后重新入队。

Scenario: consumer 消费轮询任务后可重新入队

  • WHEN consumer 实例消费 TaskTypePollingCarddata 任务
  • THEN Handler 可通过 PollingBase 读取轮询配置和 Redis 并发控制
  • AND Handler 可通过 PollingQueueManager 将卡重新写回分片 Sorted Set

Scenario: consumer 可处理导入任务的轮询生命周期回调

  • WHEN consumer 实例消费 IoT 卡导入任务并创建新卡
  • THEN 导入任务可通过 PollingLifecycleService 将新卡按配置加入轮询分片队列
  • AND 该操作不依赖本实例启动 PollingScheduler

Requirement: Worker 启动日志

系统 SHALL 在 Worker 启动时输出当前角色、实例名称、启用模块和禁用模块,日志消息 MUST 使用中文,便于部署后通过日志确认实际运行职责。

Scenario: consumer 日志显示禁用单例模块

  • WHEN worker.role=consumer
  • THEN 启动日志包含 Worker 角色
  • AND 启动日志包含 实例名称
  • AND 启动日志显示已禁用 polling_initializerpolling_schedulerasynq_scheduler

Scenario: leader 日志显示启用单例模块

  • WHEN worker.role=leader
  • THEN 启动日志显示已启用 queue_serverpolling_initializerpolling_schedulerasynq_scheduler

Requirement: 按启动状态优雅关闭

系统 SHALL 只关闭当前角色实际启动过的后台模块,避免 consumer 对未启动模块执行 StopShutdown

Scenario: consumer 关闭不访问未启动调度器

  • WHEN consumer 收到退出信号
  • THEN Worker 关闭 Asynq Worker Server
  • AND 不调用未启动的 PollingScheduler.Stop
  • AND 不调用未启动的 Asynq Scheduler Shutdown

Scenario: leader 关闭全部已启动模块

  • WHEN leader 收到退出信号
  • THEN Worker 关闭 Asynq Scheduler
  • AND 停止 PollingScheduler
  • AND 优雅关闭 Asynq Worker Server

Requirement: 多实例部署语义

系统 SHALL 支持“1 个 leader + N 个 consumer”的部署形态。部署时 SHOULD 固定只有一个 leaderall 实例承担主动调度职责,横向扩容 SHALL 优先增加 consumer

Scenario: 新增 consumer 不复制主动调度

  • WHEN 生产已有一个 leader,再新增一个 consumer
  • THEN 定时任务仍只由 leader 主动提交
  • AND 轮询全量初始化仍只由 leader 执行
  • AND consumer 只从 Asynq 队列消费已有任务

Scenario: 回滚到单实例兼容模式

  • WHEN 多实例部署出现问题并停止所有 consumer
  • THEN 保留一个 leader 可继续运行完整 Worker 功能
  • AND 必要时可将唯一实例配置切回 all 恢复兼容模式