
Rivet Actors GetOrCreate API 深度解析跨数据中心幂等 Actor 获取与创建【免费下载链接】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 中actors_get_or_createHTTPPUT /actors是构建有状态工作负载时的核心原语它以namespace name key为唯一标识实现存在则返回、不存在则创建的幂等语义特别适合 AI Agent、协作类应用与持久化执行等场景。本文以 ActorsGetOrCreateApi.md 为主体结合仓库中 api-public / api-peer / pegboard 的源码实现完整讲解该接口的请求参数、返回结构、跨数据中心路由策略Datacenter Round Trips、Epoxy Key 预留机制与典型错误处理帮助你掌握在 Rust SDK 中正确、高效地使用这一原语。一、接口概览GetOrCreate 与 Create 的定位差异actors_get_or_create由 api-public 路由 以PUT /actors注册与POST /actorsActorsCreateApi相比核心差异在于维度POST /actorsactors_createPUT /actorsactors_get_or_create语义无条件创建key 冲突会触发duplicate_key错误幂等key 已存在则直接返回既有 Actor否则创建响应ActorsCreateResponse仅含actorActorsGetOrCreateResponse含actor与created标志适用场景需要严格新建的语义或客户端已确认 Actor 不存在每次请求都拿引用如连接游戏房间、绑定会话、按业务键定位实例从 SDK 生成代码看客户端方法签名如下见 actors_get_or_create_api.rspub async fn actors_get_or_create( configuration: configuration::Configuration, namespace: str, actors_get_or_create_request: models::ActorsGetOrCreateRequest, ) - Resultmodels::ActorsGetOrCreateResponse, ErrorActorsGetOrCreateError请求的 base URL 相对http://localhost需要bearer_auth鉴权Content-Type与Accept均为application/json。二、请求参数与数据模型PUT /actors的参数分两部分query 参数namespace与 JSON bodyActorsGetOrCreateRequest。对应的 Rust 模型定义在 actors_get_or_create_request.rs。2.1 参数总表名称位置类型必填说明namespaceQueryString✅目标命名空间名称nameBodyString✅Actor 的名称与key共同构成唯一性约束keyBodyString✅业务键最大 1024 字节不可为空runner_name_selectorBodyString✅选择器决定由哪个 Runner 配置池承载该 Actorcrash_policyBodyCrashPolicy✅崩溃策略restart/sleep/destroydatacenterBodyOptionString❌目标数据中心名称不传时自动选择inputBodyOptionString❌创建时注入的初始数据为任意 base64 编码的二进制数据2.2 关键字段细节key 的约束服务端在 api-peer 的 get_or_create 中校验空 key 返回EmptyKey超过 1024 字节返回KeyTooLarge错误定义见 errors.rs。MAX_ACTOR_KEY_SIZE 1024在源码中以常量形式声明。crash_policy 枚举见 CrashPolicy取值restart、sleep、destroy分别表示崩溃后重启、进入休眠、直接销毁。input与ActorsCreateRequest一致见 ActorsCreateRequest是可选的 base64 二进制数据会在 Actor 启动时注入。三、响应结构actor created响应模型ActorsGetOrCreateResponse见 actors_get_or_create_response.rs包含两个字段字段类型说明actorActor完整的 Actor 对象createdbooltrue表示本次调用实际创建了新 Actorfalse表示命中已存在的 Actorcreated字段是幂等语义的关键客户端可以借此区分首次启动需要初始化状态、推送初始数据与复用已有实例直接连接。Actor对象本身携带丰富的生命周期信息见 Actor.mdactor_id、namespace_id、name、key、datacenter、runner_name_selectorcreate_ts首次创建时间start_ts首次可连接时间null表示从未sleep_ts进入休眠状态的时间reschedule_ts下次尝试调度的最早时间戳connectable_ts最后一次可连接时间未运行时为nulldestroy_ts、pending_allocation_ts、error销毁时间、等待分配时间与启动失败的错误详情四、核心原理Datacenter Round Trips 与跨数据中心路由原文档最重要的部分是Datacenter Round Trips分析它揭示了actors_get_or_create在不同情形下的跨数据中心网络开销。综合服务端实现 get_or_create.rs可以还原完整流程。4.1 三种情形的往返次数情形 AActor 已存在2 次往返namespace::ops::resolve_for_name_global将 namespace 名称解析为全局唯一的namespace_idGET /actors/{id}直接定位并读取既有 Actor。情形 BActor 不存在且在当前数据中心创建2 次往返namespace::ops::resolve_for_name_globalpegboard::workflows::actor创建流程包含 Epoxy Key 分配即 Actor 创建工作流。情形 CActor 不存在且在其他数据中心创建3 次往返namespace::ops::resolve_for_name_globalPOST /actors转发到远端数据中心远端执行pegboard::workflows::actor创建流程包含 Epoxy Key 分配。原文档同时强调actor::get 永远发生在同一数据中心内——也就是说一旦 Actor 被创建后续对该 Actor 的所有操作读取、连接、KV 访问都在其所在的数据中心完成不会产生跨 DC 的读取。4.2 数据中心选择的实现细节请求处理在get_or_create_inner中先解析 namespace然后调用find_dc_for_actor_creation决定目标数据中心见 utils.rs若请求带datacenter参数则通过dc_for_name解析为 datacenter label并校验该 DC 是否启用了对应的 Runner 配置若未指定则取list_runner_config_enabled_dcs返回的第一个可用 DC若没有任何 DC 配置了该 runner 名称返回NoRunnerConfigConfigured错误。选定目标 DC 后get_or_create_inner做本地 / 转发决策见 get_or_create.rsif target_dc_label ctx.config().dc_label() { rivet_api_peer::actors::get_or_create::get_or_create(ctx.into(), (), query, body).await } else { request_remote_datacenter::GetOrCreateResponse( ctx.config(), target_dc_label, /actors, axum::http::Method::PUT, Some(query), Some(body), ).await }即目标 DC 就是当前 DC 时走进程内操作api-peer否则通过 HTTP 转发到远端 DC 的/actors端点——这正对应情形 C 中的第 2 次往返。五、源码级实现剖析从 Key 查找到并发兜底api-peer中的核心逻辑见 get_or_create.rs由三步组成查 key → 命中即返回 → 未命中创建。5.1 第一步按 Key 查询既有 Actor通过pegboard::ops::actor::get_for_key操作完成见 get_for_key.rs其内部先调用get_reservation_for_key从Epoxy读取该 key 的预留reservation信息输出三种结果输出含义处理Found { actor }key 已有 Actor 且在当前 DC直接返回created: falseNotFound无预留记录进入创建流程Forward { dc_label }key 被预留到其他 DC返回KeyReservedInDifferentDatacenter错误5.2 第二步创建并处理并发竞争未命中时代码生成新的actor_idId::new_v1(ctx.config().dc_label())即 actor ID 内嵌 DC 标签调用pegboard::ops::actor::create创建并携带forward_request: true。这里有一个值得注意的并发兜底如果两个客户端同时以同一 key 调用 get_or_create创建阶段可能抛出duplicate_key错误。api-peer 通过extract_duplicate_key_error见 get_or_create.rs从错误链中提取existing_actor_id然后get这个已存在的 Actor同样返回created: false。这样即便在竞争条件下get_or_create 也保持幂等而非报错。该辅助函数同时支持本地RivetError与远端RawErrorResponse两种错误形态。5.3 第三步Epoxy Key 预留的全局语义创建流程涉及 Epoxy 的per-key Paxos机制详见 ACTOR_KEY_RESERVATION.mdEpoxy KV 中存储Actor key - reservation IDreservation ID 内含 Actor 所在 DC 标签全新 key 走 per-key Paxos 快速路径1 个 RTT 完成预留解析使用kv_get_optimistic假设值一经写入不再变化因此本地可缓存 Actor 所在 DC解析一次后无需再跨节点读取由于预留值不可变更key 与数据中心绑定Actor 只能在原预留 DC 创建这正是Forward与KeyReservedInDifferentDatacenter错误存在的根本原因错误定义见 errors.rs。另一方面pegboard::ops::actor::create还会订阅 Actor 工作流的CreateComplete/Failed/DestroyStarted事件并阻塞等待结果见 create.rs若工作流报出KeyReservedInDifferentDatacenter且允许转发则会forward_to_datacenter把请求转到正确 DC 重试——这解释了为何默认不指定datacenter时系统能自动将 Actor 创建到正确的位置。六、错误码速查get_or_create 可能触发的典型错误定义于 pegboard/src/errors.rs错误 code触发条件empty_keykey为空字符串key_too_largekey超过 1024 字节duplicate_keykey 冲突并发下会被 api-peer 自动兜底key_reserved_in_different_datacenterkey 已预留到其他 DC且请求限制了 DC 或无法转发no_runner_config_configured任何 DC 都没有配置匹配runner_name_selector的 Runnercreation_rate_limit同一 namespace 内创建速率超限destroyed_during_creation创建过程中 Actor 被销毁namespace_not_foundnamespace 名称无法解析七、实战示例Rust SDK 中的幂等获取结合前文一个完整的调用示例如下类型与函数来自 api-full Rust 客户端use rivet_api_full::apis::{configuration::Configuration, actors_get_or_create_api}; use rivet_api_full::models::{ActorsGetOrCreateRequest, CrashPolicy}; let config Configuration { base_path: http://localhost.to_string(), bearer_access_token: Some(YOUR_TOKEN.to_string()), ..Default::default() }; let request ActorsGetOrCreateRequest::new( CrashPolicy::Restart, // 崩溃后重启 session-42.to_string(), // key业务唯一键 chat-room.to_string(), // nameActor 名称 default.to_string(), // runner_name_selectorRunner 配置池 ); // datacenter 与 input 为可选字段可后续设置 // request.datacenter Some(Some(dc-1.to_string())); // request.input Some(Some(base64::encode(initial_payload))); let resp actors_get_or_create_api::actors_get_or_create( config, my-namespace, request, ).await?; if resp.created { // 首次创建初始化状态、推送初始数据 println!(created actor {}, resp.actor.actor_id); } else { // 复用已有 Actor直接连接 println!(reusing actor {}, resp.actor.actor_id); }要点回顾不传datacenter时系统依据runner_name_selector自动选择启用了对应 Runner 配置的 DC相同的namespace name key重复调用只会返回同一个 Actor若确实需要跨 DC 创建如按用户地域就近放置显式传datacenter可控制放置位置但要留意 key 一旦预留即与 DC 绑定见 ACTOR_KEY_RESERVATION.md。八、小结actors_get_or_create是 Rivet Actors 中最实用的拿引用原语它把查 建两步合并为一次幂等 PUT 请求通过 Epoxy 的全局 key 预留保证跨数据中心的一致性并用created标志让调用方精确区分首次创建与复用命中。理解其 Datacenter Round Trips 与底层get_for_key/create/ 转发链路的实现有助于你在设计多数据中心 Actor 架构时做出更合理的放置与容错决策。如需深入可继续阅读 ActorsCreateApi.md对比无条件创建、Actor.mdActor 对象全字段以及 ACTOR_LIFECYCLE.mdActor 从创建、运行、休眠到销毁的完整时序。【免费下载链接】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),仅供参考