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