工作流程等待会在 daprd 自己的运行时关闭时得到取消,返回 UNAVAILABLE
作者: CasperGN创建于 2026年9月28日更新于 2026年9月28日
在哪些区域中出现问题?(/area runtime) ## Dapr 的版本是哪个?在 1.18.0 中重现。相同的代码位于 master(e170747)。 ## 预期行为 当 daprd 关闭或重启(部署、pod 重启、热加载、重启运行时的配置更改)时,如果客户端在 WaitForInstanceCompletion 或 WaitForInstanceStart 中被阻塞,则调用应以状态结束,告诉客户端副程序已消失,并且应重试,例如 UNAVAILABLE。工作流仍在运行,对新的 daprd 发出的等待将成功。 ## 实际行为 等待失败,返回 CANCELLED 和 context canceled 的消息。SDK 将 CANCELLED 视为最终状态,因此调用者看到工作流的等待失败,然后正常完成。 ## 问题发生的方式 1. WaitForInstanceCompletion 进入 WatchWorkflowRuntimeStatus(actors.go#L801)。它调用 router.CallStream(#L824),并且编排器作用体将持续打开该流,直到 case <-ctx.Done(): return true, ctx.Err()(stream.go#L131-L132)。 2. CallStream 使用 r.withContext 封装其上下文(router.go#L165-L170)。它为每个正在运行的调用注册了取消函数(router.go#L454-L476)。 3. 当运行时上下文结束时,router.Run 标记了路由器关闭并调用了每个注册的取消(router.go#L105-L119)。调用者的上下文仍然存在,但等待返回 context.Canceled。 4. grpc-go 将其转换为 codes.Canceled "context canceled"。API 服务器以 GracefulStop 结束,因此客户端收到该状态而不是连接重置。 Call 和 CallReminder 都通过相同的 withContext 包装器,因此任何正在运行的作用体调用都以相同的方式受到影响。工作流等待最重要,因为它被保持打开了数分钟或数小时。 ## 重现问题的步骤 1. 以本地方式运行部署、调度程序和 daprd 1.18.0,使用内存中的作用体状态存储。 2. 注册一个单个活动睡眠 60 s 的工作流。对其进行调度,并使用 Python SDK 从调用者中调用 wait_for_workflow_completion(instance_id),没有超时。 3. 约 10 s 后,向 daprd 发送 SIGTERM。 客户端失败,返回 StatusCode.CANCELLED 和 context canceled 的详细信息,daprd 记录了 Daprd shutdown gracefully。如果没有 SIGTERM,相同的等待将返回
内容来源: dapr/dapr