<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>工作流协议 on Dapr 文档库</title><link>https://docs.dapr.io/zh-hans/contributing/protocol-reference/workflow-protocol/</link><description>Recent content in 工作流协议 on Dapr 文档库</description><generator>Hugo</generator><language>zh-hans</language><atom:link href="https://docs.dapr.io/zh-hans/contributing/protocol-reference/workflow-protocol/index.xml" rel="self" type="application/rss+xml"/><item><title>Workflow 协议 - 管理 API</title><link>https://docs.dapr.io/zh-hans/contributing/protocol-reference/workflow-protocol/workflow-protocol-management-api/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://docs.dapr.io/zh-hans/contributing/protocol-reference/workflow-protocol/workflow-protocol-management-api/</guid><description>&lt;h1 id="workflow-管理-api">Workflow 管理 API&lt;/h1>
&lt;p>Workflow 管理 API 允许 Dapr 客户端控制 workflow 实例的生命周期。这些 API 通过标准 Dapr gRPC 端点公开，通常通过 SDK 提供。&lt;/p>
&lt;h2 id="grpc-服务定义">gRPC 服务定义&lt;/h2>
&lt;p>管理 API 是 &lt;code>dapr.proto.runtime.v1&lt;/code> 中 &lt;code>Dapr&lt;/code> 服务的一部分。虽然可能存在多个版本（Alpha1、Beta1），以下描述的是当前的实现逻辑。&lt;/p>
&lt;h3 id="startworkflow">StartWorkflow&lt;/h3>
&lt;p>启动一个新的 workflow 实例。&lt;/p>
&lt;p>&lt;strong>请求（&lt;code>StartWorkflowRequest&lt;/code>）：&lt;/strong>&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th style="text-align: left">字段&lt;/th>
 &lt;th style="text-align: left">类型&lt;/th>
 &lt;th style="text-align: left">描述&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td style="text-align: left">&lt;code>instance_id&lt;/code>&lt;/td>
 &lt;td style="text-align: left">&lt;code>string&lt;/code>&lt;/td>
 &lt;td style="text-align: left">可选。workflow 实例的唯一标识符。如果未提供，Dapr 将生成一个随机的 UUID。&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td style="text-align: left">&lt;code>workflow_component&lt;/code>&lt;/td>
 &lt;td style="text-align: left">&lt;code>string&lt;/code>&lt;/td>
 &lt;td style="text-align: left">要使用的 workflow 组件的名称。目前，Dapr 使用内置引擎。&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td style="text-align: left">&lt;code>workflow_name&lt;/code>&lt;/td>
 &lt;td style="text-align: left">&lt;code>string&lt;/code>&lt;/td>
 &lt;td style="text-align: left">要执行的 workflow 定义的名称。&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td style="text-align: left">&lt;code>options&lt;/code>&lt;/td>
 &lt;td style="text-align: left">&lt;code>map&amp;lt;string, string&amp;gt;&lt;/code>&lt;/td>
 &lt;td style="text-align: left">可选。组件特定选项。&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td style="text-align: left">&lt;code>input&lt;/code>&lt;/td>
 &lt;td style="text-align: left">&lt;code>bytes&lt;/code>&lt;/td>
 &lt;td style="text-align: left">可选。workflow 实例的输入数据，通常是 JSON 序列化字符串。&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>&lt;strong>响应（&lt;code>StartWorkflowResponse&lt;/code>）：&lt;/strong>&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th style="text-align: left">字段&lt;/th>
 &lt;th style="text-align: left">类型&lt;/th>
 &lt;th style="text-align: left">描述&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td style="text-align: left">&lt;code>instance_id&lt;/code>&lt;/td>
 &lt;td style="text-align: left">&lt;code>string&lt;/code>&lt;/td>
 &lt;td style="text-align: left">已启动的 workflow 实例的 ID。&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h3 id="getworkflow">GetWorkflow&lt;/h3>
&lt;p>检索 workflow 实例的当前状态和元数据。&lt;/p></description></item><item><title>Workflow Protocol - Execution API</title><link>https://docs.dapr.io/zh-hans/contributing/protocol-reference/workflow-protocol/workflow-protocol-execution-api/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://docs.dapr.io/zh-hans/contributing/protocol-reference/workflow-protocol/workflow-protocol-execution-api/</guid><description>&lt;h1 id="workflow-execution-api-task-hub-protocol">Workflow Execution API (Task Hub Protocol)&lt;/h1>
&lt;p>Workflow Execution API 是一个低级 gRPC 协议，Dapr Workflow SDK 通过它充当&amp;quot;Worker&amp;quot;。SDK 通过此协议连接 Dapr sidecar 以轮询任务并报告完成状态。&lt;/p>
&lt;p>该服务名为 &lt;code>TaskHubSidecarService&lt;/code>。&lt;/p>
&lt;h3 id="service-definition-grpc">Service Definition (gRPC)&lt;/h3>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-protobuf" data-lang="protobuf">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#204a87;font-weight:bold">service&lt;/span> &lt;span style="color:#000">TaskHubSidecarService&lt;/span> &lt;span style="color:#000;font-weight:bold">{&lt;/span>&lt;span style="color:#a40000">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a40000">&lt;/span> &lt;span style="color:#204a87;font-weight:bold">rpc&lt;/span> &lt;span style="color:#000">GetWorkItems&lt;/span>&lt;span style="color:#000;font-weight:bold">(&lt;/span>&lt;span style="color:#000">GetWorkItemsRequest&lt;/span>&lt;span style="color:#000;font-weight:bold">)&lt;/span> &lt;span style="color:#204a87;font-weight:bold">returns&lt;/span> &lt;span style="color:#000;font-weight:bold">(&lt;/span>&lt;span style="color:#000">stream&lt;/span> &lt;span style="color:#000">WorkItem&lt;/span>&lt;span style="color:#000;font-weight:bold">);&lt;/span>&lt;span style="color:#a40000">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a40000">&lt;/span> &lt;span style="color:#204a87;font-weight:bold">rpc&lt;/span> &lt;span style="color:#000">CompleteOrchestratorTask&lt;/span>&lt;span style="color:#000;font-weight:bold">(&lt;/span>&lt;span style="color:#000">OrchestratorResponse&lt;/span>&lt;span style="color:#000;font-weight:bold">)&lt;/span> &lt;span style="color:#204a87;font-weight:bold">returns&lt;/span> &lt;span style="color:#000;font-weight:bold">(&lt;/span>&lt;span style="color:#000">CompleteBatchResponse&lt;/span>&lt;span style="color:#000;font-weight:bold">);&lt;/span>&lt;span style="color:#a40000">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a40000">&lt;/span> &lt;span style="color:#204a87;font-weight:bold">rpc&lt;/span> &lt;span style="color:#000">CompleteActivityTask&lt;/span>&lt;span style="color:#000;font-weight:bold">(&lt;/span>&lt;span style="color:#000">ActivityResponse&lt;/span>&lt;span style="color:#000;font-weight:bold">)&lt;/span> &lt;span style="color:#204a87;font-weight:bold">returns&lt;/span> &lt;span style="color:#000;font-weight:bold">(&lt;/span>&lt;span style="color:#000">CompleteBatchResponse&lt;/span>&lt;span style="color:#000;font-weight:bold">);&lt;/span>&lt;span style="color:#a40000">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a40000">&lt;/span> &lt;span style="color:#8f5902;font-style:italic">// ... other management methods
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8f5902;font-style:italic">&lt;/span>&lt;span style="color:#000;font-weight:bold">}&lt;/span>&lt;span style="color:#a40000">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="worker-生命周期">Worker 生命周期&lt;/h2>
&lt;ol>
&lt;li>&lt;strong>连接&lt;/strong>：SDK 打开一个到 &lt;code>GetWorkItems&lt;/code> 的长连接双向流。&lt;/li>
&lt;li>&lt;strong>轮询&lt;/strong>：SDK 从流中接收 &lt;code>WorkItem&lt;/code> 消息。&lt;/li>
&lt;li>&lt;strong>执行&lt;/strong>：
&lt;ul>
&lt;li>如果工作项是 &lt;strong>Orchestration&lt;/strong>，SDK 获取并重放历史事件以确定下一步操作。&lt;/li>
&lt;li>如果工作项是 &lt;strong>Activity&lt;/strong>，SDK 执行活动逻辑。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;strong>完成&lt;/strong>：
&lt;ul>
&lt;li>对于 Orchestration，SDK 调用 &lt;code>CompleteOrchestratorTask&lt;/code> 并附带要执行的操作列表。&lt;/li>
&lt;li>对于 Activity，SDK 调用 &lt;code>CompleteActivityTask&lt;/code> 并附带结果或失败信息。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ol>
&lt;h2 id="grpc-service-taskhubsidecarservice">gRPC Service: &lt;code>TaskHubSidecarService&lt;/code>&lt;/h2>
&lt;h3 id="getworkitems">GetWorkItems&lt;/h3>
&lt;p>打开流以接收 orchestration 和 activity 的工作项。&lt;/p></description></item><item><title>Workflow Protocol - Orchestration Lifecycle</title><link>https://docs.dapr.io/zh-hans/contributing/protocol-reference/workflow-protocol/workflow-protocol-orchestration-lifecycle/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://docs.dapr.io/zh-hans/contributing/protocol-reference/workflow-protocol/workflow-protocol-orchestration-lifecycle/</guid><description>&lt;h1 id="编排生命周期">编排生命周期&lt;/h1>
&lt;p>本文档从协议层面描述编排的生命周期，特别是 Dapr 引擎与 SDK 如何交互以可靠地执行工作流逻辑。&lt;/p>
&lt;h2 id="基于重放的执行">基于重放的执行&lt;/h2>
&lt;p>Dapr Workflow 使用 &lt;strong>事件溯源&lt;/strong> 和 &lt;strong>重放&lt;/strong> 来维护状态。Dapr 不是保存整个 worker 进程的状态（栈、变量等），而是保存已发生事件的历史记录。&lt;/p>
&lt;h3 id="重放循环">重放循环&lt;/h3>
&lt;ol>
&lt;li>&lt;strong>工作项到达&lt;/strong>：Dapr 引擎通过 &lt;code>GetWorkItems&lt;/code> 流向 SDK 发送一个 &lt;code>OrchestratorWorkItem&lt;/code>。该工作项包含工作流实例的完整历史记录以及任何新事件（例如，activity 完成或外部事件）。&lt;/li>
&lt;li>&lt;strong>重建&lt;/strong>：SDK 从头开始执行编排函数。&lt;/li>
&lt;li>&lt;strong>确定性执行&lt;/strong>：随着函数的执行，它会遇到&amp;quot;任务&amp;quot;（例如，调用 activity、休眠）。
&lt;ul>
&lt;li>对于每个任务，SDK 会检查提供的 &lt;strong>History&lt;/strong> 以查看该任务是否已完成。&lt;/li>
&lt;li>如果任务在历史记录中，SDK 会立即返回记录的结果，而无需实际重新执行任务逻辑。&lt;/li>
&lt;li>如果任务不在历史记录中，SDK 会记录该任务需要被调度并&lt;strong>暂停&lt;/strong>编排函数的执行（通常通过抛出特殊异常或返回待处理的 promise）。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;strong>报告&lt;/strong>：一旦编排函数被暂停或完成，SDK 会向 Dapr 发送 &lt;code>CompleteOrchestratorTask&lt;/code> 请求。该请求包含引擎应执行的一系列 &lt;strong>Actions&lt;/strong>（例如 &lt;code>ScheduleTask&lt;/code>、&lt;code>CreateTimer&lt;/code>）。&lt;/li>
&lt;li>&lt;strong>状态提交&lt;/strong>：Dapr 引擎接收这些操作，在状态存储中更新工作流历史记录，并调度任何请求的任务（例如，通过向 activity worker 发送工作）。&lt;/li>
&lt;/ol>
&lt;h2 id="分步示例">分步示例&lt;/h2>
&lt;p>假设一个工作流：&lt;code>Activity A -&amp;gt; Activity B&lt;/code>。&lt;/p>
&lt;h3 id="1-工作流启动">1. 工作流启动&lt;/h3>
&lt;ul>
&lt;li>&lt;strong>引擎&lt;/strong>：将 &lt;code>ExecutionStarted&lt;/code> 事件加入队列。&lt;/li>
&lt;li>&lt;strong>SDK&lt;/strong>：接收包含 &lt;code>[ExecutionStarted]&lt;/code> 的 &lt;code>OrchestratorWorkItem&lt;/code>。&lt;/li>
&lt;li>&lt;strong>SDK&lt;/strong>：运行函数。函数调用 &lt;code>Activity A&lt;/code>。&lt;/li>
&lt;li>&lt;strong>SDK&lt;/strong>：检查历史记录。&lt;code>Activity A&lt;/code> 不在其中。&lt;/li>
&lt;li>&lt;strong>SDK&lt;/strong>：暂停。发送包含 &lt;code>[ScheduleTask(Activity A)]&lt;/code> 的 &lt;code>CompleteOrchestratorTask&lt;/code>。&lt;/li>
&lt;li>&lt;strong>引擎&lt;/strong>：在历史记录中记录 &lt;code>TaskScheduled(Activity A)&lt;/code>。&lt;/li>
&lt;/ul>
&lt;h3 id="2-activity-a-完成">2. Activity A 完成&lt;/h3>
&lt;ul>
&lt;li>&lt;strong>引擎&lt;/strong>：在历史记录中记录 &lt;code>TaskCompleted(Activity A, result=&amp;quot;foo&amp;quot;)&lt;/code>。&lt;/li>
&lt;li>&lt;strong>SDK&lt;/strong>：接收包含 &lt;code>[ExecutionStarted, TaskScheduled(A), TaskCompleted(A)]&lt;/code> 的 &lt;code>OrchestratorWorkItem&lt;/code>。&lt;/li>
&lt;li>&lt;strong>SDK&lt;/strong>：从头开始运行函数。&lt;/li>
&lt;li>&lt;strong>SDK&lt;/strong>：函数调用 &lt;code>Activity A&lt;/code>。SDK 在历史记录中找到 &lt;code>TaskCompleted(A)&lt;/code>。返回 &lt;code>&amp;quot;foo&amp;quot;&lt;/code>。&lt;/li>
&lt;li>&lt;strong>SDK&lt;/strong>：函数调用 &lt;code>Activity B&lt;/code>。&lt;/li>
&lt;li>&lt;strong>SDK&lt;/strong>：检查历史记录。&lt;code>Activity B&lt;/code> 不在其中。&lt;/li>
&lt;li>&lt;strong>SDK&lt;/strong>：暂停。发送包含 &lt;code>[ScheduleTask(Activity B)]&lt;/code> 的 &lt;code>CompleteOrchestratorTask&lt;/code>。&lt;/li>
&lt;li>&lt;strong>引擎&lt;/strong>：记录 &lt;code>TaskScheduled(Activity B)&lt;/code>。&lt;/li>
&lt;/ul>
&lt;h3 id="3-工作流完成">3. 工作流完成&lt;/h3>
&lt;ul>
&lt;li>&lt;strong>Activity B&lt;/strong> 完成。&lt;/li>
&lt;li>&lt;strong>SDK&lt;/strong>：接收包含 A 和 B 都已完成的历史记录。&lt;/li>
&lt;li>&lt;strong>SDK&lt;/strong>：运行函数。A 和 B 都从历史记录返回结果。&lt;/li>
&lt;li>&lt;strong>SDK&lt;/strong>：函数完成并返回最终结果。&lt;/li>
&lt;li>&lt;strong>SDK&lt;/strong>：发送包含 &lt;code>[CompleteOrchestration(result=&amp;quot;final&amp;quot;)]&lt;/code> 的 &lt;code>CompleteOrchestratorTask&lt;/code>。&lt;/li>
&lt;li>&lt;strong>引擎&lt;/strong>：记录 &lt;code>OrchestrationCompleted&lt;/code> 并将实例标记为 &lt;code>COMPLETED&lt;/code>。&lt;/li>
&lt;/ul>
&lt;h2 id="sdk-作者的关键要求">SDK 作者的关键要求&lt;/h2>
&lt;h3 id="1-确定性">1. 确定性&lt;/h3>
&lt;p>编排函数必须是确定性的。它不能使用：&lt;/p></description></item><item><title>Workflow Protocol - Activity Lifecycle</title><link>https://docs.dapr.io/zh-hans/contributing/protocol-reference/workflow-protocol/workflow-protocol-activity-lifecycle/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://docs.dapr.io/zh-hans/contributing/protocol-reference/workflow-protocol/workflow-protocol-activity-lifecycle/</guid><description>&lt;h1 id="activity-生命周期">Activity 生命周期&lt;/h1>
&lt;p>Activity 是 Dapr Workflow 中的基本工作单元。与编排不同，Activity 不会重放，也不需要具有确定性。它们每次&amp;quot;调度&amp;quot;仅执行一次（尽管可能会发生重试）。&lt;/p>
&lt;h2 id="执行流程">执行流程&lt;/h2>
&lt;ol>
&lt;li>&lt;strong>调度&lt;/strong>：编排通过向 Dapr 引擎发送 &lt;code>ScheduleTask&lt;/code> 操作来请求一个 Activity。&lt;/li>
&lt;li>&lt;strong>工作项分发&lt;/strong>：Dapr 引擎将 Activity 任务加入队列。当 Activity worker（SDK）可用时，引擎通过 &lt;code>GetWorkItems&lt;/code> 流发送一个 &lt;code>ActivityWorkItem&lt;/code>。&lt;/li>
&lt;li>&lt;strong>执行&lt;/strong>：SDK 接收 &lt;code>ActivityWorkItem&lt;/code>，其中包含：
&lt;ul>
&lt;li>&lt;code>name&lt;/code>：要执行的 Activity 的名称。&lt;/li>
&lt;li>&lt;code>input&lt;/code>：Activity 的输入数据。&lt;/li>
&lt;li>&lt;code>instance_id&lt;/code>：调度该 Activity 的工作流实例的 ID。&lt;/li>
&lt;li>&lt;code>task_id&lt;/code>：此特定 Activity 执行的唯一标识符。&lt;/li>
&lt;li>&lt;code>task_execution_id&lt;/code>：此特定 Activity 的特定&lt;strong>尝试&lt;/strong>的唯一标识符。这对于在 Activity 逻辑中实现幂等性很有用。&lt;/li>
&lt;li>&lt;code>completion_token&lt;/code>：一个不透明 token，用于将响应与此特定工作项关联。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;strong>报告&lt;/strong>：Activity 逻辑完成后，SDK 向 Dapr 发送 &lt;code>CompleteActivityTask&lt;/code> 请求。
&lt;ul>
&lt;li>&lt;strong>成功&lt;/strong>：SDK 在 &lt;code>result&lt;/code> 字段中提供序列化输出。&lt;/li>
&lt;li>&lt;strong>失败&lt;/strong>：SDK 提供 &lt;code>failure_details&lt;/code>（错误消息、类型、堆栈跟踪）。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ol>
&lt;h2 id="task-execution-id">Task Execution ID&lt;/h2>
&lt;p>&lt;code>task_execution_id&lt;/code>（也称为 Task Execution Key）是一个唯一的、运行时生成的字符串（通常是 UUID），用于标识执行 Activity 任务的特定&lt;strong>尝试&lt;/strong>。&lt;/p></description></item><item><title>Workflow Protocol - State &amp; History</title><link>https://docs.dapr.io/zh-hans/contributing/protocol-reference/workflow-protocol/workflow-protocol-state-and-history/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://docs.dapr.io/zh-hans/contributing/protocol-reference/workflow-protocol/workflow-protocol-state-and-history/</guid><description>&lt;h1 id="状态和历史管理">状态和历史管理&lt;/h1>
&lt;p>Dapr Workflows 采用事件溯源模式，这意味着工作流的状态是从一系列事件中推导出来的。本文档描述了 Dapr 如何存储和管理这些历史记录和状态。&lt;/p>
&lt;h2 id="后端存储dapr-actors">后端存储：Dapr Actors&lt;/h2>
&lt;p>默认情况下，Dapr Workflow 引擎使用 &lt;strong>Dapr Actors&lt;/strong> 作为其存储后端。每个工作流实例都映射到一个唯一的 actor 实例。这提供了以下特性：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>并发控制&lt;/strong>：Actors 确保在任意时刻只有一个操作在处理工作流实例。&lt;/li>
&lt;li>&lt;strong>可靠性&lt;/strong>：Actor 状态会持久化到配置好的 Dapr 状态存储中。&lt;/li>
&lt;li>&lt;strong>定时器&lt;/strong>：Dapr Actors 提供持久化提醒，用于实现工作流定时器。&lt;/li>
&lt;/ul>
&lt;h2 id="工作流状态架构">工作流状态架构&lt;/h2>
&lt;p>工作流实例（actor）的状态由以下几个组件构成：&lt;/p>
&lt;h3 id="1-元数据">1. 元数据&lt;/h3>
&lt;p>存储有关该实例的高级信息：&lt;/p>
&lt;ul>
&lt;li>&lt;code>instance_id&lt;/code>：工作流的唯一 ID。&lt;/li>
&lt;li>&lt;code>name&lt;/code>：工作流的名称。&lt;/li>
&lt;li>&lt;code>status&lt;/code>：当前运行时状态（如 Running、Completed、Stalled 等）。&lt;/li>
&lt;li>&lt;code>version&lt;/code>：工作流版本的名称及任何活跃的补丁。&lt;/li>
&lt;li>&lt;code>created_at&lt;/code>：创建时间戳。&lt;/li>
&lt;li>&lt;code>last_updated_at&lt;/code>：最后活动时间戳。&lt;/li>
&lt;li>&lt;code>input&lt;/code>：原始输入数据。&lt;/li>
&lt;li>&lt;code>output&lt;/code>：最终输出数据（如已完成的）。&lt;/li>
&lt;/ul>
&lt;h3 id="2-历史记录">2. 历史记录&lt;/h3>
&lt;p>一系列 &lt;code>HistoryEvent&lt;/code> 对象，记录工作流中发生的所有事件。为了优化大型历史记录，Dapr 通常将历史事件以分块或单独键值的形式存储在状态存储中：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>键格式&lt;/strong>：&lt;code>wf-history-&amp;lt;instance_id&amp;gt;-&amp;lt;index&amp;gt;&lt;/code>&lt;/li>
&lt;li>&lt;strong>事件内容&lt;/strong>：序列化的 protobuf 消息，包含事件类型、时间戳以及类型特定的数据（如 &lt;code>TaskScheduled&lt;/code>、&lt;code>TaskCompleted&lt;/code>）。&lt;/li>
&lt;/ul>
&lt;h3 id="3-收件箱待处理事件">3. 收件箱（待处理事件）&lt;/h3>
&lt;p>已发生但尚未被编排器处理（重放）的事件集合。包括：&lt;/p>
&lt;ul>
&lt;li>向工作流引发的外部事件。&lt;/li>
&lt;li>已完成的 activity 结果。&lt;/li>
&lt;li>已触发的定时器。&lt;/li>
&lt;/ul>
&lt;p>当编排器下次运行时，它会&amp;quot;排空&amp;quot;收件箱，将这些事件移入历史记录，然后重放逻辑。&lt;/p>
&lt;h2 id="重放与状态重建">重放与状态重建&lt;/h2>
&lt;p>当 Worker（SDK）收到工作项时，Dapr 提供历史事件。SDK 通过按顺序重放这些事件来重建编排的内部状态（例如本地变量、当前执行点）。&lt;/p>
&lt;h3 id="确定性原则与历史记录">确定性原则与历史记录&lt;/h3>
&lt;p>历史记录是&amp;quot;真相的来源&amp;quot;。如果编排代码以非确定性的方式发生变化（例如在现有代码中间添加新的 activity 调用），重放将失败，因为代码的请求将与记录的历史记录不匹配。&lt;/p></description></item><item><title>工作流协议 - 版本控制</title><link>https://docs.dapr.io/zh-hans/contributing/protocol-reference/workflow-protocol/workflow-protocol-versioning/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://docs.dapr.io/zh-hans/contributing/protocol-reference/workflow-protocol/workflow-protocol-versioning/</guid><description>&lt;h1 id="工作流版本控制">工作流版本控制&lt;/h1>
&lt;p>Dapr 工作流支持工作流定义的版本控制，允许你在现有实例继续运行其原始逻辑的同时更新工作流逻辑。&lt;/p>
&lt;h2 id="命名工作流版本控制">命名工作流版本控制&lt;/h2>
&lt;p>向 Dapr 引擎注册工作流时，你可以提供版本名称。这允许同一工作流的多个版本共存。&lt;/p>
&lt;ul>
&lt;li>&lt;strong>默认版本&lt;/strong>：一个工作流版本可被标记为默认版本。如果客户端仅通过名称启动工作流而不指定版本，则使用默认版本。&lt;/li>
&lt;li>&lt;strong>特定版本&lt;/strong>：客户端可以在启动新实例时请求工作流的特定版本。&lt;/li>
&lt;/ul>
&lt;h3 id="注册-api">注册 API&lt;/h3>
&lt;p>SDK 使用其任务注册表中的 &lt;code>AddVersionedOrchestrator&lt;/code>（或类似）方法来注册版本化工作流。&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-go" data-lang="go">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8f5902;font-style:italic">// 示例（内部注册表 API）&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#000">registry&lt;/span>&lt;span style="color:#000;font-weight:bold">.&lt;/span>&lt;span style="color:#000">AddVersionedOrchestrator&lt;/span>&lt;span style="color:#000;font-weight:bold">(&lt;/span>&lt;span style="color:#4e9a06">&amp;#34;MyWorkflow&amp;#34;&lt;/span>&lt;span style="color:#000;font-weight:bold">,&lt;/span> &lt;span style="color:#4e9a06">&amp;#34;v2&amp;#34;&lt;/span>&lt;span style="color:#000;font-weight:bold">,&lt;/span> &lt;span style="color:#204a87;font-weight:bold">true&lt;/span>&lt;span style="color:#000;font-weight:bold">,&lt;/span> &lt;span style="color:#000">MyWorkflowV2&lt;/span>&lt;span style="color:#000;font-weight:bold">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#000">registry&lt;/span>&lt;span style="color:#000;font-weight:bold">.&lt;/span>&lt;span style="color:#000">AddVersionedOrchestrator&lt;/span>&lt;span style="color:#000;font-weight:bold">(&lt;/span>&lt;span style="color:#4e9a06">&amp;#34;MyWorkflow&amp;#34;&lt;/span>&lt;span style="color:#000;font-weight:bold">,&lt;/span> &lt;span style="color:#4e9a06">&amp;#34;v1&amp;#34;&lt;/span>&lt;span style="color:#000;font-weight:bold">,&lt;/span> &lt;span style="color:#204a87;font-weight:bold">false&lt;/span>&lt;span style="color:#000;font-weight:bold">,&lt;/span> &lt;span style="color:#000">MyWorkflowV1&lt;/span>&lt;span style="color:#000;font-weight:bold">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="边车版本控制">边车版本控制&lt;/h2>
&lt;p>Dapr 边车会跟踪实例正在运行的工作流命名版本，以及在该工作流执行过程中已应用的补丁列表。此信息存储在工作流历史记录中，位于 &lt;code>OrchestratorStarted&lt;/code> 事件的 &lt;code>version&lt;/code> 字段内。&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-protobuf" data-lang="protobuf">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#204a87;font-weight:bold">message&lt;/span> &lt;span style="color:#000">OrchestrationVersion&lt;/span> &lt;span style="color:#000;font-weight:bold">{&lt;/span>&lt;span style="color:#a40000">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a40000">&lt;/span> &lt;span style="color:#204a87;font-weight:bold">string&lt;/span> &lt;span style="color:#000">name&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">=&lt;/span> &lt;span style="color:#0000cf;font-weight:bold">1&lt;/span>&lt;span style="color:#000;font-weight:bold">;&lt;/span>&lt;span style="color:#a40000">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a40000">&lt;/span> &lt;span style="color:#204a87;font-weight:bold">repeated&lt;/span> &lt;span style="color:#204a87;font-weight:bold">string&lt;/span> &lt;span style="color:#000">patches&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">=&lt;/span> &lt;span style="color:#0000cf;font-weight:bold">2&lt;/span>&lt;span style="color:#000;font-weight:bold">;&lt;/span>&lt;span style="color:#a40000">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a40000">&lt;/span>&lt;span style="color:#000;font-weight:bold">}&lt;/span>&lt;span style="color:#a40000">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>当实例恢复时（例如，在某个活动完成后），Dapr 引擎负责处理因客户端版本不匹配而导致的停滞。它通过监控 placement 表的变化来实现这一点，这表明有新的 SDK 客户端已连接（可能代表应用程序的较新副本实例），并调度重放最后一个事件以尝试重试该操作。这一次，如果 SDK 能够成功完成任务，运行时将把工作流状态从 &lt;code>Stalled&lt;/code> 更改回 &lt;code>Running&lt;/code>。&lt;/p></description></item></channel></rss>