Rivet Actors GetOrCreate 请求模型解析:Rust SDK 中 ActorsGetOrCreateRequest 的字段、语义与底层实现
【免费下载链接】actorsRivet Actors are the primitive for stateful workloads. Built for AI agents, collaborative apps, and durable execution.项目地址: https://gitcode.com/GitHub_Trending/riv/actors
Rivet Actors 是面向 AI Agent、协作应用与持久化执行场景设计的有状态工作负载原语。ActorsGetOrCreateRequest是 Rivet Rust SDK(engine/sdks/rust/api-full/rust)中actors_get_or_create接口(PUT /actors)的请求模型,它提供"按键创建或获取"这一幂等能力,是构建会话型 Actor、实现去重创建的核心入口。读完本文,你将掌握该请求模型的全部字段语义、CrashPolicy枚举取值、跨数据中心路由行为,以及引擎侧对 key 的校验与竞态处理逻辑。
一、模型总览:ActorsGetOrCreateRequest 字段清单
ActorsGetOrCreateRequest定义在 rust SDK 模型文件 中,其字段结构如下:
| 名称 | 类型 | 是否必填 | 说明 |
|---|---|---|---|
| crash_policy | models::CrashPolicy | 是 | Actor 崩溃后的处理策略 |
| datacenter | Option<String> | 否(可选) | 期望创建 Actor 的目标数据中心标签 |
| input | Option<String> | 否(可选) | 任意 base64 编码的二进制数据,作为创建 Actor 时的初始化输入 |
| key | String | 是 | Actor 的全局唯一键,get-or-create 的幂等依据 |
| name | String | 是 | Actor 名称 |
| runner_name_selector | String | 是 | 用于选择运行该 Actor 的 Runner(运行池)选择器 |
在 Rust 代码层面,datacenter与input使用了serde_with::rust::double_option序列化策略,并在skip_serializing_if = "Option::is_none"的控制下,仅在确有值时才会出现在请求 JSON 中;同时结构体派生了Serialize/Deserialize,可直接作为reqwest等 HTTP 客户端的请求体使用。构造函数new()只要求crash_policy、key、name、runner_name_selector四个必填字段,datacenter与input默认置为None。
注:SDK 生成的模型文档位于 engine/sdks/rust/api-full/rust/docs/ActorsGetOrCreateRequest.md,其字段声明与上述实现一一对应。服务端真正解析该请求的类型定义在 engine/packages/api-types/src/actors/get_or_create.rs,且标注了
#[serde(deny_unknown_fields)],即请求体中不允许出现未声明的多余字段,否则会被服务端拒绝。
二、CrashPolicy:Actor 崩溃后的三种处置策略
crash_policy是一个枚举类型,其取值与 JSON 序列化值如下(见 CrashPolicy.md):
| 枚举变体 | 序列化值(JSON) |
|---|---|
| Restart | restart |
| Sleep | sleep |
| Destroy | destroy |
在引擎侧,该枚举定义于 engine/packages/types/src/actors.rs:
Restart:Actor 崩溃后由平台自动重启,适合需要持续对外服务的状态型 Actor;Sleep:崩溃后进入休眠(Hibernate)状态,等待下一次请求唤醒,适合可被惰性唤醒的工作负载;Destroy:崩溃后直接销毁 Actor 实例,是#[default]默认策略,适合无状态或可重建的临时任务。
CrashPolicy同时派生了ToSchema,因此它会直接反映到 OpenAPI 规范(engine/artifacts/openapi.json)中,SDK 文档即由该规范生成,保证客户端与服务端的取值严格一致。
三、接口语义:PUT /actors 的幂等获取或创建
ActorsGetOrCreateRequest对应actors_get_or_create操作,HTTP 方法为PUT,路径为/actors,请求与响应的 Content-Type 均为application/json,并需要bearer_auth认证(详见 ActorsGetOrCreateApi.md)。
调用时还需在Query 参数中携带namespace(命名空间名),完整请求形式为:
PUT /actors?namespace={namespace}请求体即为ActorsGetOrCreateRequest。响应体为 ActorsGetOrCreateResponse:
| 字段 | 类型 | 说明 |
|---|---|---|
| actor | models::Actor | Actor 详情(无论新建还是已存在都会返回) |
| created | bool | 本次调用是否新建了 Actor;true表示新建,false表示返回的是已存在实例 |
created字段是 get-or-create 语义的关键:调用方可以通过它区分"首次创建"与"命中既有实例",从而决定是否执行初始化逻辑(如写入初始状态、建立初始连接等)。
一个可直接运行的 curl 示例(源自 examples/kitchen-sink/CLAUDE.md):
export RIVET_NS="<namespace>" export RIVET_TOKEN="<token>" curl -s -X PUT "https://api.rivet.dev/actors?namespace=${RIVET_NS}" \ -H "Authorization: Bearer ${RIVET_TOKEN}" \ -H 'Content-Type: application/json' \ -d '{"name":"<actorName>","key":"<key>","runner_name_selector":"k8s","crash_policy":"sleep"}'返回形如{"actor":{"actor_id":"<ACTOR_ID>", ...}, "created": true/false}。
3.1 核心幂等逻辑:key 是唯一仲裁依据
key是 get-or-create 的幂等依据。在 api-peer 实现 中,处理流程如下:
- 先校验 key 合法性:key 为空返回
EmptyKey错误;key 长度超过MAX_ACTOR_KEY_SIZE(1024 字节)返回KeyTooLarge错误; - 通过
namespace::ops::resolve_for_name_global解析命名空间; - 调用
pegboard::ops::actor::get_for_key按键查询 Actor:Found:直接返回已有 Actor,created = false;NotFound:创建新 Actor(created = true);Forward:key 已被其他数据中心预留,返回KeyReservedInDifferentDatacenter错误;
- 创建过程中若出现
duplicate_key错误(如并发创建下的唯一键冲突),extract_duplicate_key_error会从错误元数据中提取existing_actor_id并回读既有 Actor,仍然返回created = false,从而保证并发场景下的幂等一致性。
也就是说:同一个 namespace 下,key 相同的多次调用始终返回同一个 Actor,这正是"获取或创建"语义的底层保证。
四、字段实战要点:datacenter、input 与 runner_name_selector
4.1 datacenter:跨数据中心创建的目标选择
datacenter(可选)用于指定 Actor 期望创建的目标数据中心标签。在 api-public 入口实现 中,服务端会先通过find_dc_for_actor_creation计算出目标数据中心:
- 若目标数据中心与当前数据中心相同,则在本数据中心内直接执行创建逻辑;
- 若目标数据中心不同,则通过
request_remote_datacenter将PUT /actors请求转发到远程数据中心执行。
注意:在 api-peer 内部实现中该字段会被忽略(注释标明 "Ignored in api-peer"),因为 api-peer 总是在自身所在数据中心创建 Actor;跨数据中心转发由 api-public 层负责。
4.2 input:base64 编码的初始化数据
input(可选)是 "Arbitrary base64 encoded binary data",即任意 base64 编码的二进制数据。它会在创建 Actor 时随创建工作流一起传入,作为 Actor 启动阶段的初始化输入(例如传入种子状态、初始消息或序列化参数)。它只对"新建"生效——当 get-or-create 命中已有 Actor 时,input 会被忽略(见下文测试依据)。
4.3 runner_name_selector:选择运行池
runner_name_selector是必填字符串,用于选择承载该 Actor 的 Runner。它参与 Actor 创建时的池选择逻辑,与运行环境(如 k8s 池、serverless 池等)绑定,对应RunnerConfig/RunnerConfigsUpsertApi中定义的 Runner 配置体系。在 key 查询阶段它同样作为pool_name传入,用于缩小按键查询范围。
五、架构与性能:数据中心往返次数(Round Trips)
ActorsGetOrCreateApi.md 明确给出了不同场景下的跨数据中心往返(round trip)成本,这是评估该接口延迟的关键指标:
场景一:Actor 已存在—— 2 次往返
namespace::ops::resolve_for_name_global(解析命名空间)GET /actors/{id}(读取既有 Actor)
场景二:Actor 不存在,且在当前数据中心创建—— 2 次往返
namespace::ops::resolve_for_name_globalpegboard::workflows::actor创建 Actor 工作流(包含 Epoxy 键分配)
场景三:Actor 不存在,且需要在其他数据中心创建—— 3 次往返
namespace::ops::resolve_for_name_global- 向远程数据中心发送
POST /actors pegboard::workflows::actor创建 Actor 工作流(包含 Epoxy 键分配)
此外文档特别强调:actor::get总是发生在同一数据中心内。这意味着对于热点 key 的频繁 get-or-create 调用,命中已存在 Actor 的成本是固定的 2 次往返,且不会跨数据中心读取,整体延迟可控。该行为与 api-public 中target_dc_label == ctx.config().dc_label()时走本地、否则走远程转发的分支逻辑完全吻合。
六、源码与测试佐证:幂等性与竞态处理
围绕该请求模型,仓库提供了完整的集成测试(engine/packages/engine/tests/envoy/api_actors_get_or_create.rs),可直接验证上述语义:
get_or_create_creates_new_actor:首次调用应返回created = true,且actor.key与请求 key 一致;get_or_create_returns_existing_actor:第二次以相同 key 调用(即使input不同)应返回created = false,且input被忽略——佐证"input 仅对新建生效";get_or_create_same_name_different_keys:同名不同 key 会创建不同 Actor,佐证幂等维度是 key 而非 name;get_or_create_idempotent:连续 5 次相同 key 调用,只有第一次created = true,后续全部返回同一actor_id;get_or_create_race_condition_handling/get_or_create_returns_winner_on_race/get_or_create_race_condition_across_datacenters:并发(含跨数据中心)竞争同一 key 时,通过 duplicate key 回读机制保证最终只有一个 Actor 胜出;get_or_create_in_current_datacenter/get_or_create_in_remote_datacenter:验证 datacenter 参数在当前数据中心与远程数据中心两种路由路径。
在 Rust 客户端侧,对应 API 绑定位于 engine/sdks/rust/api-full/rust/src/apis/actors_get_or_create_api.rs,其actors_get_or_create函数签名接收namespace与ActorsGetOrCreateRequest,返回ActorsGetOrCreateResponse。
七、使用建议与边界约束
- key 的设计:key 是全局幂等键,建议使用业务上唯一且稳定的标识(如用户 ID、会话 ID、房间 ID)。受 1024 字节上限约束,避免放入超长数据;空 key 会被直接拒绝。
- crash_policy 的选择:需要持续在线的协作型 Actor 可选
restart;可被请求唤醒的按需型 Actor 可选sleep;一次性任务建议使用默认的destroy。 - 严格请求体:由于服务端启用了
deny_unknown_fields,请勿在请求体中携带未声明字段,否则请求会被拒绝。 - 幂等是默认能力:get-or-create 天然去重,可直接用于解决"重复创建 Actor"问题,无需在业务层额外加锁。
- 跨数据中心创建:如需指定创建地域,请使用
datacenter字段;未指定时由服务端依据runner_name_selector与调度策略决定目标数据中心。
相关资源
- Rust SDK 模型定义
- Rust SDK API 绑定
- 服务端请求类型定义
- api-public 入口实现
- api-peer 核心实现
- CrashPolicy 枚举定义
- 集成测试
- curl 调用示例
【免费下载链接】actorsRivet Actors are the primitive for stateful workloads. Built for AI agents, collaborative apps, and durable execution.项目地址: https://gitcode.com/GitHub_Trending/riv/actors
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考