service

Attribute Macro service 

Source
#[service]
Expand description

Entry-point macro to define a Restate Service.

use restate_sdk::prelude::*;

#[restate_sdk::service]
trait Greeter {
    async fn greet(name: String) -> Result<String, HandlerError>;
}

This macro accepts a trait as input, and generates as output:

  • A trait with the same name, that you should implement on your own concrete type (e.g. struct), e.g.:
struct GreeterImpl;
impl Greeter for GreeterImpl {
    async fn greet(&self, _: Context<'_>, name: String) -> Result<String, HandlerError> {
        Ok(format!("Greetings {name}"))
    }
}

This trait will additionally contain, for each handler, the appropriate Context, to interact with Restate.

  • An implementation of the Service trait, to bind the service in the Endpoint and expose it:
let endpoint = Endpoint::builder()
    // .serve() returns the implementation of Service used by the SDK
    //  to bind your struct to the endpoint
    .bind(GreeterImpl.serve())
    .build();
  • A client implementation to call this service from another service, object or workflow, e.g.:
let result = ctx
   .service_client::<GreeterClient>()
   .greet("My greetings".to_string())
   .call()
   .await?;

Methods of this trait can accept either no parameter, or one parameter implementing Deserialize. The return value MUST always be a Result. Down the hood, the error type is always converted to HandlerError for the SDK to distinguish between terminal and retryable errors. For more details, check the HandlerError doc.

When invoking the service through Restate, the method name should be used as handler name, that is:

use restate_sdk::prelude::*;

#[restate_sdk::service]
trait Greeter {
    async fn my_greet(name: String) -> Result<String, HandlerError>;
}

The Greeter/my_greet handler be invoked sending a request to http://<RESTATE_ENDPOINT>/Greeter/my_greet. You can override the names used by Restate during registration using the name attribute:

use restate_sdk::prelude::*;

#[restate_sdk::service]
#[name = "greeter"]
trait Greeter {
    // You can invoke this handler with `http://<RESTATE_ENDPOINT>/greeter/myGreet`
    #[name = "myGreet"]
    async fn my_greet(name: String) -> Result<String, HandlerError>;
}