-
Notifications
You must be signed in to change notification settings - Fork 709
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add documentation for actor reentrancy (#1483)
* Add documentation for actor reentrancy #1482 * Incoporate PR feedback Co-authored-by: Aaron Crawfis <Aaron.Crawfis@microsoft.com> * Add link from preview feature to reentrancy * Update daprdocs/content/en/developing-applications/building-blocks/actors/actor-reentrancy.md Co-authored-by: Aaron Crawfis <Aaron.Crawfis@microsoft.com>
- Loading branch information
1 parent
f910dfc
commit b404b94
Showing
3 changed files
with
97 additions
and
1 deletion.
There are no files selected for viewing
94 changes: 94 additions & 0 deletions
94
...s/content/en/developing-applications/building-blocks/actors/actor-reentrancy.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
--- | ||
type: docs | ||
title: "How-to: Enable and use actor reentrancy in Dapr" | ||
linkTitle: "How-To: Actor reentrancy" | ||
weight: 30 | ||
description: Learn more about actor reentrancy | ||
--- | ||
|
||
{{% alert title="Preview feature" color="warning" %}} | ||
Actor reentrancy is currently in [preview]({{< ref preview-features.md >}}). | ||
{{% /alert %}} | ||
|
||
## Actor reentrancy | ||
A core tenet of the virtual actor pattern is the single-threaded nature of actor execution. Before reentrancy, this caused the Dapr runtime to lock an actor on any given request. A second request could not start until the first had completed. This behavior means an actor cannot call itself, or have another actor call into it even if it is part of the same chain. Reentrancy solves this by allowing requests from the same chain or context to re-enter into an already locked actor. Examples of chains that reentrancy allows can be seen below: | ||
|
||
``` | ||
Actor A -> Actor A | ||
ActorA -> Actor B -> Actor A | ||
``` | ||
|
||
With reentrancy, there can be more complex actor calls without sacrificing the single-threaded behavior of virtual actors. | ||
|
||
## Enabling actor reentrancy | ||
Actor reentrancy is currently in preview, so enabling it is a two step process. | ||
|
||
### Preview feature configuration | ||
Before using reentrancy, the feature must be enabled in Dapr. For more information on preview configurations, see [the full guide on opting into preview features in Dapr]({{< ref preview-features.md >}}). Below is an example of the configuration for actor reentrancy: | ||
|
||
```yaml | ||
apiVersion: dapr.io/v1alpha1 | ||
kind: Configuration | ||
metadata: | ||
name: reentrantconfig | ||
spec: | ||
features: | ||
- name: Actor.Reentrancy | ||
enabled: true | ||
``` | ||
|
||
### Actor runtime configuration | ||
Once actor reentrancy is enabled as an opt-in preview feature, the actor that will be reentrant must also provide the appropriate configuration to use reentrancy. This is done by the actor's endpoint for `GET /dapr/config`, similar to other actor configuration elements. Here is a snipet of an actor written in Golang providing the configuration: | ||
|
||
```go | ||
type daprConfig struct { | ||
Entities []string `json:"entities,omitempty"` | ||
ActorIdleTimeout string `json:"actorIdleTimeout,omitempty"` | ||
ActorScanInterval string `json:"actorScanInterval,omitempty"` | ||
DrainOngoingCallTimeout string `json:"drainOngoingCallTimeout,omitempty"` | ||
DrainRebalancedActors bool `json:"drainRebalancedActors,omitempty"` | ||
Reentrancy config.ReentrancyConfig `json:"reentrancy,omitempty"` | ||
} | ||
|
||
var daprConfigResponse = daprConfig{ | ||
[]string{defaultActorType}, | ||
actorIdleTimeout, | ||
actorScanInterval, | ||
drainOngoingCallTimeout, | ||
drainRebalancedActors, | ||
config.ReentrancyConfig{Enabled: true, MaxStackDepth: &maxStackDepth}, | ||
} | ||
|
||
func configHandler(w http.ResponseWriter, r *http.Request) { | ||
w.Header().Set("Content-Type", "application/json") | ||
w.WriteHeader(http.StatusOK) | ||
json.NewEncoder(w).Encode(daprConfigResponse) | ||
} | ||
``` | ||
|
||
### Handling reentrant requests | ||
The key to a reentrant request is the `Dapr-Reentrancy-Id` header. The value of this header is used to match requests to their call chain and allow them to bypass the actor's lock. | ||
|
||
The header is generated by the Dapr runtime for any actor request that has a reentrant config specified. Once it is generated, it is used to lock the actor and must be passed to all future requests. Below is a snippet of code from an actor handling this is Golang: | ||
|
||
```go | ||
func reentrantCallHandler(w http.ResponseWriter, r *http.Request) { | ||
/* | ||
* Omitted. | ||
*/ | ||
|
||
req, _ := http.NewRequest("PUT", url, bytes.NewReader(nextBody)) | ||
|
||
reentrancyID := r.Header.Get("Dapr-Reentrancy-Id") | ||
req.Header.Add("Dapr-Reentrancy-Id", reentrancyID) | ||
|
||
client := http.Client{} | ||
resp, err := client.Do(req) | ||
|
||
/* | ||
* Omitted. | ||
*/ | ||
} | ||
``` | ||
|
||
Currently, no SDK supports actor reentrancy. In the future, the method for handling the reentrancy id may be different based on the SDK that is being used. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters