Skip to main content

Managing Invocations

An invocation is a request to execute a handler that is part of either a service, or a virtual object. There are different ways to invoke a handler: by sending a request to Restate over HTTP, by using the SDK clients, or via Kafka events.

Once an invocation is created, you can inspect it, cancel it, and kill it via its Invocation Identifier:

Invocation identifier

Restate assigns an identifier to every invocation, the Invocation ID. You can use this Invocation ID to inspect the invocation via the CLI, filter the logs, find traces, cancel it, etc.

The invocation ID starts with inv_, and can be found in the logs and traces (restate.invocation.id), for example:

TypeScript
Java

[restate] [CartObject/expireTicket][inv_1gdJBtdVEcM942bjcDmb1c1khoaJe11Hbz][2024-03-18T16:14:24.671Z] DEBUG: Invoking function.

Or you can use the CLI to list the invocations and retrieve the ID from there:


restate inv ls

Output

❯ [2024-04-16 15:28:20.237 +02:00] inv_1aiqX0vFEFNH0TF1pLRFBDFosQCCTAN1M5 [CartObject @ Mary]::addTicket
Status: backing-off (4 minutes, 42 seconds and 653 ms. Retried 32 time(s). Next
retry in in 9 seconds and 469 ms))
Deployment: dp_14LsPzGz9HBxXIeBoH5wYUh [required]
Error: [2024-04-16 15:33:01.930 +02:00]
[500] Failing
Showing 1/1 invocations. Query took 86.295361ms

Cancelling invocations

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.

You can cancel the invocation with its ID (docs) using the CLI:


restate inv cancel inv_1gdJBtdVEcM942bjcDmb1c1khoaJe11Hbz

You can also use the abbreviation rm instead of cancel.

Implement compensation logic

To roll back correctly, the handlers need to contain the necessary compensation logic. This way, the service state stays consistent even in the presence of cancellations. Have a look at this blog post on how to implement compensation logic with Restate.

info

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.

How does cancellation work?

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.

Killing invocations

Sometimes Restate cannot cancel an invocation. For example, when an endpoint is permanently unavailable, Restate can't invoke the handler to run its compensation logic, so it can't complete the cancellation. For these cases, you can kill invocations.

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


restate inv cancel --kill inv_1gdJBtdVEcM942bjcDmb1c1khoaJe11Hbz

You can also use the abbreviation rm instead of cancel.

warning

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

Watch out for inconsistency

Killing an invocation immediately stops every call in the call tree of the invocation. Handlers will not execute compensation logic. This might leave the service instance in an inconsistent state. Use it with caution and try fixing the invocation in other ways before resorting to killing it.

Managing Kafka subscriptions

Restate can trigger handlers via Kafka events.

  • Create subscriptions for a handler on a topic via:

curl localhost:9070/subscriptions -H 'content-type: application/json' \
-d '{
"source": "kafka://my-cluster/my-topic",
"sink": "service://MyService/Handle",
"options": {"auto.offset.reset": "earliest"}
}'

The options field is optional and accepts any configuration parameter from librdkafka configuration.

  • List the current subscriptions via:

curl localhost:9070/subscriptions

Output

{
"subscriptions": [
{
"id": "sub_11XHoawrCiWtv8kzhEyGtsR",
"source": "kafka://my-cluster/my-topic",
"sink": "service://Greeter/greet",
"options": {
"auto.offset.reset": "earliest",
"client.id": "restate",
"group.id": "sub_11XHoawrCiWtv8kzhEyGtsR"
}
}
]
}

The creation and listing of subscriptions returns an identifier.

  • Delete a subscription with its identifier (starting with sub_) via:

curl -X DELETE localhost:9070/subscriptions/sub_11XHoawrCiWtv8kzhEyGtsR

info

When you delete a subscription, Restate stops the consumer group associated to it. Any messages that were already enqueued by Restate will still be processed.