Overview
The Restate TypeScript SDK is open source and can be found on GitHub: (sdk-typescript repo).
Have a look at the TypeScript Quickstart!
Add the @restatedev/restate-sdk
dependency to your project to start developing Restate services.
The Restate SDK lets you implement handlers. Handlers can either be part of a Service, a Virtual Object, or a Workflow. Let's have a look at how to define them.
Services
Services and their handlers are defined as follows:
import * as restate from "@restatedev/restate-sdk";import { Context } from "@restatedev/restate-sdk";const myService = restate.service({name: "MyService",handlers: {myHandler: async (ctx: Context, greeting: string) => {return `${greeting}!`;},},});export const MyService: typeof myService = { name: "MyService" };restate.endpoint().bind(myService).listen();
- Specify that you want to create a Service via
restate.service
. - Specify the service name. The service can then be called at
<RESTATE_INGRESS_URL>/MyService/myHandler
. - The service definition contains a list of handlers.
Each handler has a name (
myHandler
) and a function that implements the handler logic. The function has the Restate Context as its first argument. Within the handler, you use theContext
to interact with Restate. The SDK stores the actions you do on the context in the Restate journal to make them durable. - The handler input parameter (at most one) and return type are optional and can be of any type, as long as they can be serialized as a Buffer with
Buffer.from(JSON.stringify(yourObject))
and deserialized withJSON.parse(result.toString()) as T
. - Export the service definition
MyService
so that it can be used by other handlers to call the service. (See Service Communication docs.) - Finally, create an endpoint and bind the service(s) to the Restate endpoint. Listen on the specified port (default
9080
) for connections and requests.
Virtual Objects
Virtual Objects and their handlers are defined similarly to services, with the following differences:
import * as restate from "@restatedev/restate-sdk";import {handlers,ObjectContext,ObjectSharedContext,} from "@restatedev/restate-sdk";const myVirtualObject = restate.object({name: "MyVirtualObject",handlers: {myHandler: async (ctx: ObjectContext, greeting: string) => {return `${greeting} ${ctx.key}!`;},myConcurrentHandler: handlers.object.shared(async (ctx: ObjectSharedContext, greeting: string) => {return `${greeting} ${ctx.key}!`;}),},});export const MyVirtualObject: typeof myVirtualObject = {name: "MyVirtualObject",};restate.endpoint().bind(myVirtualObject).listen();
- Specify that you want to create a Virtual Object via
restate.object
. - The first argument of each handler must be the
ObjectContext
parameter. Handlers with theObjectContext
parameter can write to the K/V state store. Only one handler can be active at a time per object, to ensure consistency. - You can retrieve the key of the object you are in via
ctx.key
. - If you want to have a handler that executes concurrently to the others and doesn't have write access to the K/V state, wrap the handler in
handlers.object.shared
and use theObjectSharedContext
. You can use these handlers, for example, to read K/V state and expose it to the outside world, or to interact with the blocking handler (e.g. resolve awakeables).
Workflows
Workflows are a special type of Virtual Objects, their definition is similar but with the following differences:
import * as restate from "@restatedev/restate-sdk";import {WorkflowContext,WorkflowSharedContext,} from "@restatedev/restate-sdk";const myWorkflow = restate.workflow({name: "MyWorkflow",handlers: {run: async (ctx: WorkflowContext, req: string) => {// implement workflow logic herereturn "success";},interactWithWorkflow: async (ctx: WorkflowSharedContext) => {// implement interaction logic here// e.g. resolve a promise that the workflow is waiting on},},});export const MyWorkflow: typeof myWorkflow = { name: "MyWorkflow" };restate.endpoint().bind(myWorkflow).listen();
- Create the workflow with
restate.workflow
. - Every workflow implementation needs to have a handler called
run
that implements the workflow logic. This handler uses theWorkflowContext
to interact with the SDK. Therun
handler executes exactly one time per workflow execution/object. - The other handlers of the workflow are used to interact with the workflow: either query it, or signal it.
They use the
WorkflowSharedContext
to interact with the SDK. These handlers can run concurrently with therun
handler and can still be called after therun
handler has finished. - Have a look at the workflow docs to learn more.
Now that you have a high-level idea of what a Restate service might look like, let's have a look at what the Restate Context allows you to do.