Skip to main content

Invocation

An invocation is a single call to a service method.

Invoking Restate services​

There are different ways to invoke a Restate service:

Over HTTP​

You can invoke services over HTTP 1.1 or higher. Request/response bodies should be encoded as either JSON or Protobuf. You can send requests directly from the browser or via curl without generating a client.

For the handler API, you invoke the function with a payload with the request and an optional key (for keyed services) fields. For example, to invoke the function greet of the service greeter using curl:

curl <RESTATE_INGRESS_URL>/<SERVICE_NAME>/<FUNCTION_NAME> \
-H 'content-type: application/json' \
-d '{"key": "<KEY_OF_KEYED_SERVICE>", "request": <REQUEST_DATA>}}'

The service name is the one specified when binding the service to the HTTP deployment server, and the function name is the one specified when binding the function to the service. For unkeyed services, drop the key field from the request.

Restate relies on the fields being named key and request, so do not use other names here.

For example, to call the greet function of a keyed service greeter that takes a request of the form {age: number}:

curl localhost:8080/greeter/greet \
-H 'content-type: application/json' \
-d '{"key": "John Doe", "request": {"age": 55}}'
Protobuf-encoded request bodies

If the request body is encoded with Protobuf, use Content-Type: application/proto as the header. The response body will have the same content type as the request.

note

This follows the Connect Protocol, allowing you to send gRPC-like requests as regular HTTP requests. For more details, check out the Connect documentation.

Over gRPC and gRPC-web​

You can send requests to your services as regular gRPC requests.

You can use any gRPC code generator to generate a gRPC client to invoke a Restate service. Check out the awesome-grpc page for a comprehensive list of clients, code generators and tools.

For example, to invoke the service org.example.Greeter method Greet using grpcurl:

grpcurl -plaintext -d '{"name": "Restate"}' <RESTATE_INGRESS_URL> org.example.Greeter/Greet

Restate supports gRPC reflections, hence some tools like grpcurl will automatically discover the protobuf definitions of the services to invoke.

For example, to query the available services in the runtime:

grpcurl -plaintext <RESTATE_INGRESS_URL> describe

Restate also natively supports gRPC-web. You can use a gRPC-web code generator and point it directly to Restate, without using a 3rd party proxy to translate gRPC-web to gRPC.

Invoke a service idempotently​

You can send requests to Restate providing an idempotency key, through the Idempotency-Key header:

curl <RESTATE_INGRESS_URL>/org.example.Greeter/Greet \
-H 'idempotency-key: <IDEMPOTENCY_KEY>' \
-H 'content-type: application/json' \
-d '{"name": "Restate"}'

After the invocation completes, Restate persists the response for a retention period of 30 minutes. If you re-invoke the service with the same idempotency key within 30 minutes, Restate sends back the same response and doesn't re-execute the request to the service.

You can tune the retention period by setting the header idempotency-retention-period: <seconds>

The Idempotency-Key header works with both HTTP and gRPC/gRPC-web.

Invoke a service without waiting for the response​

You can invoke a service without waiting for the response, similar to one-way calls in the SDK (TypeScript docs or Java docs), by using the Restate built-in dev.restate.Ingress/Invoke service method, which can be invoked like any other user service, using gRPC, gRPC-web or Connect.

For example, using HTTP and curl:

curl <RESTATE_INGRESS_URL>/dev.restate.Ingress/Invoke \
-H 'content-type: application/json' \
-d '{"service": "org.example.Greeter", "method": "Greet", "argument": {"name": "Restate"}}'

The response contains the Invocation identifier. You can use this identifier to cancel or kill the invocation as described in the below paragraph.

For the complete documentation of the dev.restate.Ingress built-in service, check out the Restate protobuf definitions.

tip

This feature can be especially useful when you need to invoke a service method implementing a long-running workflow.

Private services​

When registering a service deployment, every service is by default accessible both by other services, and by sending requests to Restate using HTTP and/or gRPC. You can configure a service as private, such that you can't invoke it by sending requests to Restate, through the Admin APIs:

curl -X PATCH <RESTATE_ADMIN_URL>/services/<SERVICE_NAME> \
-H 'content-type: application/json' \
-d '{"public": false}'

For example:

curl -X PATCH localhost:9070/services/org.example.ExampleService \
-H 'content-type: application/json' \
-d '{"public": false}'

You can revert it back to public with {"public": true}. Private services can still be reached by other Restate services. For more details on the API, refer to the admin API docs.

Invocation identifier​

Every invocation to a service gets a unique identifier assigned by Restate, called Invocation identifier. You can use this identifier to filter your structured logs, find traces, and execute some management operations such as cancelling an invocation.

You can find this identifier in the runtime logs and OpenTelemetry traces by looking for the restate.invocation.id, for example:

2023-05-19T15:02:28.656467Z INFO restate_invoker::invocation_task
Executing invocation at deployment
http.url: http://localhost:9080/invoke/coordinator.Coordinator/Sleep
in restate_invoker::invocation_task::invoker_invocation_task
rpc.system: "restate"
rpc.service: coordinator.Coordinator
restate.invocation.id: T4pIkIJIGAsBiiGDV2dxK7PkkKnWyWHE
note

The Invocation identifier is opaque and its current format should not be relied on, as it might change in future Restate versions.

Cancel an invocation​

If an invocation takes too long to complete or is no longer of interest, you can cancel it. Canceling an invocation allows it to free any resources it is holding and roll back any changes it has made so far. In order to roll back changes correctly, the service handlers need to contain the necessary compensation logic. If the required compensation logic is implemented, then the service state stays consistent even in the presence of cancellations.

The cancellation process works recursively in the following way: First, Restate tries to cancel the leaves of the current invocation, i.e. interrupt ongoing sleeps and awakeables or try to cancel calls to other services. Once the leaves are canceled, a terminal error is thrown in the service handler at the point in the code that the invocation had reached. This allows the handler to run its specific compensation logic. The response of the handler will then be propagated back to its caller where it will continue with the cancellation process.

note

Canceling an invocation is a non-blocking operation. This means that the cancellation is not guaranteed to have completed when the API call returns. In some rare cases, cancellations will not have an effect. In these cases, users need to retry the operation.

Retrieve the invocation identifier from the logs or traces, or use the CLI:

restate inv ls

You can cancel an invocation using the CLI:

restate inv cancel <INVOCATION_IDENTIFIER>

You can also use the abbreviation rm instead of cancel.

Kill an invocation​

In a few cases, it is not possible for Restate to cancel an invocation. For example, if the service deployment is permanently unavailable, Restate cannot invoke the service handler to run its compensation logic which is needed to complete the cancellation. For these cases, Restate provides the ability to kill an invocation.

Killing an invocation means that every call in the call tree of the invocation will be stopped immediately without giving the service handler a chance to react and execute compensation logic. This entails that killing the invocation will not roll back its progress.

warning

One-way calls and delayed calls will not be killed because they are considered detached from the originating call tree.

danger

Killing an invocation might leave the service instance in an inconsistent state, just like how killing a process in your operating system may cause the open files to become corrupted. Use it with caution and try to fix the invocation in other ways before resorting to killing it.

Retrieve the invocation identifier from the logs or traces, or use the CLI:

restate inv ls

Kill the invocation by using cancel and the --kill flag:

restate inv cancel --kill <INVOCATION_IDENTIFIER>

You can also use the abbreviation rm instead of cancel.