All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 8m8s
5.4 KiB
5.4 KiB
worker-role-management Specification
Purpose
TBD - created by archiving change split-worker-roles. Update Purpose after archive.
Requirements
Requirement: Worker 角色配置
系统 SHALL 支持 all、leader、consumer 三种 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;只有 all 和 leader SHALL 启动主动调度与初始化模块。
共享模块:
- Redis 客户端
- PostgreSQL 连接
- Storage 服务(可选)
- Gateway 客户端(可选)
- Asynq Client
BootstrapWorker- Asynq Worker Server
PollingConfigManagerPollingQueueManagerPollingBasePollingLifecycleService- TaskHandler 及全部任务 Handler 注册
单例模块:
PollingInitializerPollingScheduler- 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_initializer、polling_scheduler、asynq_scheduler
Scenario: leader 日志显示启用单例模块
- WHEN
worker.role=leader - THEN 启动日志显示已启用
queue_server、polling_initializer、polling_scheduler、asynq_scheduler
Requirement: 按启动状态优雅关闭
系统 SHALL 只关闭当前角色实际启动过的后台模块,避免 consumer 对未启动模块执行 Stop 或 Shutdown。
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 固定只有一个 leader 或 all 实例承担主动调度职责,横向扩容 SHALL 优先增加 consumer。
Scenario: 新增 consumer 不复制主动调度
- WHEN 生产已有一个
leader,再新增一个consumer - THEN 定时任务仍只由
leader主动提交 - AND 轮询全量初始化仍只由
leader执行 - AND
consumer只从 Asynq 队列消费已有任务
Scenario: 回滚到单实例兼容模式
- WHEN 多实例部署出现问题并停止所有
consumer - THEN 保留一个
leader可继续运行完整 Worker 功能 - AND 必要时可将唯一实例配置切回
all恢复兼容模式