Loading...
Loading...
RivetKit Rust client guidance. Use for Rust clients and backends that connect to Rivet Actors with rivetkit::client, create typed actor handles, call actions, or manage connections.
npx skill4agent add rivet-dev/skills rivetkit-client-rustrivetkit::clientcargo add rivetkit anyhow async-trait
cargo add serde --features derive
cargo add tokio --features fullClient::new(ClientConfig::new(endpoint))get_or_create_typed_default::<A>(...)anyhow::Result?matchrivetkitrivetkit::clienthello-world-rustrivetkitcargo add rivetkit anyhow async-trait
cargo add serde --features derive
cargo add tokio --features fullsrc/lib.rsuse counter::{Counter, Increment};
use rivetkit::{
client::{Client, ClientConfig},
prelude::*,
TypedClientExt,
};
#[tokio::main]
async fn main() -> Result<()> {
let client = Client::new(ClientConfig::new("http://localhost:6420").namespace("default"));
let counter = client.get_or_create_typed_default::<Counter>("counter", ["my-counter"])?;
let count = counter.send(Increment { amount: 1 }).await?;
println!("New count: {count}");
Ok(())
}counternameCargo.tomlCounterIncrementuse counter::{Counter, Increment, NewCount};
use rivetkit::{
client::{Client, ClientConfig},
prelude::*,
TypedClientExt,
};
#[tokio::main]
async fn main() -> Result<()> {
let client = Client::new(ClientConfig::new("http://localhost:6420").namespace("default"));
let counter = client.get_or_create_typed_default::<Counter>("counter", ["my-counter"])?;
// Stateless: each call is independent
counter.send(Increment { amount: 1 }).await?;
// Stateful: keep a connection open for realtime events
let connection = counter.connect();
connection
.on::<NewCount>(|event| println!("count: {}", event.count))
.await;
connection.send(Increment { amount: 1 }).await?;
connection.disconnect().await;
Ok(())
}use counter::Counter;
use rivetkit::{
client::{Client, ClientConfig, GetOrCreateOptions},
prelude::*,
TypedClientExt,
};
use serde_json::json;
#[tokio::main]
async fn main() -> Result<()> {
let client = Client::new(ClientConfig::new("http://localhost:6420").namespace("default"));
// Get or create an actor
let room = client.get_or_create_typed_default::<Counter>("counter", ["room-42"])?;
// Get an existing actor handle (fails when used if the actor does not exist)
let existing = client.get_typed_default::<Counter>("counter", ["room-42"])?;
// Create a new actor with input
let created = client.get_or_create_typed::<Counter>(
"counter",
["game-1"],
GetOrCreateOptions {
create_with_input: Some(json!({ "mode": "ranked" })),
..Default::default()
},
)?;
// Get an actor handle by ID
let by_id = client.get_for_id("counter", "actor-id", Default::default())?;
// Resolve the actor ID
let resolved_id = room.inner().resolve().await?;
println!("Resolved ID: {resolved_id}");
Ok(())
}get_typed_defaultget_or_create_typed_defaultget_typedget_or_create_typedGetOptionsGetOrCreateOptionscreate_conn_stateuse counter::Counter;
use rivetkit::{
client::{Client, ClientConfig, GetOrCreateOptions},
prelude::*,
TypedClientExt,
};
use serde_json::json;
#[tokio::main]
async fn main() -> Result<()> {
let client = Client::new(ClientConfig::new("http://localhost:6420").namespace("default"));
let chat = client.get_or_create_typed::<Counter>(
"counter",
["general"],
GetOrCreateOptions {
params: Some(json!({ "authToken": "jwt-token-here" })),
..Default::default()
},
)?;
let connection = chat.connect();
connection.disconnect().await;
Ok(())
}onuse counter::{Counter, NewCount};
use rivetkit::{
client::{Client, ClientConfig},
prelude::*,
TypedClientExt,
};
#[tokio::main]
async fn main() -> Result<()> {
let client = Client::new(ClientConfig::new("http://localhost:6420").namespace("default"));
let connection = client
.get_or_create_typed_default::<Counter>("counter", ["general"])?
.connect();
connection
.on::<NewCount>(|event| println!("count changed: {}", event.count))
.await;
Ok(())
}NewCountconnection.inner()use counter::Counter;
use rivetkit::{
client::{Client, ClientConfig},
prelude::*,
TypedClientExt,
};
#[tokio::main]
async fn main() -> Result<()> {
let client = Client::new(ClientConfig::new("http://localhost:6420").namespace("default"));
let connection = client
.get_or_create_typed_default::<Counter>("counter", ["general"])?
.connect();
let inner = connection.inner().clone();
inner.on_open(|| println!("connected")).await;
inner.on_close(|| println!("disconnected")).await;
inner.on_error(|message| eprintln!("error: {message}")).await;
inner
.on_status_change(|status| println!("status: {status:?}"))
.await;
println!("current status: {:?}", inner.conn_status());
connection.disconnect().await;
Ok(())
}ConnectionStatusIdleConnectingConnectedDisconnecteddisconnecton_requeston_websockethandle.inner()fetchreqwest::Responseweb_sockettokio_tungstenitecargo add futures-util tokio-tungstenite
cargo add reqwest --features jsonuse counter::Counter;
use futures_util::{SinkExt, StreamExt};
use reqwest::{header::HeaderMap, Method};
use rivetkit::{
client::{Client, ClientConfig},
prelude::*,
TypedClientExt,
};
use tokio_tungstenite::tungstenite::Message;
#[tokio::main]
async fn main() -> Result<()> {
let client = Client::new(ClientConfig::new("http://localhost:6420").namespace("default"));
let handle = client.get_or_create_typed_default::<Counter>("counter", ["general"])?;
// Raw HTTP request
let response = handle
.inner()
.fetch("history", Method::GET, HeaderMap::new(), None)
.await?;
let history: Vec<String> = response.json().await?;
println!("history: {history:?}");
// Raw WebSocket connection
let mut ws = handle.inner().web_socket("stream", None).await?;
ws.send(Message::text("hello")).await?;
if let Some(message) = ws.next().await {
println!("received: {:?}", message?);
}
Ok(())
}Cloneuse counter::{Counter, Increment};
use rivetkit::{
client::{Client, ClientConfig},
prelude::*,
TypedClientExt,
};
async fn increment(client: Client) -> Result<i64> {
let counter = client.get_or_create_typed_default::<Counter>("counter", ["server-counter"])?;
let count = counter.send(Increment { amount: 1 }).await?;
Ok(count)
}anyhow::Resultanyhow::Erroruse counter::{Counter, Increment};
use rivetkit::{
client::{Client, ClientConfig},
prelude::*,
TypedClientExt,
};
#[tokio::main]
async fn main() -> Result<()> {
let client = Client::new(ClientConfig::new("http://localhost:6420").namespace("default"));
let counter = client.get_or_create_typed_default::<Counter>("counter", ["my-counter"])?;
match counter.send(Increment { amount: 1 }).await {
Ok(count) => println!("count: {count}"),
Err(error) => eprintln!("action failed: {error:#}"),
}
Ok(())
}use counter::Counter;
use rivetkit::{
client::{Client, ClientConfig},
prelude::*,
TypedClientExt,
};
#[tokio::main]
async fn main() -> Result<()> {
let client = Client::new(ClientConfig::new("http://localhost:6420").namespace("default"));
// Compound key: [org, room]
let room = client.get_or_create_typed_default::<Counter>("counter", ["org-acme", "general"])?;
let actor_id = room.inner().resolve().await?;
println!("Actor ID: {actor_id}");
Ok(())
}&strString["org-acme", "general"]format!("org:{user_id}")user_idClientConfig::new(endpoint)use rivetkit::client::ClientConfig;
let config = ClientConfig::new("http://localhost:6420")
.namespace("default")
.token("pk_...")
.pool_name("my-pool")
.header("x-custom", "value");namespacetokenpool_nameheaderheadersmax_input_size/api/rivetnpx skills add rivet-dev/skillsrivetkit