mirror of https://github.com/dapr/docs.git
Merge branch 'v1.11' into issue_3216
This commit is contained in:
commit
4b0a175549
|
@ -264,6 +264,96 @@ A workflow implementing the monitor pattern can loop forever or it can terminate
|
|||
This pattern can also be expressed using actors and reminders. The difference is that this workflow is expressed as a single function with inputs and state stored in local variables. Workflows can also execute a sequence of actions with stronger reliability guarantees, if necessary.
|
||||
{{% /alert %}}
|
||||
|
||||
## External system interaction
|
||||
|
||||
In some cases, a workflow may need to pause and wait for an external system to perform some action. For example, a workflow may need to pause and wait for a payment to be received. In this case, a payment system might publish an event to a pub/sub topic on receipt of a payment, and a listener on that topic can raise an event to the workflow using the [raise event workflow API]({{< ref "howto-manage-workflow.md#raise-an-event" >}}).
|
||||
|
||||
Another very common scenario is when a workflow needs to pause and wait for a human, for example when approving a purchase order. Dapr Workflow supports this event pattern via the [external events]({{< ref "workflow-features-concepts.md#external-events" >}}) feature.
|
||||
|
||||
Here's an example workflow for a purchase order involving a human:
|
||||
|
||||
1. A workflow is triggered when a purchase order is received.
|
||||
1. A rule in the workflow determines that a human needs to perform some action. For example, the purchase order cost exceeds a certain auto-approval threshold.
|
||||
1. The workflow sends a notification requesting a human action. For example, it sends an email with an approval link to a designated approver.
|
||||
1. The workflow pauses and waits for the human to either approve or reject the order by clicking on a link.
|
||||
1. If the approval isn't received within the specified time, the workflow resumes and performs some compensation logic, such as canceling the order.
|
||||
|
||||
The following diagram illustrates this flow.
|
||||
|
||||
<img src="/images/workflow-overview/workflow-human-interaction-pattern.png" width=600 alt="Diagram showing how the external system interaction pattern works with a human involved"/>
|
||||
|
||||
The following example code shows how this pattern can be implemented using Dapr Workflow.
|
||||
|
||||
{{< tabs ".NET" >}}
|
||||
|
||||
{{% codetab %}}
|
||||
|
||||
```csharp
|
||||
public override async Task<OrderResult> RunAsync(WorkflowContext context, OrderPayload order)
|
||||
{
|
||||
// ...(other steps)...
|
||||
|
||||
// Require orders over a certain threshold to be approved
|
||||
if (order.TotalCost > OrderApprovalThreshold)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Request human approval for this order
|
||||
await context.CallActivityAsync(nameof(RequestApprovalActivity), order);
|
||||
|
||||
// Pause and wait for a human to approve the order
|
||||
ApprovalResult approvalResult = await context.WaitForExternalEventAsync<ApprovalResult>(
|
||||
eventName: "ManagerApproval",
|
||||
timeout: TimeSpan.FromDays(3));
|
||||
if (approvalResult == ApprovalResult.Rejected)
|
||||
{
|
||||
// The order was rejected, end the workflow here
|
||||
return new OrderResult(Processed: false);
|
||||
}
|
||||
}
|
||||
catch (TaskCanceledException)
|
||||
{
|
||||
// An approval timeout results in automatic order cancellation
|
||||
return new OrderResult(Processed: false);
|
||||
}
|
||||
}
|
||||
|
||||
// ...(other steps)...
|
||||
|
||||
// End the workflow with a success result
|
||||
return new OrderResult(Processed: true);
|
||||
}
|
||||
```
|
||||
|
||||
{{% alert title="Note" color="primary" %}}
|
||||
In the example above, `RequestApprovalActivity` is the name of a workflow activity to invoke and `ApprovalResult` is an enumeration defined by the workflow app. For brevity, these definitions were left out of the example code.
|
||||
{{% /alert %}}
|
||||
|
||||
{{% /codetab %}}
|
||||
|
||||
{{< /tabs >}}
|
||||
|
||||
The code that delivers the event to resume the workflow execution is external to the workflow. Workflow events can be delivered to a waiting workflow instance using the [raise event]({{< ref "howto-manage-workflow.md#raise-an-event" >}}) workflow management API, as shown in the following example:
|
||||
|
||||
{{< tabs ".NET" >}}
|
||||
|
||||
{{% codetab %}}
|
||||
|
||||
```csharp
|
||||
// Raise the workflow event to the waiting workflow
|
||||
await daprClient.RaiseWorkflowEventAsync(
|
||||
instanceId: orderId,
|
||||
workflowComponent: "dapr",
|
||||
eventName: "ManagerApproval",
|
||||
eventData: ApprovalResult.Approved);
|
||||
```
|
||||
|
||||
{{% /codetab %}}
|
||||
|
||||
{{< /tabs >}}
|
||||
|
||||
External events don't have to be directly triggered by humans. They can also be triggered by other systems. For example, a workflow may need to pause and wait for a payment to be received. In this case, a payment system might publish an event to a pub/sub topic on receipt of a payment, and a listener on that topic can raise an event to the workflow using the raise event workflow API.
|
||||
|
||||
## Next steps
|
||||
|
||||
{{< button text="Workflow architecture >>" page="workflow-architecture.md" >}}
|
||||
|
|
|
@ -67,6 +67,14 @@ You can also name each app directory's `.dapr` directory something other than `.
|
|||
|
||||
## Logs
|
||||
|
||||
The run template provides two log destination fields for each application and its associated daprd process:
|
||||
|
||||
1. `appLogDestination` : This field configures the log destination for the application. The possible values are `console`, `file` and `fileAndConsole`. The default value is `fileAndConsole` where application logs are written to both console and to a file by default.
|
||||
|
||||
2. `daprdLogDestination` : This field configures the log destination for the `daprd` process. The possible values are `console`, `file` and `fileAndConsole`. The default value is `file` where the `daprd` logs are written to a file by default.
|
||||
|
||||
#### Log file format
|
||||
|
||||
Logs for application and `daprd` are captured in separate files. These log files are created automatically under `.dapr/logs` directory under each application directory (`appDirPath` in the template). These log file names follow the pattern seen below:
|
||||
|
||||
- `<appID>_app_<timestamp>.log` (file name format for `app` log)
|
||||
|
@ -74,6 +82,7 @@ Logs for application and `daprd` are captured in separate files. These log files
|
|||
|
||||
Even if you've decided to rename your resources folder to something other than `.dapr`, the log files are written only to the `.dapr/logs` folder (created in the application directory).
|
||||
|
||||
|
||||
## Watch the demo
|
||||
|
||||
Watch [this video for an overview on Multi-App Run](https://youtu.be/s1p9MNl4VGo?t=2456):
|
||||
|
|
|
@ -76,12 +76,15 @@ common: # optional section for variables shared across apps
|
|||
apps:
|
||||
- appID: webapp # optional
|
||||
appDirPath: .dapr/webapp/ # REQUIRED
|
||||
resourcesPath: .dapr/resources # (optional) can be default by convention
|
||||
resourcesPath: .dapr/resources # deprecated
|
||||
resourcesPaths: .dapr/resources # comman separated resources paths. (optional) can be default by convention
|
||||
configFilePath: .dapr/config.yaml # (optional) can be default by convention too, ignore if file is not found.
|
||||
appProtocol: http
|
||||
appPort: 8080
|
||||
appHealthCheckPath: "/healthz"
|
||||
command: ["python3" "app.py"]
|
||||
appLogDestination: file # (optional), can be file, console or fileAndConsole. default is fileAndConsole.
|
||||
daprdLogDestination: file # (optional), can be file, console or fileAndConsole. default is file.
|
||||
- appID: backend # optional
|
||||
appDirPath: .dapr/backend/ # REQUIRED
|
||||
appProtocol: grpc
|
||||
|
@ -110,7 +113,8 @@ The properties for the Multi-App Run template align with the `dapr run` CLI flag
|
|||
|--------------------------|:--------:|--------|---------|
|
||||
| `appDirPath` | Y | Path to the your application code | `./webapp/`, `./backend/` |
|
||||
| `appID` | N | Application's app ID. If not provided, will be derived from `appDirPath` | `webapp`, `backend` |
|
||||
| `resourcesPath` | N | Path to your Dapr resources. Can be default by convention; ignore if directory isn't found | `./app/components`, `./webapp/components` |
|
||||
| `resourcesPath` | N | **Deprecated**. Path to your Dapr resources. Can be default by convention| `./app/components`, `./webapp/components` |
|
||||
| `resourcesPaths` | N | Comma separated paths to your Dapr resources. Can be default by convention | `./app/components`, `./webapp/components` |
|
||||
| `configFilePath` | N | Path to your application's configuration file | `./webapp/config.yaml` |
|
||||
| `appProtocol` | N | The protocol Dapr uses to talk to the application. | `http`, `grpc` |
|
||||
| `appPort` | N | The port your application is listening on | `8080`, `3000` |
|
||||
|
@ -137,6 +141,8 @@ The properties for the Multi-App Run template align with the `dapr run` CLI flag
|
|||
| `enableApiLogging` | N | Enable the logging of all API calls from application to Dapr | |
|
||||
| `runtimePath` | N | Dapr runtime install path | |
|
||||
| `env` | N | Map to environment variable; environment variables applied per application will overwrite environment variables shared across applications | `DEBUG`, `DAPR_HOST_ADD` |
|
||||
| `appLogDestination` | N | Log destination for outputting app logs; Its value can be file, console or fileAndConsole. Default is fileAndConsole | `file`, `console`, `fileAndConsole` |
|
||||
| `daprdLogDestination` | N | Log destination for outputting daprd logs; Its value can be file, console or fileAndConsole. Default is file | `file`, `console`, `fileAndConsole` |
|
||||
|
||||
## Next steps
|
||||
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 118 KiB |
Loading…
Reference in New Issue