Expand description
§memable
An embeddable durable execution engine for Rust.
Unlike platforms such as Temporal or Restate, memable is a library — it runs inside your process with zero external dependencies. Workflows recover via key-based memoisation rather than positional replay, so you can deploy new code, fix bugs, and selectively re-execute steps without breaking in-flight workflows.
§Quick start
use memable::{Engine, Context, EngineError, WorkflowState};
async fn greet(ctx: Context) -> Result<(), EngineError> {
let name: String = ctx.step("fetch-name:v1").run(async || {
Ok("world".to_string())
}).await?;
let message: String = ctx.step("format-greeting:v1").run(async move || {
Ok(format!("Hello, {name}!"))
}).await?;
assert_eq!(message, "Hello, world!");
Ok(())
}
let mut engine = Engine::builder().in_memory().build();
engine.register("greet", greet);
engine.start().await?;
let state = engine.invoke("greet").await?.wait().await;
assert_eq!(state, WorkflowState::Completed(None));§Automatic retry
Steps that return StepError::Retryable are retried automatically
when a RetryPolicy is configured. Permanent errors bypass retries.
use std::time::Duration;
use memable::{Engine, Context, EngineError, StepError, RetryPolicy, WorkflowState};
let mut engine = Engine::builder()
.in_memory()
.default_retry(RetryPolicy::exponential(3, Duration::from_secs(1)))
.build();
engine.register("fetch", |ctx: Context| async move {
let data: String = ctx.step("call-api:v1")
.run(async || {
// Returning Retryable triggers automatic retry with backoff.
// Returning Permanent would fail immediately.
Ok("response".to_string())
}).await?;
Ok(())
});
engine.start().await?;
let state = engine.invoke("fetch").await?.wait().await;
assert_eq!(state, WorkflowState::Completed(None));§Closure captures
Step closures use AsyncFnMut bounds to support retry. Closures that
capture variables from the workflow scope need async move || with
owned values — clone shared state before each closure:
let counter = Arc::new(AtomicU32::new(0));
let c = Arc::clone(&counter);
let _: u32 = ctx.step("count:v1").run(async move || {
Ok(c.fetch_add(1, Ordering::Relaxed))
}).await?;Structs§
- Context
- Workflow execution context.
- Engine
- The durable execution engine.
- Engine
Builder - Builder for configuring and constructing an
Engine. - Invocation
- Handle for a running workflow instance.
- Invocation
Builder - Builder for invoking a workflow with optional typed input.
- Retry
Policy - Configures automatic retry behavior for a step.
- Status
Stream - A stream of
WorkflowStateupdates for a workflow instance. - Step
Builder - Builder for a durable step with optional timeout.
- Suspend
Builder - Builder for a suspend point with optional status message.
- Suspend
Point - A typed suspend point that encodes both the step key and payload type.
- Workflow
Metadata - Metadata record for a workflow instance.
Enums§
- Engine
Error - Errors originating from the engine itself.
- Metadata
Status - Lifecycle status of a workflow instance.
- State
Error - Error returned by
Engine::state. - Step
Error - Error returned by step closures.
- Subscribe
Error - Error returned by
Engine::subscribe. - Workflow
State - Observable state of a workflow instance.