Restate is a system for easily building resilient applications using distributed durable async/await. This repository contains the Restate SDK for writing services using Rust.
- 🤗️ Join our online community for help, sharing feedback and talking to the community.
- 📖 Check out our documentation to get quickly started!
- 📣 Follow us on Twitter for staying up to date.
- 🙋 Create a GitHub issue for requesting a new feature or reporting a problem.
- 🏠 Visit our GitHub org for exploring other repositories.
Add Restate and Tokio as dependencies:
[dependencies] restate-sdk = "0.1" tokio = { version = "1", features = ["full"] }Then you're ready to develop your Restate service using Rust:
use restate_sdk::prelude::*; #[restate_sdk::service] trait Greeter { async fn greet(name: String) -> HandlerResult<String>; } struct GreeterImpl; impl Greeter for GreeterImpl { async fn greet(&self, _: Context<'_>, name: String) -> HandlerResult<String> { Ok(format!("Greetings {name}")) } } #[tokio::main] async fn main() { // To enable logging/tracing // tracing_subscriber::fmt::init(); HttpServer::new( Endpoint::builder() .with_service(GreeterImpl.serve()) .build(), ) .listen_and_serve("0.0.0.0:9080".parse().unwrap()) .await; }The SDK uses tokio's tracing crate to generate logs. Just configure it as usual through tracing_subscriber to get your logs.
The SDK uses Testcontainers to support integration testing using a Docker-deployed restate server. The restate-sdk-testcontainers crate provides a framework for initializing the test environment, and an integration test example in testcontainers/tests/test_container.rs.
#[tokio::test] async fn test_container() { tracing_subscriber::fmt::fmt() .with_max_level(tracing::Level::INFO) // Set the maximum log level .init(); let endpoint = Endpoint::builder().bind(MyServiceImpl.serve()).build(); // simple test container intialization with default configuration //let test_container = TestContainer::default().start(endpoint).await.unwrap(); // custom test container initialization with builder let test_container = TestContainer::builder() // optional passthrough logging from the resstate server testcontainer // prints container logs to tracing::info level .with_container_logging() .with_container( "docker.io/restatedev/restate".to_string(), "latest".to_string(), ) .build() .start(endpoint) .await .unwrap(); let ingress_url = test_container.ingress_url(); // call container ingress url for /MyService/my_handler let response = reqwest::Client::new() .post(format!("{}/MyService/my_handler", ingress_url)) .header("Accept", "application/json") .header("Content-Type", "*/*") .header("idempotency-key", "abc") .send() .await .unwrap(); assert_eq!(response.status(), StatusCode::OK); info!( "/MyService/my_handler response: {:?}", response.text().await.unwrap() ); }The Rust SDK is currently in active development, and might break across releases.
The compatibility with Restate is described in the following table:
| Restate Server\sdk-rust | 0.0 - 0.2 | 0.3 | 0.4 - 0.5 | 0.6 |
|---|---|---|---|---|
| 1.0 | ✅ | ❌ | ❌ | ❌ |
| 1.1 | ✅ | ✅ | ❌ | ❌ |
| 1.2 | ✅ | ✅ | ❌ | ❌ |
| 1.3 | ✅ | ✅ | ✅ | ✅ (1) |
| 1.4 | ✅ | ✅ | ✅ | ✅ |
(1) Note bind_with_options works only from Restate 1.4 onward.
We’re excited if you join the Restate community and start contributing! Whether it is feature requests, bug reports, ideas & feedback or PRs, we appreciate any and all contributions. We know that your time is precious and, therefore, deeply value any effort to contribute!
Prerequisites:
To build and test the SDK:
just verifyYou need the Rust toolchain. To verify:
just verify To release we use cargo-release:
cargo release <VERSION> --exclude test-services --workspace