ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Rivet Actors GetOrCreate 响应模型解析:actor + created 双字段背后的幂等创建语义

Rivet Actors GetOrCreate 响应模型解析:actor + created 双字段背后的幂等创建语义 Rivet Actors GetOrCreate 响应模型解析actor created 双字段背后的幂等创建语义【免费下载链接】actorsRivet Actors are the primitive for stateful workloads. Built for AI agents, collaborative apps, and durable execution.项目地址: https://gitcode.com/GitHub_Trending/riv/actors导读ActorsGetOrCreateResponse是 Rivet Actors 公开 API 中获取或创建 ActorPUT /actors的响应模型它用actor与created两个字段同时回答我要的 Actor 在哪里和它是不是刚刚才被创建两个问题。本文以 ActorsGetOrCreateResponse.md 为骨架结合同目录下的请求/API 文档与 Rust 源码api-full生成的 OpenAPI 客户端以及rivetkit-rust高层封装完整讲解该响应模型的结构、语义、底层 Datacenter 往返过程以及基于它实现的幂等创建实战模式。读完本文你将能准确理解created字段的判定时机、actor字段的生命周期字段含义并在自己的 Rust 客户端中正确消费这一响应。一、响应模型概览两个字段两种语义ActorsGetOrCreateResponse是 OpenAPI 生成模型定义于 actors_get_or_create_response.rs字段类型说明actormodels::Actor本次请求对应命中或新建的 Actor 完整对象createdbool标记该 Actor 是否为本次请求新建若为已存在对象则为false#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize)] pub struct ActorsGetOrCreateResponse { #[serde(rename actor)] pub actor: Boxmodels::Actor, #[serde(rename created)] pub created: bool, }模型同时提供了new(actor, created)构造函数与标准Serialize/Deserialize派生可以直接与serde_json配合反序列化服务端响应。1.1 actor 字段完整的 Actor 状态视图actor字段的类型为 Actor.md 中定义的Actor模型它描述了 Actor 的标识、调度与生命周期状态其中常见字段包括字段类型说明actor_idStringActor 的唯一标识nameStringActor 的全局名称keyOptionString命名空间内唯一的业务键namespace_idString所属命名空间 IDdatacenterStringActor 所在的数据中心runner_name_selectorString调度时选择的 Runner 池名称crash_policyCrashPolicy崩溃策略create_tsi64首次创建时间戳start_tsOptioni64首次可连接时间未启动过则为nullconnectable_tsOptioni64最近一次可连接时间未运行时为nulldestroy_tsOptioni64销毁时间sleep_tsOptioni64进入休眠状态的时间pending_allocation_tsOptioni64开始等待资源分配的时间reschedule_tsOptioni64下次尝试分配的时间设置后在此之前不会重新分配errorOptionserde_json::Value启动失败时的错误详情通过这些时间戳字段调用方仅凭一次actors_get_or_create响应即可判断 Actor 当前是运行中、休眠中、等待分配还是已销毁无需额外查询。1.2 created 字段幂等语义的关键created是bool类型表示本次GetOrCreate调用是否真正创建了 Actortrue该请求触发了新建流程返回的actor是新建对象false请求命中了一个已存在的同名同键 Actor返回的是既有对象。这一设计让GetOrCreate接口天然具备幂等性对同一namekey重复调用无论网络重试多少次最终都只会有一个 Actor 存在同时调用方可通过created精确区分首次创建与复用已有便于触发一次性的初始化逻辑。二、请求与响应一次完整的 GetOrCreate 调用2.1 请求端ActorsGetOrCreateRequestactors_get_or_create接口的请求体为 ActorsGetOrCreateRequest.md字段类型必填说明crash_policyCrashPolicy是崩溃后的处理策略datacenterOptionString否期望部署的数据中心inputOptionString否传给 Actor 的初始输入keyString是命名空间内唯一的业务键nameString是Actor 的全局名称runner_name_selectorString是选择 Runner 池的表达式2.2 API 端点ActorsGetOrCreateApi按照 ActorsGetOrCreateApi.md该方法对应HTTP 方法PUT /actors认证bearer_authBearer Token请求头Content-Type: application/json、Accept: application/json返回值models::ActorsGetOrCreateResponse生成的客户端函数签名位于 actors_get_or_create_api.rs调用时以 query 参数传递namespace以 JSON 传递请求体成功时通过serde_json反序列化为ActorsGetOrCreateResponse非 2xx 响应则包装为ErrorActorsGetOrCreateError返回。pub async fn actors_get_or_create( configuration: configuration::Configuration, namespace: str, actors_get_or_create_request: models::ActorsGetOrCreateRequest, ) - Resultmodels::ActorsGetOrCreateResponse, ErrorActorsGetOrCreateError { // ... let uri_str format!({}/actors, configuration.base_path); let mut req_builder configuration.client.request(reqwest::Method::PUT, uri_str); req_builder req_builder.query([(namespace, p_namespace.to_string())]); // bearer auth JSON body... }2.3 响应体示例一次成功的调用返回形如{ actor: { actor_id: …, name: my-actor, key: …, namespace_id: …, datacenter: …, runner_name_selector: …, crash_policy: destroy, create_ts: 1726000000000, start_ts: null, connectable_ts: null }, created: true }三、底层语义Datacenter 往返过程Round TripsActorsGetOrCreateApi.md 明确记录了该接口在不同情况下的内部往返次数这是理解接口延迟与created判定时机的核心Actor 已存在2 次往返namespace::ops::resolve_for_name_global全局解析名称归属GET /actors/{}直接读取既有 Actor此时created为false。Actor 不存在且创建在当前数据中心2 次往返namespace::ops::resolve_for_name_global执行pegboard::workflows::actor创建 Actor 工作流包含 Epoxy key 分配此时created为true。Actor 不存在且需创建在其他数据中心3 次往返namespace::ops::resolve_for_name_globalPOST /actors转发到远端数据中心远端执行pegboard::workflows::actor创建工作流包含 Epoxy key 分配。文档同时强调actor::get永远发生在同一数据中心内actor::get will always be in the same datacenter即读取路径不会跨数据中心往返。这也解释了为何命中已有 Actor 时只需 2 次往返——名称解析 本地读取无需再走创建工作流。3.1 从往返过程看 created 的判定created本质上反映的是服务端实际走了读取命中还是新建工作流分支命中已有对象 →created false触发pegboard::workflows::actor创建无论本地还是远端→created true。由于名称解析resolve_for_name_global在所有分支都会发生创建与读取的分水岭在于第二步是否执行了创建工作流。这正是响应模型把created独立成一个字段、而不是让调用方对比时间戳的原因。四、源码纵深rivetkit-rust 中的幂等封装在高层 Rust SDK remote_manager.rs 中ActorsGetOrCreateResponse被封装为get_or_create_with_key方法remote_manager.rslet request_body ActorsGetOrCreateRequest { name: name.to_string(), key: key_str, // 规范的斜杠转义 key 格式 input: input_encoded, // base64 编码的 CBOR runner_name_selector: pool_name.unwrap_or_else(|| self.pool_name.clone()), crash_policy: destroy.to_string(), }; let req self.apply_common_headers_with( self.client.put(format!( {}/actors?namespace{}, config.endpoint, urlencoding::encode(config.namespace) )).json(request_body), config, )?; // ... let data: ActorsGetOrCreateResponse res.json().await?; Ok(data.actor.actor_id) // 只取 actor_id 返回几个值得注意的实现细节Key 的规范化序列化key 使用serialize_actor_key生成斜杠转义格式注释明确说明与 TS SDK 及 Runner 端解析器保持一致而非 JSON 编码保证多语言 SDK 之间的 key 语义互通。Input 的编码input先经serde_cbor序列化再以 Base64 编码为字符串与ActorsGetOrCreateRequest.input: OptionString的类型定义吻合。默认 crash_policy高层封装默认传入destroy字符串。跨数据中心冲突回退当请求返回key_reserved_in_different_datacenter错误groupactor、codekey_reserved_in_different_datacenter时客户端会回退为get_with_key按 key 读取——这恰好对应上文在远端数据中心创建分支在并发场景下可能出现的竞态注释称之为race 后自愈。对应地客户端内部定义了响应反序列化结构remote_manager.rs与 OpenAPI 生成模型保持字段一致#[derive(Debug, Serialize, Deserialize)] struct ActorsGetOrCreateResponse { actor: Actor, // 此处为精简后的 actor_id/name/key created: bool, }与ActorsCreateResponse仅含actor、无created对比可见created字段是 GetOrCreate 幂等语义独有的普通创建接口不会返回该信息。五、实战如何消费 ActorsGetOrCreateResponse5.1 用 created 区分首次初始化与复用幂等创建最常见的场景是保证某个有状态 Worker 全局唯一多个请求并发调用actors_get_or_create只有created true的那次负责执行初始化如建表、加载种子数据let resp actors_get_or_create(config, namespace, request).await?; if resp.created { // 本次请求新建了 Actor执行一次性初始化 bootstrap_actor_state(resp.actor.actor_id).await?; } else { // 已存在直接复用避免重复初始化 tracing::info!(actor already exists: {}, resp.actor.actor_id); }5.2 用 actor 字段做状态预判在拿到actor后可结合生命周期时间戳决定下一步start_ts/connectable_ts为nullActor 尚未启动完成需等待连接sleep_ts非空Actor 已休眠可能需要唤醒后再连接reschedule_ts非空Actor 正在等待下一次资源分配不应立即连接error非空Actor 启动失败应从响应中读取错误详情。5.3 注意事项连接地址不在此响应中ActorsGetOrCreateResponse只包含 Actor 状态对象不含可连接端点获取连接信息需配合其他接口或 SDK 的后续步骤。跨数据中心场景若请求指定了datacenter且目标为远端可能触发 3 次往返的创建路径延迟高于本地命中路径。并发竞态正如高层封装所见极端并发下可能遇到 key 在异数据中心被预留的冲突客户端应以回退读取策略自愈。六、相关资源在仓库中可以继续查阅模型定义与字段说明ActorsGetOrCreateResponse.md、Actor.md、CrashPolicy.md请求与 API 文档ActorsGetOrCreateRequest.md、ActorsGetOrCreateApi.md生成的 Rust 模型与客户端actors_get_or_create_response.rs、actors_get_or_create_api.rs高层幂等封装remote_manager.rsSDK 总览README.md通过actorcreated的组合Rivet Actors 把查询、创建、初始化三个动作收敛到一次幂等调用中是构建有状态工作负载AI Agent、协作应用、持久化执行时最常用的入口之一。【免费下载链接】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),仅供参考
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进