Overview
The Restate Python SDK is open source and can be found on GitHub: (sdk-python repo).
Have a look at the Python Quickstart!
Add the restate_sdk
requirement to your Python 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 restatefrom restate import Context, Servicemy_service = Service("MyService")@my_service.handler("myHandler")async def my_service_handler(ctx: Context, greeting: str) -> str:return f"${greeting}!"app = restate.app([my_service])
- Initialize a
Service
and specify the service name (hereMyService
). - The service definition contains a list of handlers.
Each handler is annotated by
@service_name.handler()
, optionally you can override the name of the handler (heremyHandler
). This is the name that will be used to call the handler, here you would use<RESTATE_INGRESS_URL>/MyService/myHandler
. - The function has the Restate Context as its first argument.
Within the handler, you use the
Context
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 argument (at most one) and return type are optional and can be of any primitive type or a
TypedDict
. They need to be serializable withjson.dumps
and deserializable withjson.loads
. If not, you need to specify a custom serializer. - Finally, initialize the app and bind the service(s) to it. The SDK follows the ASGI standard to serve the app. The templates and examples use Hypercorn as the server. Have a look at the serving docs to learn more.
Virtual Objects
Virtual Objects and their handlers are defined similarly to services, with the following differences:
import restatefrom restate import VirtualObject, ObjectContext, ObjectSharedContextmy_virtual_object = VirtualObject("MyVirtualObject")@my_virtual_object.handler("myHandler")async def my_object_handler(ctx: ObjectContext, greeting: str) -> str:return f"${greeting} ${ctx.key()}!"@my_virtual_object.handler(kind="shared")async def my_concurrent_handler(ctx: ObjectSharedContext, greeting: str) -> str:return f"${greeting} ${ctx.key()}!"app = restate.app([my_virtual_object])
- Initialize a
VirtualObject
and specify the object's name (hereMyVirtualObject
). - 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, 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, add
kind="shared"
as annotation argument 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 restatefrom restate import Workflow, WorkflowSharedContext, WorkflowContextfrom restate.serde import Serdemy_workflow = Workflow("MyWorkflow")@my_workflow.main()async def run(ctx: WorkflowContext, req: str) -> str:# ... implement workflow logic here ---return "success"@my_workflow.handler()async def interact_with_workflow(ctx: WorkflowSharedContext, req: str):# ... implement interaction logic here ...returnapp = restate.app([my_workflow])
- Initialize a
Workflow
and specify its name (hereMyWorkflow
). - Every workflow implementation needs to have a handler annotated with
@workflow_name.main()
calledrun
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.