restate
npx skills add https://github.com/schpet/toolbox --skill restate
Agent 安装分布
Skill 文档
Restate Durable Execution Framework
Restate is a durable execution framework that makes applications resilient to failures. Use this skill when building:
- Durable workflows with automatic retries
- Services with persisted state (Virtual Objects)
- Microservice orchestration with transactional guarantees
- Event processing with exactly-once semantics
- Long-running tasks that survive crashes
When to Use Restate
Use Restate when:
- Building workflows that must complete despite failures
- Need automatic retry and recovery without manual retry logic
- Building stateful services (shopping carts, user sessions, payment processing)
- Orchestrating multiple services with saga/compensation patterns
- Processing events with exactly-once delivery guarantees
- Scheduling durable timers and cron jobs
Core Concepts
Service Types
Restate supports three service types:
-
Services – Stateless handlers with durable execution
- Use for: microservice orchestration, sagas, idempotent requests
-
Virtual Objects – Stateful handlers with K/V state isolated per key
- Use for: entities (shopping cart), state machines, actors, stateful event processing
- Only one handler runs at a time per object key (consistency guarantee)
-
Workflows – Special Virtual Objects where
runhandler executes exactly once- Use for: order processing, human-in-the-loop, long-running provisioning
See Services Concepts for detailed comparison.
Durable Building Blocks
Restate provides these building blocks through the SDK context:
- Journaled actions (
ctx.run()) – Persist results of side effects - State (
ctx.get/set/clear) – K/V state for Virtual Objects - Timers (
ctx.sleep()) – Durable sleep that survives restarts - Service calls (
ctx.serviceClient()) – RPC with automatic retries - Awakeables – Wait for external events/signals
TypeScript SDK Quick Reference
Installation
npm install @restatedev/restate-sdk
Basic Service
import * as restate from "@restatedev/restate-sdk";
const myService = restate.service({
name: "MyService",
handlers: {
greet: async (ctx: restate.Context, name: string) => {
return "Hello, " + name + "!";
},
},
});
restate.endpoint().bind(myService).listen(9080);
Virtual Object (Stateful)
const counter = restate.object({
name: "Counter",
handlers: {
add: async (ctx: restate.ObjectContext, value: number) => {
const current = (await ctx.get<number>("count")) ?? 0;
ctx.set("count", current + value);
return current + value;
},
get: restate.handlers.object.shared(
async (ctx: restate.ObjectSharedContext) => {
return (await ctx.get<number>("count")) ?? 0;
}
),
},
});
Workflow
const paymentWorkflow = restate.workflow({
name: "PaymentWorkflow",
handlers: {
run: async (ctx: restate.WorkflowContext, payment: Payment) => {
// Step 1: Reserve funds
const reservation = await ctx.run("reserve", () =>
reserveFunds(payment)
);
// Step 2: Wait for approval (awakeable)
const approved = await ctx.promise<boolean>("approval");
if (!approved) {
await ctx.run("cancel", () => cancelReservation(reservation));
return { status: "cancelled" };
}
// Step 3: Complete payment
await ctx.run("complete", () => completePayment(reservation));
return { status: "completed" };
},
approve: async (ctx: restate.WorkflowSharedContext) => {
ctx.promise<boolean>("approval").resolve(true);
},
reject: async (ctx: restate.WorkflowSharedContext) => {
ctx.promise<boolean>("approval").resolve(false);
},
},
});
Key SDK Patterns
// Journaled action - result persisted, replayed on retry
const result = await ctx.run("action-name", async () => {
return await callExternalApi();
});
// Durable timer - survives restarts
await ctx.sleep(60_000); // 60 seconds
// Call another service
const client = ctx.serviceClient(OtherService);
const response = await client.handler(input);
// Async call (fire and forget)
ctx.serviceSendClient(OtherService).handler(input);
// Delayed call
ctx.serviceSendClient(OtherService, { delay: 60_000 }).handler(input);
// Awakeable - wait for external signal
const { id, promise } = ctx.awakeable<string>();
// Give `id` to external system, then:
const result = await promise;
// Random (deterministic)
const value = ctx.rand.random();
const uuid = ctx.rand.uuidv4();
Running Locally
- Start Restate server:
npx @restatedev/restate-server
- Run your service:
npx ts-node src/app.ts
- Register service with Restate:
npx @restatedev/restate deployments register http://localhost:9080
- Invoke handlers via HTTP:
# Service handler
curl localhost:8080/MyService/greet -H 'content-type: application/json' -d '"World"'
# Virtual Object handler (with key)
curl localhost:8080/Counter/user123/add -H 'content-type: application/json' -d '5'
# Start workflow
curl localhost:8080/PaymentWorkflow/order-456/run -H 'content-type: application/json' -d '{"amount": 100}'
Documentation References
Concepts
- Services – Service types and use cases
- Invocations – How invocations work
- Durable Execution – Execution guarantees
- Durable Building Blocks – SDK primitives
TypeScript SDK
- Overview – SDK setup and service definitions
- State – K/V state management
- Journaling Results – Side effects and
ctx.run() - Durable Timers – Sleep and scheduling
- Service Communication – Calling other services
- Awakeables – External events
- Workflows – Workflow implementation
- Error Handling – Error patterns
- Serving – Running services
- Testing – Testing strategies
- Clients – Client SDK
Guides
- Error Handling – Comprehensive error handling
- Sagas – Saga pattern with compensations
- Cron Jobs – Scheduled tasks
- Parallelizing Work – Fan-out patterns
- Databases – Database integration
- Lambda Deployment – AWS Lambda deployment
Use Cases
Operations
Important Guidelines
-
Side effects must be wrapped in
ctx.run()– External calls, random values, timestamps must go through the context to be journaled and replayed correctly. -
State access only in Virtual Objects/Workflows – Plain Services don’t have state access.
-
Handlers must be deterministic – Same inputs should produce same outputs. Use
ctx.randfor randomness. -
One handler per Virtual Object key at a time – Restate ensures consistency by queuing concurrent requests to the same key.
-
Workflows
runhandler executes exactly once – Use other handlers to query/signal the workflow. -
Register services after code changes – Run
restate deployments registerto update handler definitions.
Generated from Restate documentation. Run scripts/sync-docs.sh to update.
License
The content in the references/ directory is derived from the Restate documentation and TypeScript SDK.