外延服务¶
外延服务(plaita.server.services,需 server extra)是运行在流程之外的后台服务,负责监听外部触发源并把它们转成事件 publish 到 EventBus,从而唤醒挂起的流程。它们与扩展节点是"触发端"与"声明端"的配对。
ServiceManager¶
ServiceManager 统一管理所有外延服务的生命周期与任务分发:
from plaita.server.services.service_manager import ServiceManager
manager = ServiceManager(event_bus=bus)
manager.start_all_services(service_configs)
# ... 运行 ...
manager.stop_all_services()
它内置五类服务,按扩展节点产出的 service_config.type 分发任务:
| type | 服务类 | 配对节点 |
|---|---|---|
delay |
DelayService |
DelayNode |
redis_queue |
RedisQueueService |
RedisQueueNode |
kafka_queue |
KafkaQueueService |
KafkaQueueNode |
http_callback |
HttpCallbackService |
HttpCallbackNode |
approval |
ApprovalService |
ApprovalNode |
可通过 register_service_class(service_type, service_class) 注册自定义服务。
闭环¶
flowchart LR
N["扩展节点
(delay/approval/...)"] -->|挂起 + service_config| FW["FlowWorker"]
FW -->|保存 context| ES["ExecutionStorage"]
FW -->|注册订阅| EB["EventBus"]
FW -->|RPUSH| Q["plaita:{type}:queue"]
Q -->|消费| SC["外延服务"]
SC -->|到点/收到消息/审批通过| EB
EB -->|publish 事件| FW
FW -->|resume| N
- 流程跑到扩展节点 → 生成
service_config→ 挂起、存 context、订阅事件 FlowWorker把service_config当任务 RPUSH 到plaita:{type}:queue(type取节点产出的服务类型,如plaita:approval:queue)- 配对服务消费该队列并建立挂起所需的状态(审批记录 / 回调注册 / 排程),随后监听外部触发源(定时器/队列/HTTP/审批系统)
- 触发条件满足 →
publish一个correlation_id=execution_id的事件 FlowWorker收到事件 →run_distributed(resume_type="event", resume_data)恢复
派发队列必须有消费方
消费 plaita:{type}:queue 是各服务自己的职责:DelayService 与 ApprovalService 起了常驻消费线程,http_callback / redis_queue / kafka_queue 的派发队列目前没有消费方(依赖它们的扩展节点在集群档上会一直挂起)。新增挂起类节点时务必同时确认队列有人读。
各服务职责¶
DelayService¶
按 service_config.delay_ms 设定定时器,到点发布 delay_trigger 事件。适合"X 分钟后继续"的场景。
RedisQueueService / KafkaQueueService¶
阻塞监听对应队列,消息到达后包装成事件发布。适合"等某条消息到达再继续"。
HttpCallbackService¶
注册回调路径(Redis 键 plaita:http_callback:registered:{path},7 天 TTL,跨实例共享)
并在回调到达时先校验注册记录里的 auth_config、再原子认领,把回调 body 作为
event_data 发布。适合"等第三方异步通知"。
未授权请求返回 error 且不消费注册记录(认领是 GET+DEL 一体,先认领会把一次
未授权请求变成挂起执行永久失醒);认证已配置时「凭据不对」与「路径未注册」是同一条
响应,不构成 path-existence oracle(免认证注册记录是已文档化的边界);凭据载体见
扩展节点 § http_callback。
尚未暴露 HTTP 端点
唯一入口是进程内的 handle_callback_request(path, request_data, headers);
集群档拉起的 python -m plaita.server.services http_callback_service 只是空转,
且其任务队列 plaita:http_callback:queue 无消费方(见上文派发队列警告)。
ApprovalService¶
对接审批系统:通知审批人、收集决策;满足 approval_strategy(any/all/majority)后发布 approval_decision 事件,event_data 含审批结果与意见。支持自动升级(auto_escalation)。
它常驻消费 plaita:approval:queue(worker 挂起时派发的审批任务),为每个审批落一条 plaita:approval:pending:{id} 记录(7 天 TTL,跨实例共享);处理走完才出队,重放不会覆盖已落记录的审批决策。
启动入口¶
plaita.server.services.__main__ 提供命令行启动:
也可在应用代码里手动构造 ServiceManager 嵌入自己的服务进程。
多实例与负载均衡¶
ServiceManager 支持多实例部署:事件总线(redis/sqlalchemy 后端)与状态存储共享,多个 worker 实例可分担挂起流程的恢复负载,EventProcessingTracker 保证事件不重复消费。