diff --git a/daprdocs/content/en/developing-applications/building-blocks/workflow/howto-author-workflow.md b/daprdocs/content/en/developing-applications/building-blocks/workflow/howto-author-workflow.md index b6191d23d..6caa7f3ff 100644 --- a/daprdocs/content/en/developing-applications/building-blocks/workflow/howto-author-workflow.md +++ b/daprdocs/content/en/developing-applications/building-blocks/workflow/howto-author-workflow.md @@ -30,10 +30,12 @@ The Dapr sidecar doesn’t load any workflow definitions. Rather, the sidecar si [Workflow activities]({{< ref "workflow-features-concepts.md#workflow-activites" >}}) are the basic unit of work in a workflow and are the tasks that get orchestrated in the business process. -{{< tabs ".NET" >}} +{{< tabs ".NET" Python >}} {{% codetab %}} + + Define the workflow activities you'd like your workflow to perform. Activities are a class definition and can take inputs and outputs. Activities also participate in dependency injection, like binding to a Dapr client. The activities called in the example below are: @@ -96,6 +98,24 @@ public class ProcessPaymentActivity : WorkflowActivity [See the full `ProcessPaymentActivity.cs` workflow activity example.](https://github.com/dapr/dotnet-sdk/blob/master/examples/Workflow/WorkflowConsoleApp/Activities/ProcessPaymentActivity.cs) +{{% /codetab %}} + +{{% codetab %}} + + + +Define the workflow activities you'd like your workflow to perform. Activities are a function definition and can take inputs and outputs. The following example creates a counter (activity) called `hello_act` that notifies users of the current counter value. `hello_act` is a function derived from a class called `WorkflowActivityContext`. + +```python +def hello_act(ctx: WorkflowActivityContext, input): + global counter + counter += input + print(f'New counter value is: {counter}!', flush=True) +``` + +[See the `hello_act` workflow activity in context.](https://github.com/dapr/python-sdk/blob/master/examples/demo_workflow/app.py#LL40C1-L43C59) + + {{% /codetab %}} {{< /tabs >}} @@ -104,10 +124,12 @@ public class ProcessPaymentActivity : WorkflowActivity Next, register and call the activites in a workflow. -{{< tabs ".NET" >}} +{{< tabs ".NET" Python >}} {{% codetab %}} + + The `OrderProcessingWorkflow` class is derived from a base class called `Workflow` with input and output parameter types. It also includes a `RunAsync` method that does the heavy lifting of the workflow and calls the workflow activities. ```csharp @@ -144,6 +166,28 @@ The `OrderProcessingWorkflow` class is derived from a base class called `Workflo [See the full workflow example in `OrderProcessingWorkflow.cs`.](https://github.com/dapr/dotnet-sdk/blob/master/examples/Workflow/WorkflowConsoleApp/Workflows/OrderProcessingWorkflow.cs) + +{{% /codetab %}} + +{{% codetab %}} + + + +The `hello_world_wf` function is derived from a class called `DaprWorkflowContext` with input and output parameter types. It also includes a `yield` statement that does the heavy lifting of the workflow and calls the workflow activities. + +```python +def hello_world_wf(ctx: DaprWorkflowContext, input): + print(f'{input}') + yield ctx.call_activity(hello_act, input=1) + yield ctx.call_activity(hello_act, input=10) + yield ctx.wait_for_external_event("event1") + yield ctx.call_activity(hello_act, input=100) + yield ctx.call_activity(hello_act, input=1000) +``` + +[See the `hello_world_wf` workflow in context.](https://github.com/dapr/python-sdk/blob/master/examples/demo_workflow/app.py#LL32C1-L38C51) + + {{% /codetab %}} {{< /tabs >}} @@ -152,10 +196,12 @@ The `OrderProcessingWorkflow` class is derived from a base class called `Workflo Finally, compose the application using the workflow. -{{< tabs ".NET" >}} +{{< tabs ".NET" Python >}} {{% codetab %}} + + [In the following `Program.cs` example](https://github.com/dapr/dotnet-sdk/blob/master/examples/Workflow/WorkflowConsoleApp/Program.cs), for a basic ASP.NET order processing application using the .NET SDK, your project code would include: - A NuGet package called `Dapr.Workflow` to receive the .NET SDK capabilities @@ -223,8 +269,97 @@ app.Run(); {{% /codetab %}} -{{< /tabs >}} +{{% codetab %}} + + +[In the following example](https://github.com/dapr/python-sdk/blob/master/examples/demo_workflow/app.py), for a basic Python hello world application using the Python SDK, your project code would include: + +- A Python package called `DaprClient` to receive the Python SDK capabilities. +- A builder with extensions called: + - `WorkflowRuntime`: Allows you to register workflows and workflow activities + - `DaprWorkflowContext`: Allows you to [create workflows]({{< ref "#write-the-workflow" >}}) + - `WorkflowActivityContext`: Allows you to [create workflow activities]({{< ref "#write-the-workflow-activities" >}}) +- API calls. In the example below, these calls start, pause, resume, purge, and terminate the workflow. + +```python +from dapr.ext.workflow import WorkflowRuntime, DaprWorkflowContext, WorkflowActivityContext +from dapr.clients import DaprClient + +# ... + +def main(): + with DaprClient() as d: + host = settings.DAPR_RUNTIME_HOST + port = settings.DAPR_GRPC_PORT + workflowRuntime = WorkflowRuntime(host, port) + workflowRuntime = WorkflowRuntime() + workflowRuntime.register_workflow(hello_world_wf) + workflowRuntime.register_activity(hello_act) + workflowRuntime.start() + + # Start workflow + print("==========Start Counter Increase as per Input:==========") + start_resp = d.start_workflow(instance_id=instanceId, workflow_component=workflowComponent, + workflow_name=workflowName, input=inputData, workflow_options=workflowOptions) + print(f"start_resp {start_resp.instance_id}") + + # ... + + # Pause workflow + d.pause_workflow(instance_id=instanceId, workflow_component=workflowComponent) + getResponse = d.get_workflow(instance_id=instanceId, workflow_component=workflowComponent) + print(f"Get response from {workflowName} after pause call: {getResponse.runtime_status}") + + # Resume workflow + d.resume_workflow(instance_id=instanceId, workflow_component=workflowComponent) + getResponse = d.get_workflow(instance_id=instanceId, workflow_component=workflowComponent) + print(f"Get response from {workflowName} after resume call: {getResponse.runtime_status}") + + sleep(1) + # Raise workflow + d.raise_workflow_event(instance_id=instanceId, workflow_component=workflowComponent, + event_name=eventName, event_data=eventData) + + sleep(5) + # Purge workflow + d.purge_workflow(instance_id=instanceId, workflow_component=workflowComponent) + try: + getResponse = d.get_workflow(instance_id=instanceId, workflow_component=workflowComponent) + except DaprInternalError as err: + if nonExistentIDError in err._message: + print("Instance Successfully Purged") + + # Kick off another workflow for termination purposes + start_resp = d.start_workflow(instance_id=instanceId, workflow_component=workflowComponent, + workflow_name=workflowName, input=inputData, workflow_options=workflowOptions) + print(f"start_resp {start_resp.instance_id}") + + # Terminate workflow + d.terminate_workflow(instance_id=instanceId, workflow_component=workflowComponent) + sleep(1) + getResponse = d.get_workflow(instance_id=instanceId, workflow_component=workflowComponent) + print(f"Get response from {workflowName} after terminate call: {getResponse.runtime_status}") + + # Purge workflow + d.purge_workflow(instance_id=instanceId, workflow_component=workflowComponent) + try: + getResponse = d.get_workflow(instance_id=instanceId, workflow_component=workflowComponent) + except DaprInternalError as err: + if nonExistentIDError in err._message: + print("Instance Successfully Purged") + + workflowRuntime.shutdown() + +if __name__ == '__main__': + main() +``` + + +{{% /codetab %}} + + +{{< /tabs >}} {{% alert title="Important" color="warning" %}} @@ -241,4 +376,6 @@ Now that you've authored a workflow, learn how to manage it. ## Related links - [Workflow overview]({{< ref workflow-overview.md >}}) - [Workflow API reference]({{< ref workflow_api.md >}}) -- [Try out the .NET example](https://github.com/dapr/dotnet-sdk/tree/master/examples/Workflow) +- Try out the full SDK examples: + - [.NET example](https://github.com/dapr/dotnet-sdk/tree/master/examples/Workflow) + - [Python example](https://github.com/dapr/python-sdk/tree/master/examples/demo_workflow) diff --git a/daprdocs/content/en/developing-applications/building-blocks/workflow/howto-manage-workflow.md b/daprdocs/content/en/developing-applications/building-blocks/workflow/howto-manage-workflow.md index 7b2af68b4..99cb87c9b 100644 --- a/daprdocs/content/en/developing-applications/building-blocks/workflow/howto-manage-workflow.md +++ b/daprdocs/content/en/developing-applications/building-blocks/workflow/howto-manage-workflow.md @@ -8,12 +8,12 @@ description: Manage and run workflows Now that you've [authored the workflow and its activities in your application]({{< ref howto-author-workflow.md >}}), you can start, terminate, and get information about the workflow using HTTP API calls. For more information, read the [workflow API reference]({{< ref workflow_api.md >}}). -{{< tabs ".NET SDK" HTTP >}} +{{< tabs ".NET" Python HTTP >}} {{% codetab %}} -Manage your workflow within your code. In the `OrderProcessingWorkflow` example from the [Author a workflow]({{< ref "howto-author-workflow.md#write-the-workflow" >}}) guide, the workflow is registered in the code. You can now start, terminate, and get information about a running workflow: +Manage your workflow within your code. In the `OrderProcessingWorkflow` example from the [Author a workflow]({{< ref "howto-author-workflow.md#write-the-application" >}}) guide, the workflow is registered in the code. You can now start, terminate, and get information about a running workflow: ```csharp string orderId = "exampleOrderId"; @@ -46,6 +46,56 @@ await daprClient.PurgeWorkflowAsync(orderId, workflowComponent); {{% /codetab %}} + +{{% codetab %}} + +Manage your workflow within your code. In the workflow example from the [Author a workflow]({{< ref "howto-author-workflow.md#write-the-application" >}}) guide, the workflow is registered in the code using the following APIs: +- **start_workflow**: Start an instance of a workflow +- **get_workflow**: Get information on the status of the workflow +- **pause_workflow**: Pauses or suspends a workflow instance that can later be resumed +- **resume_workflow**: Resumes a paused workflow instance +- **raise_workflow_event**: Raise an event on a workflow +- **purge_workflow**: Removes all metadata related to a specific workflow instance +- **terminate_workflow**: Terminate or stop a particular instance of a workflow + +```python +from dapr.ext.workflow import WorkflowRuntime, DaprWorkflowContext, WorkflowActivityContext +from dapr.clients import DaprClient + +# Sane parameters +instanceId = "exampleInstanceID" +workflowComponent = "dapr" +workflowName = "hello_world_wf" +eventName = "event1" +eventData = "eventData" + +# Start the workflow +start_resp = d.start_workflow(instance_id=instanceId, workflow_component=workflowComponent, + workflow_name=workflowName, input=inputData, workflow_options=workflowOptions) + +# Get info on the workflow +getResponse = d.get_workflow(instance_id=instanceId, workflow_component=workflowComponent) + +# Pause the workflow +d.pause_workflow(instance_id=instanceId, workflow_component=workflowComponent) + +# Resume the workflow +d.resume_workflow(instance_id=instanceId, workflow_component=workflowComponent) + +# Raise an event on the workflow. + d.raise_workflow_event(instance_id=instanceId, workflow_component=workflowComponent, + event_name=eventName, event_data=eventData) + +# Purge the workflow +d.purge_workflow(instance_id=instanceId, workflow_component=workflowComponent) + +# Terminate the workflow +d.terminate_workflow(instance_id=instanceId, workflow_component=workflowComponent) +``` + +{{% /codetab %}} + + {{% codetab %}} @@ -121,5 +171,7 @@ Learn more about these HTTP calls in the [workflow API reference guide]({{< ref ## Next steps - [Try out the Workflow quickstart]({{< ref workflow-quickstart.md >}}) -- [Try out the .NET example](https://github.com/dapr/dotnet-sdk/tree/master/examples/Workflow) +- Try out the full SDK examples: + - [.NET example](https://github.com/dapr/dotnet-sdk/tree/master/examples/Workflow) + - [Python example](https://github.com/dapr/python-sdk/blob/master/examples/demo_workflow/app.py) - [Workflow API reference]({{< ref workflow_api.md >}}) diff --git a/daprdocs/content/en/developing-applications/building-blocks/workflow/workflow-overview.md b/daprdocs/content/en/developing-applications/building-blocks/workflow/workflow-overview.md index 5afd25055..20418d9c7 100644 --- a/daprdocs/content/en/developing-applications/building-blocks/workflow/workflow-overview.md +++ b/daprdocs/content/en/developing-applications/building-blocks/workflow/workflow-overview.md @@ -81,6 +81,8 @@ You can use the following SDKs to author a workflow. | Language stack | Package | | - | - | | .NET | [Dapr.Workflow](https://www.nuget.org/profiles/dapr.io) | +| Python | [dapr-ext-workflow](https://github.com/dapr/python-sdk/tree/master/ext/dapr-ext-workflow) | + ## Try out workflows @@ -92,6 +94,8 @@ Want to put workflows to the test? Walk through the following quickstart and tut | ------------------- | ----------- | | [Workflow quickstart]({{< ref workflow-quickstart.md >}}) | Run a .NET workflow application with four workflow activities to see Dapr Workflow in action | | [Workflow .NET SDK example](https://github.com/dapr/dotnet-sdk/tree/master/examples/Workflow) | Learn how to create a Dapr Workflow and invoke it using ASP.NET Core web APIs. | +| [Workflow Python SDK example](https://github.com/dapr/python-sdk/tree/master/examples/demo_workflow) | Learn how to create a Dapr Workflow and invoke it using the Python `DaprClient` package. | + ### Start using workflows directly in your app @@ -110,4 +114,6 @@ Watch [this video for an overview on Dapr Workflow](https://youtu.be/s1p9MNl4VGo ## Related links - [Workflow API reference]({{< ref workflow_api.md >}}) -- [Try out the .NET example](https://github.com/dapr/dotnet-sdk/tree/master/examples/Workflow) +- Try out the full SDK examples: + - [.NET example](https://github.com/dapr/dotnet-sdk/tree/master/examples/Workflow) + - [Python example](https://github.com/dapr/python-sdk/tree/master/examples/demo_workflow) diff --git a/daprdocs/static/presentations/Dapr-Diagrams.pptx.zip b/daprdocs/static/presentations/Dapr-Diagrams.pptx.zip index b16cffdcf..ac7ffa00e 100644 Binary files a/daprdocs/static/presentations/Dapr-Diagrams.pptx.zip and b/daprdocs/static/presentations/Dapr-Diagrams.pptx.zip differ