pub trait ContextAwakeables<'ctx>: SealedContext<'ctx> {
// Provided methods
fn awakeable<T: Deserialize + 'static>(
&self,
) -> (String, impl DurableFuture<Output = Result<T, TerminalError>> + Send + 'ctx) { ... }
fn resolve_awakeable<T: Serialize + 'static>(&self, key: &str, t: T) { ... }
fn reject_awakeable(&self, key: &str, failure: TerminalError) { ... }
}
Expand description
§Awakeables
Awakeables pause an invocation while waiting for another process to complete a task. You can use this pattern to let a handler execute a task somewhere else and retrieve the result. This pattern is also known as the callback (task token) pattern.
§Creating awakeables
- Create an awakeable. This contains a String identifier and a Promise.
- Trigger a task/process and attach the awakeable ID (e.g., over Kafka, via HTTP, …).
For example, send an HTTP request to a service that executes the task, and attach the ID to the payload.
You use
ctx.run
to avoid re-triggering the task on retries. - Wait until the other process has executed the task. The handler receives the payload and resumes.
/// 1. Create an awakeable
let (id, promise) = ctx.awakeable::<String>();
/// 2. Trigger a task
ctx.run(|| trigger_task_and_deliver_id(id.clone())).await?;
/// 3. Wait for the promise to be resolved
let payload = promise.await?;
§Completing awakeables
The external process completes the awakeable by either resolving it with an optional payload or by rejecting it with its ID and a reason for the failure. This throws a terminal error in the waiting handler.
- Resolving over HTTP with its ID and an optional payload:
curl localhost:8080/restate/awakeables/prom_1PePOqp/resolve
-H 'content-type: application/json'
-d '{"hello": "world"}'
- Rejecting over HTTP with its ID and a reason:
curl localhost:8080/restate/awakeables/prom_1PePOqp/reject
-H 'content-type: text/plain' \
-d 'Very bad error!'
- Resolving via the SDK with its ID and an optional payload, or rejecting with its ID and a reason:
// Resolve the awakeable
ctx.resolve_awakeable(&id, "hello".to_string());
// Or reject the awakeable
ctx.reject_awakeable(&id, TerminalError::new("my error reason"));
For more info about serialization of the payload, see crate::serde
When running on Function-as-a-Service platforms, such as AWS Lambda, Restate suspends the handler while waiting for the awakeable to be completed. Since you only pay for the time that the handler is actually running, you don’t pay while waiting for the external process to return.
Be aware: Virtual Objects only process a single invocation at a time, so the Virtual Object will be blocked while waiting on the awakeable to be resolved.
Provided Methods§
Sourcefn awakeable<T: Deserialize + 'static>(
&self,
) -> (String, impl DurableFuture<Output = Result<T, TerminalError>> + Send + 'ctx)
fn awakeable<T: Deserialize + 'static>( &self, ) -> (String, impl DurableFuture<Output = Result<T, TerminalError>> + Send + 'ctx)
Create an awakeable
Sourcefn resolve_awakeable<T: Serialize + 'static>(&self, key: &str, t: T)
fn resolve_awakeable<T: Serialize + 'static>(&self, key: &str, t: T)
Resolve an awakeable
Sourcefn reject_awakeable(&self, key: &str, failure: TerminalError)
fn reject_awakeable(&self, key: &str, failure: TerminalError)
Resolve an awakeable
Dyn Compatibility§
This trait is not dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.