From d35344c942a2e3dd5a8b4776f86fb9a68cf5237c Mon Sep 17 00:00:00 2001 From: joshvanl Date: Thu, 9 Oct 2025 20:53:18 +0100 Subject: [PATCH 1/9] Adds dapr workflow docs Based on https://github.com/dapr/cli/pull/1560 Signed-off-by: joshvanl --- .../workflow/howto-author-workflow.md | 40 +++ .../workflow/howto-manage-workflow.md | 273 +++++++++++++++++- .../workflow/workflow-architecture.md | 28 ++ .../workflow/workflow-features-concepts.md | 56 ++++ .../workflow/workflow-overview.md | 36 +++ .../workflow/workflow-patterns.md | 10 + .../quickstarts/workflow-quickstart.md | 62 ++++ .../content/en/reference/cli/dapr-workflow.md | 240 +++++++++++++++ 8 files changed, 744 insertions(+), 1 deletion(-) create mode 100644 daprdocs/content/en/reference/cli/dapr-workflow.md 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 ca3777064b9..f9e7533e2a0 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 @@ -1179,6 +1179,46 @@ Because of how replay-based workflows execute, you'll write logic that does thin {{% /alert %}} +## Testing Your Workflow + +After authoring your workflow, test it using the Dapr CLI: + +### Start Your Workflow + +```bash +dapr workflow run OrderProcessingWorkflow \ + --app-id orderservice \ + --input '{"orderId": "test-001", "items": [{"sku": "WIDGET", "quantity": 5}]}' +``` + +### Monitor Workflow Execution + +```bash +dapr workflow list --app-id orderservice --filter-status RUNNING +``` + +### Test External Events + +```bash +# Raise an event your workflow is waiting for +dapr workflow raise-event /ApprovalReceived \ + --app-id orderservice \ + --input '{"approved": true, "approver": "manager@company.com"}' +``` + +### Debug Failed Workflows + +```bash +# List failed workflows +dapr workflow list --app-id orderservice --filter-status FAILED --output wide + +# Get detailed history of a failed workflow +dapr workflow history --app-id orderservice --output json + +# Re-run the workflow after fixing issues +dapr workflow rerun --app-id orderservice +``` + ## Next steps Now that you've authored a workflow, learn how to manage it. 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 8b5dd89f855..446bcbfd641 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 @@ -6,7 +6,7 @@ weight: 6000 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 %}}). +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 the CLI or API calls. For more information, read the [workflow API reference]({{% ref workflow_api.md %}}). {{< tabpane text=true >}} @@ -69,6 +69,277 @@ dapr scheduler import -f workflow-reminders-backup.bin - Create workflow reminders via the Workflow API. - Manage reminders (list, get, delete, backup/restore) with the dapr scheduler CLI. +## Managing Workflows with the Dapr CLI + +The Dapr CLI provides powerful commands for managing workflow instances in both self-hosted and Kubernetes environments. + +### Prerequisites + +- Dapr CLI version 1.16.2 or later +- A running Dapr application with workflows configured +- For database operations: network access to your actor state store + +### Basic Workflow Operations + +#### Start a Workflow + +```bash +# Start a workflow with input data +dapr workflow run OrderProcessingWorkflow \ + --app-id orderprocessing \ + --input '{"orderId": "12345", "amount": 100.50}' + +# Start with a specific instance ID +dapr workflow run OrderProcessingWorkflow \ + --app-id orderprocessing \ + --instance-id order-12345 \ + --input '{"orderId": "12345"}' + +# Schedule a workflow to start later +dapr workflow run OrderProcessingWorkflow \ + --app-id orderprocessing \ + --start-time "2024-12-25T10:00:00Z" +``` + +#### List Workflow Instances + +```bash +# List all workflows for an app +dapr workflow list --app-id orderprocessing + +# Filter by status +dapr workflow list --app-id orderprocessing --filter-status RUNNING + +# Filter by workflow name +dapr workflow list --app-id orderprocessing --filter-name OrderProcessingWorkflow + +# Filter by age (workflows started in last 24 hours) +dapr workflow list --app-id orderprocessing --filter-max-age 24h + +# Get detailed output +dapr workflow list --app-id orderprocessing --output wide +``` + +#### View Workflow History + +```bash +# Get execution history +dapr workflow history order-12345 --app-id orderprocessing + +# Get history in JSON format +dapr workflow history order-12345 --app-id orderprocessing --output json +``` + +#### Control Workflow Execution + +```bash +# Suspend a running workflow +dapr workflow suspend order-12345 \ + --app-id orderprocessing \ + --reason "Waiting for manual approval" + +# Resume a suspended workflow +dapr workflow resume order-12345 \ + --app-id orderprocessing \ + --reason "Approved by manager" + +# Terminate a workflow +dapr workflow terminate order-12345 \ + --app-id orderprocessing \ + --output '{"reason": "Cancelled by customer"}' +``` + +#### Raise External Events + +```bash +# Raise an event for a waiting workflow +dapr workflow raise-event order-12345/PaymentReceived \ + --app-id orderprocessing \ + --input '{"paymentId": "pay-67890", "amount": 100.50}' +``` + +#### Re-run Workflows + +```bash +# Re-run from the beginning +dapr workflow rerun order-12345 --app-id orderprocessing + +# Re-run from a specific event +dapr workflow rerun order-12345 \ + --app-id orderprocessing \ + --event-id 5 + +# Re-run with a new instance ID +dapr workflow rerun order-12345 \ + --app-id orderprocessing \ + --new-instance-id order-12345-retry +``` + +#### Purge Completed Workflows + +```bash +# Purge a specific instance +dapr workflow purge order-12345 --app-id orderprocessing + +# Purge all completed workflows older than 30 days +dapr workflow purge --app-id orderprocessing --all-older-than 720h + +# Purge all terminal workflows (use with caution!) +dapr workflow purge --app-id orderprocessing --all +``` + +### Kubernetes Operations + +All commands support the `-k` flag for Kubernetes deployments: + +```bash +# List workflows in Kubernetes +dapr workflow list \ + --kubernetes \ + --namespace production \ + --app-id orderprocessing + +# Suspend a workflow in Kubernetes +dapr workflow suspend order-12345 \ + --kubernetes \ + --namespace production \ + --app-id orderprocessing \ + --reason "Maintenance window" +``` + +### Advanced: Direct Database Access + +For advanced operations like listing and purging workflows, you can connect directly to the actor state store database. This is useful for: + +- Querying workflows across multiple app instances +- Bulk operations on workflow metadata +- Custom filtering beyond what the API provides + +#### Self-Hosted Mode + +In self-hosted mode, the CLI can automatically discover your state store configuration: + +```bash +# The CLI reads your component configuration automatically +dapr workflow list --app-id orderprocessing +``` + +To override with a specific connection string: + +```bash +# PostgreSQL +dapr workflow list \ + --app-id orderprocessing \ + --connection-string "host=localhost user=dapr password=dapr dbname=dapr port=5432 sslmode=disable" \ + --table-name workflows + +# MySQL +dapr workflow list \ + --app-id orderprocessing \ + --connection-string "dapr:dapr@tcp(localhost:3306)/dapr?parseTime=true" \ + --table-name workflows + +# SQL Server +dapr workflow list \ + --app-id orderprocessing \ + --connection-string "sqlserver://dapr:Pass@word1@localhost:1433?database=dapr" \ + --table-name workflows +``` + +#### Kubernetes Mode with Port Forwarding + +In Kubernetes, you need to establish connectivity to your database: + +**Step 1: Port forward to your database service** + +```bash +# PostgreSQL +kubectl port-forward service/postgres 5432:5432 -n production + +# MySQL +kubectl port-forward service/mysql 3306:3306 -n production + +# SQL Server +kubectl port-forward service/mssql 1433:1433 -n production +``` + +**Step 2: Use the CLI with the connection string** + +```bash +# PostgreSQL example +dapr workflow list \ + --kubernetes \ + --namespace production \ + --app-id orderprocessing \ + --connection-string "host=localhost user=dapr password=dapr dbname=dapr port=5432 sslmode=disable" \ + --table-name workflows + +# Purge old workflows +dapr workflow purge \ + --kubernetes \ + --namespace production \ + --app-id orderprocessing \ + --connection-string "host=localhost user=dapr password=dapr dbname=dapr port=5432 sslmode=disable" \ + --table-name workflows \ + --all-older-than 2160h # 90 days +``` + +**Step 3: Stop port forwarding when done** + +```bash +# Press Ctrl+C to stop the port forward +``` + +#### Connection String Formats by Database + +**PostgreSQL / CockroachDB** +``` +host=localhost user=dapr password=dapr dbname=dapr port=5432 sslmode=disable connect_timeout=10 +``` + +**MySQL** +``` +username:password@tcp(host:port)/database?parseTime=true&loc=UTC +``` + +**SQL Server** +``` +sqlserver://username:password@host:port?database=dbname&encrypt=false +``` + +**MongoDB** +``` +mongodb://username:password@localhost:27017/database +``` + +**Redis** +``` +localhost:6379,password=secret,db=0 +``` + +### Workflow Management Best Practices + +1. **Regular Cleanup**: Schedule periodic purge operations for completed workflows + ```bash + # Weekly cron job to purge workflows older than 90 days + dapr workflow purge --app-id orderprocessing --all-older-than 2160h + ``` + +2. **Monitor Running Workflows**: Use filtered lists to track long-running instances + ```bash + dapr workflow list --app-id orderprocessing --filter-status RUNNING --filter-max-age 24h + ``` + +3. **Use Instance IDs**: Assign meaningful instance IDs for easier tracking + ```bash + dapr workflow run OrderWorkflow --app-id orderprocessing --instance-id "order-$(date +%s)" + ``` + +4. **Export for Analysis**: Export workflow data for analysis + ```bash + dapr workflow list --app-id orderprocessing --output json > workflows.json + ``` + {{% /tab %}} diff --git a/daprdocs/content/en/developing-applications/building-blocks/workflow/workflow-architecture.md b/daprdocs/content/en/developing-applications/building-blocks/workflow/workflow-architecture.md index e5d77c2c18e..e06ba6725b5 100644 --- a/daprdocs/content/en/developing-applications/building-blocks/workflow/workflow-architecture.md +++ b/daprdocs/content/en/developing-applications/building-blocks/workflow/workflow-architecture.md @@ -189,6 +189,34 @@ This number may be larger or smaller depending on retries or concurrency. | Raise event | 3 records | | Start child workflow | 8 records | +#### Direct Database Access + +For advanced operations, you can access workflow data directly: + +```bash +# Port forward to database in Kubernetes +kubectl port-forward service/postgres 5432:5432 + +# Query workflows directly +dapr workflow list \ + --app-id myapp \ + --connection-string "host=localhost user=dapr password=dapr dbname=dapr port=5432 sslmode=disable" \ + --table-name workflows +``` + +### Supported State Stores + +The workflow engine supports these state stores: +- PostgreSQL +- MySQL +- SQL Server +- SQLite +- Oracle Database +- CockroachDB +- MongoDB +- Redis + + ## Workflow scalability Because Dapr Workflows are internally implemented using actors, Dapr Workflows have the same scalability characteristics as actors. diff --git a/daprdocs/content/en/developing-applications/building-blocks/workflow/workflow-features-concepts.md b/daprdocs/content/en/developing-applications/building-blocks/workflow/workflow-features-concepts.md index 2114b1827d7..4ef76ece687 100644 --- a/daprdocs/content/en/developing-applications/building-blocks/workflow/workflow-features-concepts.md +++ b/daprdocs/content/en/developing-applications/building-blocks/workflow/workflow-features-concepts.md @@ -24,6 +24,62 @@ There are several different kinds of tasks that a workflow can schedule, includi - [Child workflows]({{% ref "workflow-features-concepts.md#child-workflows" %}}) for breaking larger workflows into smaller pieces - [External event waiters]({{% ref "workflow-features-concepts.md#external-events" %}}) for blocking workflows until they receive external event signals. These tasks are described in more details in their corresponding sections. +## Workflow Instance Management + +### Querying Workflow State + +You can query workflow instances using the CLI: + +```bash +# Find all running workflows +dapr workflow list --app-id myapp --filter-status RUNNING + +# Find workflows by name +dapr workflow list --app-id myapp --filter-name OrderProcessing + +# Find recent workflows (last 2 hours) +dapr workflow list --app-id myapp --filter-max-age 2h + +# Get detailed JSON output +dapr workflow list --app-id myapp --output json +``` + +### Workflow History + +View the complete execution history: + +```bash +dapr workflow history wf-12345 --app-id myapp --output json +``` + +This shows all events, activities, and state transitions. + +## External Events + +### Raising Events via CLI + +```bash +dapr workflow raise-event wf-12345/ApprovalReceived \ + --app-id myapp \ + --input '{"approved": true, "comments": "Approved by manager"}' +``` + +## Workflow Suspension and Resumption + +### Using the CLI + +```bash +# Suspend for manual intervention +dapr workflow suspend wf-12345 \ + --app-id myapp \ + --reason "Awaiting customer response" + +# Resume when ready +dapr workflow resume wf-12345 \ + --app-id myapp \ + --reason "Customer responded" +``` + ### Workflow identity Each workflow you define has a type name, and individual executions of a workflow require a unique _instance ID_. Workflow instance IDs can be generated by your app code, which is useful when workflows correspond to business entities like documents or jobs, or can be auto-generated UUIDs. A workflow's instance ID is useful for debugging and also for managing workflows using the [Workflow APIs]({{% 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 5c79019fafd..a35899396d4 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 @@ -114,6 +114,42 @@ Want to put workflows to the test? Walk through the following quickstart and tut Want to skip the quickstarts? Not a problem. You can try out the workflow building block directly in your application. After [Dapr is installed]({{% ref install-dapr-cli.md %}}), you can begin using workflows, starting with [how to author a workflow]({{% ref howto-author-workflow.md %}}). +## Managing Workflows + +Dapr provides comprehensive workflow management capabilities through both the HTTP API and the CLI. + +### Workflow Lifecycle Operations + +**Start Workflows** +```bash +dapr workflow run MyWorkflow --app-id myapp --input '{"key": "value"}' +``` + +**Monitor Workflows** +```bash +# List active workflows +dapr workflow list --app-id myapp --filter-status RUNNING + +# View execution history +dapr workflow history --app-id myapp +``` + +**Control Workflows** +```bash +# Suspend, resume, or terminate +dapr workflow suspend --app-id myapp +dapr workflow resume --app-id myapp +dapr workflow terminate --app-id myapp +``` + +**Maintenance Operations** +```bash +# Purge completed workflows +dapr workflow purge --app-id myapp --all-older-than 720h +``` + +See [How-To: Manage workflows]({{< ref howto-manage-workflow.md >}}) for detailed instructions. + ## Limitations - **State stores:** You can only use state stores which support workflows, as [described here]({{% ref supported-state-stores %}}). diff --git a/daprdocs/content/en/developing-applications/building-blocks/workflow/workflow-patterns.md b/daprdocs/content/en/developing-applications/building-blocks/workflow/workflow-patterns.md index a0f0e66bbd4..8158ddfdbbc 100644 --- a/daprdocs/content/en/developing-applications/building-blocks/workflow/workflow-patterns.md +++ b/daprdocs/content/en/developing-applications/building-blocks/workflow/workflow-patterns.md @@ -307,6 +307,16 @@ In addition to the challenges mentioned in [the previous pattern]({{% ref "workf Dapr Workflows provides a way to express the fan-out/fan-in pattern as a simple function, as shown in the following example: +```bash +# Start the workflow +dapr workflow run DataProcessingWorkflow \ + --app-id processor \ + --input '{"items": ["item1", "item2", "item3"]}' + +# Monitor parallel execution +dapr workflow history --app-id processor --output json +``` + {{< tabpane text=true >}} {{% tab "Python" %}} diff --git a/daprdocs/content/en/getting-started/quickstarts/workflow-quickstart.md b/daprdocs/content/en/getting-started/quickstarts/workflow-quickstart.md index 72473207839..bfa1772635b 100644 --- a/daprdocs/content/en/getting-started/quickstarts/workflow-quickstart.md +++ b/daprdocs/content/en/getting-started/quickstarts/workflow-quickstart.md @@ -2064,6 +2064,68 @@ func RequestApprovalActivity(ctx workflow.ActivityContext) (any, error) { {{< /tabpane >}} + +## Step 5: Manage Your Workflow + +Now that your workflow is running, let's learn how to manage it using the Dapr CLI. + +### View Running Workflows + +```bash +# List all workflows +dapr workflow list --app-id orderprocessing + +# You should see output like: +# INSTANCE ID WORKFLOW NAME CREATED LAST UPDATED RUNTIME STATUS +# order-20240312-001 OrderProcessingWorkflow 2024-03-12 10:00:00 2024-03-12 10:00:05 RUNNING +``` + +### Check Workflow History + +View the detailed execution history of your workflow: + +```bash +dapr workflow history order-20240312-001 --app-id orderprocessing +``` + +### Interact with Your Workflow + +#### Raise an External Event + +If your workflow is waiting for an external event: + +```bash +dapr workflow raise-event order-20240312-001/PaymentReceived \ + --app-id orderprocessing \ + --input '{"paymentId": "pay-123", "amount": 100.00}' +``` + +#### Suspend and Resume + +```bash +# Suspend a workflow +dapr workflow suspend order-20240312-001 \ + --app-id orderprocessing \ + --reason "Waiting for inventory" + +# Resume when ready +dapr workflow resume order-20240312-001 \ + --app-id orderprocessing \ + --reason "Inventory received" +``` + +### Clean Up + +After testing, purge completed workflows: + +```bash +# Purge a specific workflow +dapr workflow purge order-20240312-001 --app-id orderprocessing + +# Or purge all completed workflows +dapr workflow purge --app-id orderprocessing --all-older-than 1h +``` + ## Tell us what you think! We're continuously working to improve our Quickstart examples and value your feedback. Did you find this Quickstart helpful? Do you have suggestions for improvement? diff --git a/daprdocs/content/en/reference/cli/dapr-workflow.md b/daprdocs/content/en/reference/cli/dapr-workflow.md new file mode 100644 index 00000000000..a9f6857ad47 --- /dev/null +++ b/daprdocs/content/en/reference/cli/dapr-workflow.md @@ -0,0 +1,240 @@ +--- +type: docs +title: "workflow CLI command" +linkTitle: "workflow" +description: "Detailed information on the workflow CLI command" +--- + +Manage Dapr workflow instances. + +## Commands + +| Command | Description | +|---------|-------------| +| [dapr workflow run]({{< ref dapr-workflow-run.md >}}) | Start a new workflow instance | +| [dapr workflow list]({{< ref dapr-workflow-list.md >}}) | List workflow instances | +| [dapr workflow history]({{< ref dapr-workflow-history.md >}}) | Get workflow execution history | +| [dapr workflow purge]({{< ref dapr-workflow-purge.md >}}) | Purge workflow instances | +| [dapr workflow suspend]({{< ref dapr-workflow-suspend.md >}}) | Suspend a workflow | +| [dapr workflow resume]({{< ref dapr-workflow-resume.md >}}) | Resume a workflow | +| [dapr workflow terminate]({{< ref dapr-workflow-terminate.md >}}) | Terminate a workflow | +| [dapr workflow raise-event]({{< ref dapr-workflow-raise-event.md >}}) | Raise an external event | +| [dapr workflow rerun]({{< ref dapr-workflow-rerun.md >}}) | Re-run a workflow | + +## Flags + +``` + -a, --app-id string The app ID owner of the workflow instance + -h, --help help for workflow + -k, --kubernetes Target a Kubernetes dapr installation + -n, --namespace string Namespace to perform workflow operation on (default "default") +``` + +## Examples + +### List workflows +```bash +dapr workflow list --app-id myapp +``` + +### Start a workflow +```bash +dapr workflow run MyWorkflow --app-id myapp --input '{"key": "value"}' +``` + +### Kubernetes mode +```bash +dapr workflow list -k -n production --app-id myapp +``` +``` + +### dapr-workflow-list.md + +```markdown +--- +type: docs +title: "workflow list CLI command" +linkTitle: "workflow list" +description: "Detailed information on the workflow list CLI command" +--- + +List workflow instances for a given application. + +## Usage + +```bash +dapr workflow list [flags] +``` + +## Flags + +| Name | Type | Description | +|------|------|-------------| +| `--app-id`, `-a` | string | (Required) The app ID owner of the workflow instances | +| `--filter-name`, `-w` | string | Filter workflows by name | +| `--filter-status`, `-s` | string | Filter by status: RUNNING, COMPLETED, FAILED, CANCELED, TERMINATED, PENDING, SUSPENDED | +| `--filter-max-age`, `-m` | string | Filter workflows started within duration or timestamp (e.g., "300ms", "1.5h", "2023-01-02T15:04:05") | +| `--output`, `-o` | string | Output format: short, wide, yaml, json (default "short") | +| `--connection-string`, `-c` | string | Connection string to the actor state store | +| `--table-name`, `-t` | string | Table or collection name used as the actor state store | +| `--kubernetes`, `-k` | bool | Target a Kubernetes Dapr installation | +| `--namespace`, `-n` | string | Kubernetes namespace (default "default") | + +## Examples + +### Basic usage +```bash +dapr workflow list --app-id myapp +``` + +### Filter by status +```bash +dapr workflow list --app-id myapp --filter-status RUNNING +``` + +### Filter by workflow name +```bash +dapr workflow list --app-id myapp --filter-name OrderProcessing +``` + +### Filter by age +```bash +# Workflows from last 24 hours +dapr workflow list --app-id myapp --filter-max-age 24h + +# Workflows after specific date +dapr workflow list --app-id myapp --filter-max-age 2024-01-01T00:00:00Z +``` + +### JSON output +```bash +dapr workflow list --app-id myapp --output json +``` + +### Kubernetes with port forwarding +```bash +# Terminal 1: Port forward to database +kubectl port-forward service/postgres 5432:5432 -n production + +# Terminal 2: List workflows with direct database access +dapr workflow list \ + --kubernetes \ + --namespace production \ + --app-id myapp \ + --connection-string "host=localhost user=dapr password=dapr dbname=dapr port=5432 sslmode=disable" \ + --table-name workflows +``` + +## Connection String Formats + +### PostgreSQL / CockroachDB +``` +host=localhost user=dapr password=dapr dbname=dapr port=5432 sslmode=disable +``` + +### MySQL +``` +dapr:dapr@tcp(localhost:3306)/dapr?parseTime=true +``` + +### SQL Server +``` +sqlserver://dapr:Pass@word@localhost:1433?database=dapr +``` + +### MongoDB +``` +mongodb://localhost:27017/dapr +``` + +### Redis +``` +localhost:6379,password=secret,db=0 +``` +``` + +### dapr-workflow-purge.md + +```markdown +--- +type: docs +title: "workflow purge CLI command" +linkTitle: "workflow purge" +description: "Detailed information on the workflow purge CLI command" +--- + +Purge workflow instances with terminal states (COMPLETED, FAILED, TERMINATED). + +## Usage + +```bash +dapr workflow purge [instance-id] [flags] +``` + +## Flags + +| Name | Type | Description | +|------|------|-------------| +| `--app-id`, `-a` | string | (Required) The app ID owner of the workflow instances | +| `--all` | bool | Purge all terminal workflow instances (use with caution) | +| `--all-older-than` | string | Purge instances older than duration or timestamp (e.g., "24h", "2023-01-02T15:04:05Z") | +| `--connection-string`, `-c` | string | Connection string to the actor state store | +| `--table-name`, `-t` | string | Table or collection name used as the actor state store | +| `--kubernetes`, `-k` | bool | Target a Kubernetes Dapr installation | +| `--namespace`, `-n` | string | Kubernetes namespace (default "default") | + +## Examples + +### Purge a specific instance +```bash +dapr workflow purge wf-12345 --app-id myapp +``` + +### Purge instances older than 30 days +```bash +dapr workflow purge --app-id myapp --all-older-than 720h +``` + +### Purge instances older than specific date +```bash +dapr workflow purge --app-id myapp --all-older-than 2023-12-01T00:00:00Z +``` + +### Purge all terminal instances (dangerous!) +```bash +dapr workflow purge --app-id myapp --all +``` + +### Kubernetes with database access +```bash +# Port forward to database +kubectl port-forward service/postgres 5432:5432 -n production + +# Purge old workflows +dapr workflow purge \ + --kubernetes \ + --namespace production \ + --app-id myapp \ + --connection-string "host=localhost user=dapr password=dapr dbname=dapr port=5432 sslmode=disable" \ + --table-name workflows \ + --all-older-than 2160h # 90 days +``` + +## Best Practices + +1. **Regular Cleanup**: Schedule periodic purge operations + ```bash + # Cron job to purge workflows older than 90 days + 0 2 * * 0 dapr workflow purge --app-id myapp --all-older-than 2160h + ``` + +2. **Test First**: Use list command to see what will be purged + ```bash + dapr workflow list --app-id myapp --filter-status COMPLETED --filter-max-age 2160h + ``` + +3. **Backup Before Bulk Purge**: Export data before using `--all` + ```bash + dapr workflow list --app-id myapp --output json > backup.json + ``` +``` From 95633f64827753ff19123f95f39072232d7f3aa3 Mon Sep 17 00:00:00 2001 From: joshvanl Date: Thu, 30 Oct 2025 21:46:08 +0000 Subject: [PATCH 2/9] Remove link references in CLI table Signed-off-by: joshvanl --- .../workflow/howto-manage-workflow.md | 2 ++ .../content/en/reference/cli/dapr-workflow.md | 18 +++++++++--------- 2 files changed, 11 insertions(+), 9 deletions(-) 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 446bcbfd641..ae9ccdcc418 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 @@ -177,6 +177,8 @@ dapr workflow rerun order-12345 \ #### Purge Completed Workflows +Note that purging a workflow from the CLI will also delete all associated Scheduler reminders. + ```bash # Purge a specific instance dapr workflow purge order-12345 --app-id orderprocessing diff --git a/daprdocs/content/en/reference/cli/dapr-workflow.md b/daprdocs/content/en/reference/cli/dapr-workflow.md index a9f6857ad47..f2190442ca1 100644 --- a/daprdocs/content/en/reference/cli/dapr-workflow.md +++ b/daprdocs/content/en/reference/cli/dapr-workflow.md @@ -11,15 +11,15 @@ Manage Dapr workflow instances. | Command | Description | |---------|-------------| -| [dapr workflow run]({{< ref dapr-workflow-run.md >}}) | Start a new workflow instance | -| [dapr workflow list]({{< ref dapr-workflow-list.md >}}) | List workflow instances | -| [dapr workflow history]({{< ref dapr-workflow-history.md >}}) | Get workflow execution history | -| [dapr workflow purge]({{< ref dapr-workflow-purge.md >}}) | Purge workflow instances | -| [dapr workflow suspend]({{< ref dapr-workflow-suspend.md >}}) | Suspend a workflow | -| [dapr workflow resume]({{< ref dapr-workflow-resume.md >}}) | Resume a workflow | -| [dapr workflow terminate]({{< ref dapr-workflow-terminate.md >}}) | Terminate a workflow | -| [dapr workflow raise-event]({{< ref dapr-workflow-raise-event.md >}}) | Raise an external event | -| [dapr workflow rerun]({{< ref dapr-workflow-rerun.md >}}) | Re-run a workflow | +| dapr workflow run | Start a new workflow instance | +| dapr workflow list | List workflow instances | +| dapr workflow history | Get workflow execution history | +| dapr workflow purge | Purge workflow instances | +| dapr workflow suspend | Suspend a workflow | +| dapr workflow resume | Resume a workflow | +| dapr workflow terminate | Terminate a workflow | +| dapr workflow raise-event | Raise an external event | +| dapr workflow rerun | Re-run a workflow | ## Flags From 4ba4744b6294a913c5094d5a2436235707c763aa Mon Sep 17 00:00:00 2001 From: joshvanl Date: Wed, 5 Nov 2025 18:16:33 +0000 Subject: [PATCH 3/9] Fix dapr workflow CLI reference doc Signed-off-by: joshvanl --- .../content/en/reference/cli/dapr-workflow.md | 27 ++----------------- 1 file changed, 2 insertions(+), 25 deletions(-) diff --git a/daprdocs/content/en/reference/cli/dapr-workflow.md b/daprdocs/content/en/reference/cli/dapr-workflow.md index f2190442ca1..08499a62adb 100644 --- a/daprdocs/content/en/reference/cli/dapr-workflow.md +++ b/daprdocs/content/en/reference/cli/dapr-workflow.md @@ -46,19 +46,8 @@ dapr workflow run MyWorkflow --app-id myapp --input '{"key": "value"}' ```bash dapr workflow list -k -n production --app-id myapp ``` -``` -### dapr-workflow-list.md - -```markdown ---- -type: docs -title: "workflow list CLI command" -linkTitle: "workflow list" -description: "Detailed information on the workflow list CLI command" ---- - -List workflow instances for a given application. +## List workflow instances for a given application. ## Usage @@ -151,19 +140,8 @@ mongodb://localhost:27017/dapr ``` localhost:6379,password=secret,db=0 ``` -``` -### dapr-workflow-purge.md - -```markdown ---- -type: docs -title: "workflow purge CLI command" -linkTitle: "workflow purge" -description: "Detailed information on the workflow purge CLI command" ---- - -Purge workflow instances with terminal states (COMPLETED, FAILED, TERMINATED). +## Purge workflow instances with terminal states (COMPLETED, FAILED, TERMINATED). ## Usage @@ -237,4 +215,3 @@ dapr workflow purge \ ```bash dapr workflow list --app-id myapp --output json > backup.json ``` -``` From 20af9b3dc86bee994f327224087a3569aec5b04d Mon Sep 17 00:00:00 2001 From: joshvanl Date: Thu, 6 Nov 2025 18:21:18 +0000 Subject: [PATCH 4/9] Update docs for workflow docs Signed-off-by: joshvanl --- .../workflow/howto-author-workflow.md | 444 ++++++++++++------ .../workflow/howto-manage-workflow.md | 28 +- .../workflow/workflow-architecture.md | 13 +- .../workflow/workflow-overview.md | 2 +- .../quickstarts/workflow-quickstart.md | 12 +- .../content/en/reference/cli/dapr-workflow.md | 2 +- 6 files changed, 337 insertions(+), 164 deletions(-) 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 f9e7533e2a0..bbafbf252f0 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 @@ -227,7 +227,7 @@ func BusinessWorkflow(ctx *workflow.WorkflowContext) (any, error) { if err := ctx.CallActivity(BusinessActivity, workflow.ActivityInput(input)).Await(&output); err != nil { return nil, err } - if err := ctx.WaitForExternalEvent("businessEvent", time.Second*60).Await(&output); err != nil { + if err := ctx.WaitForExternalEvent("businessEvent", time.Minute*60).Await(&output); err != nil { return nil, err } @@ -475,7 +475,7 @@ func BusinessWorkflow(ctx *workflow.WorkflowContext) (any, error) { if err := ctx.CallActivity(BusinessActivity, workflow.ActivityInput(input)).Await(&output); err != nil { return nil, err } - if err := ctx.WaitForExternalEvent("businessEvent", time.Second*60).Await(&output); err != nil { + if err := ctx.WaitForExternalEvent("businessEvent", time.Minute*60).Await(&output); err != nil { return nil, err } @@ -666,6 +666,7 @@ def main(): if non_existent_id_error in err._message: print('Instance Successfully Purged') + sleep(10000) wfr.shutdown() @@ -685,139 +686,79 @@ if __name__ == '__main__': - `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, terminate, get status, pause, resume, raise event, and purge the workflow. - -```javascript -import { TaskHubGrpcClient } from "@microsoft/durabletask-js"; -import { WorkflowState } from "./WorkflowState"; -import { generateApiTokenClientInterceptors, generateEndpoint, getDaprApiToken } from "../internal/index"; -import { TWorkflow } from "../../types/workflow/Workflow.type"; -import { getFunctionName } from "../internal"; -import { WorkflowClientOptions } from "../../types/workflow/WorkflowClientOption"; - -/** DaprWorkflowClient class defines client operations for managing workflow instances. */ - -export default class DaprWorkflowClient { - private readonly _innerClient: TaskHubGrpcClient; - - /** Initialize a new instance of the DaprWorkflowClient. - */ - constructor(options: Partial = {}) { - const grpcEndpoint = generateEndpoint(options); - options.daprApiToken = getDaprApiToken(options); - this._innerClient = this.buildInnerClient(grpcEndpoint.endpoint, options); - } +- API calls. The following example is a simple project consuming the workflow APIs: - private buildInnerClient(hostAddress: string, options: Partial): TaskHubGrpcClient { - let innerOptions = options?.grpcOptions; - if (options.daprApiToken !== undefined && options.daprApiToken !== "") { - innerOptions = { - ...innerOptions, - interceptors: [generateApiTokenClientInterceptors(options), ...(innerOptions?.interceptors ?? [])], - }; - } - return new TaskHubGrpcClient(hostAddress, innerOptions); - } +```bash +mkdir my-wf && cd my-wf +npm init -y +npm i @dapr/dapr @microsoft/durabletask-js +npm i -D typescript ts-node @types/node +``` - /** - * Schedule a new workflow using the DurableTask client. - */ - public async scheduleNewWorkflow( - workflow: TWorkflow | string, - input?: any, - instanceId?: string, - startAt?: Date, - ): Promise { - if (typeof workflow === "string") { - return await this._innerClient.scheduleNewOrchestration(workflow, input, instanceId, startAt); - } - return await this._innerClient.scheduleNewOrchestration(getFunctionName(workflow), input, instanceId, startAt); - } +Create the following `tsconfig.json` file: - /** - * Terminate the workflow associated with the provided instance id. - * - * @param {string} workflowInstanceId - Workflow instance id to terminate. - * @param {any} output - The optional output to set for the terminated workflow instance. - */ - public async terminateWorkflow(workflowInstanceId: string, output: any) { - await this._innerClient.terminateOrchestration(workflowInstanceId, output); - } +```json +{ + "compilerOptions": { + "target": "ES2020", + "module": "CommonJS", + "moduleResolution": "Node", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "outDir": "dist" + }, + "include": ["src"] +} +``` - /** - * Fetch workflow instance metadata from the configured durable store. - */ - public async getWorkflowState( - workflowInstanceId: string, - getInputsAndOutputs: boolean, - ): Promise { - const state = await this._innerClient.getOrchestrationState(workflowInstanceId, getInputsAndOutputs); - if (state !== undefined) { - return new WorkflowState(state); - } - } +Create the following `src/app.ts` file: - /** - * Waits for a workflow to start running - */ - public async waitForWorkflowStart( - workflowInstanceId: string, - fetchPayloads = true, - timeoutInSeconds = 60, - ): Promise { - const state = await this._innerClient.waitForOrchestrationStart( - workflowInstanceId, - fetchPayloads, - timeoutInSeconds, - ); - if (state !== undefined) { - return new WorkflowState(state); - } - } +```typescript +import { + WorkflowRuntime, + WorkflowActivityContext, + WorkflowContext, + DaprWorkflowClient, + TWorkflow +} from "@dapr/dapr"; - /** - * Waits for a workflow to complete running - */ - public async waitForWorkflowCompletion( - workflowInstanceId: string, - fetchPayloads = true, - timeoutInSeconds = 60, - ): Promise { - const state = await this._innerClient.waitForOrchestrationCompletion( - workflowInstanceId, - fetchPayloads, - timeoutInSeconds, - ); - if (state != undefined) { - return new WorkflowState(state); - } - } +const workflowClient = new DaprWorkflowClient(); +const workflowRuntime = new WorkflowRuntime(); - /** - * Sends an event notification message to an awaiting workflow instance - */ - public async raiseEvent(workflowInstanceId: string, eventName: string, eventPayload?: any) { - this._innerClient.raiseOrchestrationEvent(workflowInstanceId, eventName, eventPayload); - } +// simple activity +const hello = async (_: WorkflowActivityContext, name: string) => `Hello ${name}!`; - /** - * Purges the workflow instance state from the workflow state store. - */ - public async purgeWorkflow(workflowInstanceId: string): Promise { - const purgeResult = await this._innerClient.purgeOrchestration(workflowInstanceId); - if (purgeResult !== undefined) { - return purgeResult.deletedInstanceCount > 0; - } - return false; - } +// simple workflow: call the activity 3 times +const sequence: TWorkflow = async function* (ctx: WorkflowContext): any { + const out: string[] = []; + out.push(yield ctx.callActivity(hello, "Tokyo")); + out.push(yield ctx.callActivity(hello, "Seattle")); + out.push(yield ctx.callActivity(hello, "London")); + out.push(yield ctx.waitForExternalEvent("continue")); + return out; +}; + +async function main() { + workflowRuntime.registerWorkflow(sequence).registerActivity(hello); + await workflowRuntime.start(); + + const id = await workflowClient.scheduleNewWorkflow(sequence); + console.log("Scheduled:", id); + + workflowClient.raiseEvent(id, "continue", "Go go go!"); + + const state = await workflowClient.waitForWorkflowCompletion(id, undefined, 30); + console.log("Done:", state?.runtimeStatus, "output:", state?.serializedOutput); + + await new Promise(f => setTimeout(f, 100000)); + + await workflowRuntime.stop(); + await workflowClient.stop(); - /** - * Closes the inner DurableTask client and shutdown the GRPC channel. - */ - public async stop() { - await this._innerClient.stop(); - } } + +main().catch((e) => { console.error(e); }); ``` {{% /tab %}} @@ -960,6 +901,7 @@ import ( "errors" "fmt" "log" + "strconv" "time" "github.com/dapr/durabletask-go/workflow" @@ -1004,7 +946,7 @@ func main() { // "start". This is useful for increasing the throughput of creating // workflows. // workflow.WithStartTime(time.Now()) - instanceID, err := wclient.ScheduleWorkflow(ctx, "BusinessWorkflow", workflow.WithInstanceID("a7a4168d-3a1c-41da-8a4f-e7f6d9c718d9"), workflow.WithInput(1)) + instanceID, err := wclient.ScheduleWorkflow(ctx, "BusinessWorkflow", workflow.WithInstanceID("a7a4168d-3a1c-41da-8a4f-e7f6d9c718d9"), workflow.WithInput("1")) if err != nil { log.Fatalf("failed to start workflow: %v", err) } @@ -1058,9 +1000,7 @@ func main() { fmt.Printf("stage: %d\n", stage) - waitCtx, cancel := context.WithTimeout(ctx, 5*time.Second) - _, err = wclient.WaitForWorkflowCompletion(waitCtx, instanceID) - cancel() + _, err = wclient.WaitForWorkflowCompletion(ctx, instanceID) if err != nil { log.Fatalf("failed to wait for workflow: %v", err) } @@ -1090,7 +1030,7 @@ func main() { fmt.Printf("stage: %d\n", stage) // Terminate workflow test - id, err := wclient.ScheduleWorkflow(ctx, "BusinessWorkflow", workflow.WithInstanceID("a7a4168d-3a1c-41da-8a4f-e7f6d9c718d9"), workflow.WithInput(1)) + id, err := wclient.ScheduleWorkflow(ctx, "BusinessWorkflow", workflow.WithInstanceID("a7a4168d-3a1c-41da-8a4f-e7f6d9c718d9"), workflow.WithInput("1")) if err != nil { log.Fatalf("failed to start workflow: %v", err) } @@ -1114,27 +1054,28 @@ func main() { } fmt.Println("workflow purged") + <-ctx.Done() cancel() fmt.Println("workflow worker successfully shutdown") } func BusinessWorkflow(ctx *workflow.WorkflowContext) (any, error) { - var input int + var input string if err := ctx.GetInput(&input); err != nil { return nil, err } var output string - if err := ctx.CallActivity(BusinessActivity, task.WithActivityInput(input)).Await(&output); err != nil { + if err := ctx.CallActivity(BusinessActivity, workflow.WithActivityInput(input)).Await(&output); err != nil { return nil, err } - err := ctx.WaitForSingleEvent("businessEvent", time.Second*60).Await(&output) + err := ctx.WaitForExternalEvent("businessEvent", time.Minute*60).Await(&output) if err != nil { return nil, err } - if err := ctx.CallActivity(BusinessActivity, task.WithActivityInput(input)).Await(&output); err != nil { + if err := ctx.CallActivity(BusinessActivity, workflow.WithActivityInput(input)).Await(&output); err != nil { return nil, err } @@ -1150,13 +1091,18 @@ func BusinessWorkflow(ctx *workflow.WorkflowContext) (any, error) { return output, nil } -func BusinessActivity(ctx task.ActivityContext) (any, error) { - var input int +func BusinessActivity(ctx workflow.ActivityContext) (any, error) { + var input string if err := ctx.GetInput(&input); err != nil { return "", err } - stage += input + iinput, err := strconv.Atoi(input) + if err != nil { + return "", err + } + + stage += iinput return fmt.Sprintf("Stage: %d", stage), nil } @@ -1179,22 +1125,226 @@ Because of how replay-based workflows execute, you'll write logic that does thin {{% /alert %}} -## Testing Your Workflow +## Testing your workflow After authoring your workflow, test it using the Dapr CLI: -### Start Your Workflow +{{< tabpane text=true >}} + +{{% tab "Python" %}} + +#### Run the workflow application + +```bash +dapr run --app-id workflow-app python3 app.py +``` +Make sure the application is running: + +```bash +dapr list +``` + +#### Run the workflow +```bash +dapr workflow run hello_world_wf --app-id workflow-app --input 'hello world' --instance-id test-run +``` + +#### Check the workflow status +```bash +dapr workflow list --app-id workflow-app --connection-string=redis://127.0.0.1:6379 -o wide +``` + +#### Check completed workflows +```bash +dapr workflow list --app-id workflow-app --connection-string=redis://127.0.0.1:6379 --filter-status COMPLETED -o wide +``` + +#### View workflow history +```bash +dapr workflow history --app-id workflow-app test-run +``` + +{{% /tab %}} + +{{% tab "Javascript" %}} + +#### Run the workflow application + +```bash +dapr run --app-id workflow-app npx ts-node src/app.ts +``` +Make sure the application is running: + +```bash +dapr list +``` + +#### Run the workflow +```bash +dapr workflow run sequence --app-id workflow-app --input 'hello world' --instance-id test-run +``` + +#### Check the workflow status +```bash +dapr workflow list --app-id workflow-app --connection-string=redis://127.0.0.1:6379 -o wide +``` + +#### Raise the waiting external event +```bash +dapr workflow raise-event --app-id workflow-app test-run/businessEvent +``` + +#### Check completed workflows +```bash +dapr workflow list --app-id workflow-app --connection-string=redis://127.0.0.1:6379 --filter-status COMPLETED -o wide +``` + +#### View workflow history +```bash +dapr workflow history --app-id workflow-app test-run +``` + +{{% /tab %}} + +{{% tab ".NET" %}} + +#### Run the workflow application + +```bash +dapr run --app-id workflow-app dotnet run +``` +Make sure the application is running: + +```bash +dapr list +``` + +#### Run the workflow +```bash +dapr workflow run OrderProcessingWorkflow --app-id workflow-app --instance-id test-run --input '{"name": "Paperclips", "totalCost": 99.95}' +``` + +#### Check the workflow status +```bash +dapr workflow list --app-id workflow-app --connection-string=redis://127.0.0.1:6379 -o wide +``` + +#### Raise the waiting external event +```bash +dapr workflow raise-event --app-id workflow-app test-run/incoming-purchase-order --input '{"name": "Paperclips", "totalCost": 99.95}' +``` + +#### Check completed workflows +```bash +dapr workflow list --app-id workflow-app --connection-string=redis://127.0.0.1:6379 --filter-status COMPLETED -o wide +``` + +#### View workflow history +```bash +dapr workflow history --app-id workflow-app test-run +``` + +{{% /tab %}} + +{{% tab "Java" %}} + +#### Run the workflow application + +```bash +dapr run --app-id workflow-app -- java -jar target/WorkflowService-0.0.1-SNAPSHOT.jar +``` + +Make sure the application is running: + +```bash +dapr list +``` + +#### Run the workflow +```bash +dapr workflow run DemoWorkflow --app-id workflow-app --instance-id test-run --input "input data" +``` + +#### Check the workflow status +```bash +dapr workflow list --app-id workflow-app --connection-string=redis://127.0.0.1:6379 -o wide +``` +#### Raise the waiting external event ```bash -dapr workflow run OrderProcessingWorkflow \ - --app-id orderservice \ - --input '{"orderId": "test-001", "items": [{"sku": "WIDGET", "quantity": 5}]}' +dapr workflow raise-event --app-id workflow-app test-run/TestEvent --input 'TestEventPayload' +dapr workflow raise-event --app-id workflow-app test-run/event1 --input 'TestEvent 1 Payload' +dapr workflow raise-event --app-id workflow-app test-run/event2 --input 'TestEvent 2 Payload' +dapr workflow raise-event --app-id workflow-app test-run/event3 --input 'TestEvent 3 Payload' ``` +#### Check completed workflows +```bash +dapr workflow list --app-id workflow-app --connection-string=redis://127.0.0.1:6379 --filter-status COMPLETED -o wide +``` + +#### View workflow history +```bash +dapr workflow history --app-id workflow-app test-run +``` + +{{% /tab %}} + +{{% tab "Go" %}} + +#### Run the workflow application +```bash +dapr run --app-id workflow-app go run main.go +``` + +Make sure the application is running: + +```bash +dapr list +``` + +#### Run the workflow +```bash +dapr workflow run BusinessWorkflow --app-id workflow-app --input '1' --instance-id test-run +``` + +#### Check the workflow status +```bash +dapr workflow list --app-id workflow-app --connection-string=redis://127.0.0.1:6379 -o wide +``` + +#### Raise the waiting external event +```bash +dapr workflow raise-event --app-id workflow-app test-run/businessEvent +``` + +#### Check completed workflows +```bash +dapr workflow list --app-id workflow-app --connection-string=redis://127.0.0.1:6379 --filter-status COMPLETED -o wide +``` + +#### View workflow history +```bash +dapr workflow history test-run --app-id workflow-app +``` + +{{% /tab %}} + +{{< /tabpane >}} + + ### Monitor Workflow Execution ```bash -dapr workflow list --app-id orderservice --filter-status RUNNING +dapr workflow list --app-id workflow-app --filter-status RUNNING -o wide +``` + +```bash +dapr workflow list --app-id workflow-app --filter-status FAILED -o wide +``` + +```bash +dapr workflow list --app-id workflow-app --filter-status COMPLETED -o wide ``` ### Test External Events @@ -1202,7 +1352,7 @@ dapr workflow list --app-id orderservice --filter-status RUNNING ```bash # Raise an event your workflow is waiting for dapr workflow raise-event /ApprovalReceived \ - --app-id orderservice \ + --app-id workflow-app \ --input '{"approved": true, "approver": "manager@company.com"}' ``` @@ -1210,13 +1360,13 @@ dapr workflow raise-event /ApprovalReceived \ ```bash # List failed workflows -dapr workflow list --app-id orderservice --filter-status FAILED --output wide +dapr workflow list --app-id workflow-app --filter-status FAILED --output wide # Get detailed history of a failed workflow -dapr workflow history --app-id orderservice --output json +dapr workflow history --app-id workflow-app --output json # Re-run the workflow after fixing issues -dapr workflow rerun --app-id orderservice +dapr workflow rerun --app-id workflow-app --input '' ``` ## Next steps 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 ae9ccdcc418..e6b994c73fd 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 @@ -71,12 +71,12 @@ dapr scheduler import -f workflow-reminders-backup.bin ## Managing Workflows with the Dapr CLI -The Dapr CLI provides powerful commands for managing workflow instances in both self-hosted and Kubernetes environments. +The Dapr CLI provides commands for managing workflow instances in both self-hosted and Kubernetes environments. ### Prerequisites - Dapr CLI version 1.16.2 or later -- A running Dapr application with workflows configured +- A running Dapr application that has registered a workflow - For database operations: network access to your actor state store ### Basic Workflow Operations @@ -84,18 +84,18 @@ The Dapr CLI provides powerful commands for managing workflow instances in both #### Start a Workflow ```bash -# Start a workflow with input data +# Using the `orderprocessing` application, start a new workflow instance with input data dapr workflow run OrderProcessingWorkflow \ --app-id orderprocessing \ --input '{"orderId": "12345", "amount": 100.50}' -# Start with a specific instance ID +# Start with a new workflow with a specific instance ID dapr workflow run OrderProcessingWorkflow \ --app-id orderprocessing \ --instance-id order-12345 \ --input '{"orderId": "12345"}' -# Schedule a workflow to start later +# Schedule a new workflow to start at 10:00:00 AM on December 25, 2024, Coordinated Universal Time (UTC). dapr workflow run OrderProcessingWorkflow \ --app-id orderprocessing \ --start-time "2024-12-25T10:00:00Z" @@ -223,7 +223,7 @@ In self-hosted mode, the CLI can automatically discover your state store configu ```bash # The CLI reads your component configuration automatically -dapr workflow list --app-id orderprocessing +dapr workflow list --app-id orderprocessing --connection-string=redis://127.0.0.1:6379 ``` To override with a specific connection string: @@ -233,19 +233,24 @@ To override with a specific connection string: dapr workflow list \ --app-id orderprocessing \ --connection-string "host=localhost user=dapr password=dapr dbname=dapr port=5432 sslmode=disable" \ - --table-name workflows + --table-name actor-store # MySQL dapr workflow list \ --app-id orderprocessing \ --connection-string "dapr:dapr@tcp(localhost:3306)/dapr?parseTime=true" \ - --table-name workflows + --table-name actor-store # SQL Server dapr workflow list \ --app-id orderprocessing \ --connection-string "sqlserver://dapr:Pass@word1@localhost:1433?database=dapr" \ - --table-name workflows + --table-name abc + +# Redis +dapr workflow list \ + --app-id orderprocessing \ + --connection-string=redis://user:mypassword@127.0.0.1:6379 \ ``` #### Kubernetes Mode with Port Forwarding @@ -263,6 +268,9 @@ kubectl port-forward service/mysql 3306:3306 -n production # SQL Server kubectl port-forward service/mssql 1433:1433 -n production + +# Redis +kubectl port-forward service/redis 6379:6379 -n production ``` **Step 2: Use the CLI with the connection string** @@ -316,7 +324,7 @@ mongodb://username:password@localhost:27017/database **Redis** ``` -localhost:6379,password=secret,db=0 +redis://127.0.0.1:6379 ``` ### Workflow Management Best Practices diff --git a/daprdocs/content/en/developing-applications/building-blocks/workflow/workflow-architecture.md b/daprdocs/content/en/developing-applications/building-blocks/workflow/workflow-architecture.md index e06ba6725b5..47893aab80a 100644 --- a/daprdocs/content/en/developing-applications/building-blocks/workflow/workflow-architecture.md +++ b/daprdocs/content/en/developing-applications/building-blocks/workflow/workflow-architecture.md @@ -194,7 +194,7 @@ This number may be larger or smaller depending on retries or concurrency. For advanced operations, you can access workflow data directly: ```bash -# Port forward to database in Kubernetes +# Port forward to a postgres database in Kubernetes kubectl port-forward service/postgres 5432:5432 # Query workflows directly @@ -204,6 +204,17 @@ dapr workflow list \ --table-name workflows ``` +```bash +# Port forward to redis database in Kubernetes +kubectl port-forward service/redis 6379:6379 + +# Query workflows directly +dapr workflow list \ + --app-id myapp \ + --connection-string redis://127.0.0.1:6379 \ + --table-name workflows +``` + ### Supported State Stores The workflow engine supports these state stores: 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 a35899396d4..cce02d3316b 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 @@ -127,7 +127,7 @@ dapr workflow run MyWorkflow --app-id myapp --input '{"key": "value"}' **Monitor Workflows** ```bash -# List active workflows +# List active workflows for a given application dapr workflow list --app-id myapp --filter-status RUNNING # View execution history diff --git a/daprdocs/content/en/getting-started/quickstarts/workflow-quickstart.md b/daprdocs/content/en/getting-started/quickstarts/workflow-quickstart.md index bfa1772635b..15401e30dc6 100644 --- a/daprdocs/content/en/getting-started/quickstarts/workflow-quickstart.md +++ b/daprdocs/content/en/getting-started/quickstarts/workflow-quickstart.md @@ -1847,6 +1847,7 @@ func main() { fmt.Printf("workflow status: %v\n", respFetch.String()) fmt.Println("Purchase of item is complete") + select {} } func restockInventory(daprClient client.Client, inventory []InventoryItem) error { @@ -2071,9 +2072,11 @@ Now that your workflow is running, let's learn how to manage it using the Dapr C ### View Running Workflows +Open a separate terminal and run the following CLI commands. + ```bash # List all workflows -dapr workflow list --app-id orderprocessing +dapr workflow list --app-id orderprocessing --connection-string=redis://127.0.0.1:6379 # You should see output like: # INSTANCE ID WORKFLOW NAME CREATED LAST UPDATED RUNTIME STATUS @@ -2085,7 +2088,7 @@ dapr workflow list --app-id orderprocessing View the detailed execution history of your workflow: ```bash -dapr workflow history order-20240312-001 --app-id orderprocessing +dapr workflow history order-20240312-001 --app-id orderprocessing --connection-string=redis://127.0.0.1:6379 ``` ### Interact with Your Workflow @@ -2095,9 +2098,10 @@ dapr workflow history order-20240312-001 --app-id orderprocessing If your workflow is waiting for an external event: ```bash -dapr workflow raise-event order-20240312-001/PaymentReceived \ +dapr workflow raise-event order-20240312-001/ApprovalEvent \ --app-id orderprocessing \ - --input '{"paymentId": "pay-123", "amount": 100.00}' + --input '{"paymentId": "pay-123", "amount": 100.00}' \ + --connection-string=redis://127.0.0.1:6379 ``` #### Suspend and Resume diff --git a/daprdocs/content/en/reference/cli/dapr-workflow.md b/daprdocs/content/en/reference/cli/dapr-workflow.md index 08499a62adb..2ec7f343772 100644 --- a/daprdocs/content/en/reference/cli/dapr-workflow.md +++ b/daprdocs/content/en/reference/cli/dapr-workflow.md @@ -138,7 +138,7 @@ mongodb://localhost:27017/dapr ### Redis ``` -localhost:6379,password=secret,db=0 +redis://localhost:6379 ``` ## Purge workflow instances with terminal states (COMPLETED, FAILED, TERMINATED). From 4b122b75b3b24883f257b2d5cf1619826f53fec2 Mon Sep 17 00:00:00 2001 From: joshvanl Date: Thu, 6 Nov 2025 18:26:44 +0000 Subject: [PATCH 5/9] Add redis example format Signed-off-by: joshvanl --- daprdocs/content/en/reference/cli/dapr-workflow.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/daprdocs/content/en/reference/cli/dapr-workflow.md b/daprdocs/content/en/reference/cli/dapr-workflow.md index 2ec7f343772..f490a8a7ecd 100644 --- a/daprdocs/content/en/reference/cli/dapr-workflow.md +++ b/daprdocs/content/en/reference/cli/dapr-workflow.md @@ -138,7 +138,7 @@ mongodb://localhost:27017/dapr ### Redis ``` -redis://localhost:6379 +redis[s]://[[username][:password]@][host][:port][/db-number]: ``` ## Purge workflow instances with terminal states (COMPLETED, FAILED, TERMINATED). From 802d3775f8d1d536f2b30a52c97aea82418705d3 Mon Sep 17 00:00:00 2001 From: joshvanl Date: Thu, 6 Nov 2025 18:30:03 +0000 Subject: [PATCH 6/9] Fix commands on quickstart Signed-off-by: joshvanl --- .../quickstarts/workflow-quickstart.md | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/daprdocs/content/en/getting-started/quickstarts/workflow-quickstart.md b/daprdocs/content/en/getting-started/quickstarts/workflow-quickstart.md index 15401e30dc6..a95bcc09313 100644 --- a/daprdocs/content/en/getting-started/quickstarts/workflow-quickstart.md +++ b/daprdocs/content/en/getting-started/quickstarts/workflow-quickstart.md @@ -2077,10 +2077,13 @@ Open a separate terminal and run the following CLI commands. ```bash # List all workflows dapr workflow list --app-id orderprocessing --connection-string=redis://127.0.0.1:6379 +``` + +You should see output like: -# You should see output like: -# INSTANCE ID WORKFLOW NAME CREATED LAST UPDATED RUNTIME STATUS -# order-20240312-001 OrderProcessingWorkflow 2024-03-12 10:00:00 2024-03-12 10:00:05 RUNNING +``` +INSTANCE ID WORKFLOW NAME CREATED LAST UPDATED RUNTIME STATUS +order-20240312-001 OrderProcessingWorkflow 2024-03-12 10:00:00 2024-03-12 10:00:05 RUNNING ``` ### Check Workflow History @@ -2088,7 +2091,7 @@ dapr workflow list --app-id orderprocessing --connection-string=redis://127.0.0. View the detailed execution history of your workflow: ```bash -dapr workflow history order-20240312-001 --app-id orderprocessing --connection-string=redis://127.0.0.1:6379 +dapr workflow history order-20240312-001 --app-id orderprocessing ``` ### Interact with Your Workflow @@ -2100,8 +2103,7 @@ If your workflow is waiting for an external event: ```bash dapr workflow raise-event order-20240312-001/ApprovalEvent \ --app-id orderprocessing \ - --input '{"paymentId": "pay-123", "amount": 100.00}' \ - --connection-string=redis://127.0.0.1:6379 + --input '{"paymentId": "pay-123", "amount": 100.00}' ``` #### Suspend and Resume @@ -2124,10 +2126,10 @@ After testing, purge completed workflows: ```bash # Purge a specific workflow -dapr workflow purge order-20240312-001 --app-id orderprocessing +dapr workflow purge order-20240312-001 --app-id orderprocessing --connection-string=redis://127.0.0.1:6379 # Or purge all completed workflows -dapr workflow purge --app-id orderprocessing --all-older-than 1h +dapr workflow purge --app-id orderprocessing --connection-string=redis://127.0.0.1:6379 --all-older-than 1h ``` ## Tell us what you think! From 4d118589bc8b818f4c26c634ca6188550192a178 Mon Sep 17 00:00:00 2001 From: joshvanl Date: Fri, 7 Nov 2025 12:25:20 +0000 Subject: [PATCH 7/9] Adds review comments Signed-off-by: joshvanl --- .../workflow/howto-manage-workflow.md | 8 ++ .../quickstarts/workflow-quickstart.md | 107 +++++++++++++++--- 2 files changed, 99 insertions(+), 16 deletions(-) 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 e6b994c73fd..2631174d749 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 @@ -179,6 +179,14 @@ dapr workflow rerun order-12345 \ Note that purging a workflow from the CLI will also delete all associated Scheduler reminders. +{{% alert title="Important" color="warning" %}} +In order to preserve the workflow state machine integrity and prevent corruption, purging workflow requires that the workflow client for that app ID is running. +Errors like the following suggest that the workflow client is not running: +``` +failed to purge orchestration state: rpc error: code = FailedPrecondition desc = failed to purge orchestration state: failed to lookup actor: api error: code = FailedPrecondition desc = did not find address for actor +``` +{{% /alert %}} + ```bash # Purge a specific instance dapr workflow purge order-12345 --app-id orderprocessing diff --git a/daprdocs/content/en/getting-started/quickstarts/workflow-quickstart.md b/daprdocs/content/en/getting-started/quickstarts/workflow-quickstart.md index a95bcc09313..61010e1f6a0 100644 --- a/daprdocs/content/en/getting-started/quickstarts/workflow-quickstart.md +++ b/daprdocs/content/en/getting-started/quickstarts/workflow-quickstart.md @@ -1827,7 +1827,7 @@ func main() { TotalCost: totalCost, } - id, err := wfClient.ScheduleWorkflow(context.Background(), workflowName, workflow.WithInput(orderPayload)) + id, err := wfClient.ScheduleWorkflow(context.Background(), workflowName, workflow.WithInput(orderPayload), workflow.WithInstanceID("order-"+time.Now().Format("20060102150405"))) if err != nil { log.Fatalf("failed to start workflow: %v", err) } @@ -1847,7 +1847,7 @@ func main() { fmt.Printf("workflow status: %v\n", respFetch.String()) fmt.Println("Purchase of item is complete") - select {} + select {} } func restockInventory(daprClient client.Client, inventory []InventoryItem) error { @@ -1882,6 +1882,48 @@ import ( "github.com/dapr/go-sdk/client" ) +type OrderPayload struct { + ItemName string `json:"item_name"` + TotalCost int `json:"total_cost"` + Quantity int `json:"quantity"` +} + +type OrderResult struct { + Processed bool `json:"processed"` +} + +type InventoryItem struct { + ItemName string `json:"item_name"` + PerItemCost int `json:"per_item_cost"` + Quantity int `json:"quantity"` +} + +type InventoryRequest struct { + RequestID string `json:"request_id"` + ItemName string `json:"item_name"` + Quantity int `json:"quantity"` +} + +type InventoryResult struct { + Success bool `json:"success"` + InventoryItem InventoryItem `json:"inventory_item"` +} + +type PaymentRequest struct { + RequestID string `json:"request_id"` + ItemBeingPurchased string `json:"item_being_purchased"` + Amount int `json:"amount"` + Quantity int `json:"quantity"` +} + +type ApprovalRequired struct { + Approval bool `json:"approval"` +} + +type Notification struct { + Message string `json:"message"` +} + // OrderProcessingWorkflow is the main workflow for orchestrating activities in the order process. func OrderProcessingWorkflow(ctx *workflow.WorkflowContext) (any, error) { orderID := ctx.ID() @@ -2076,14 +2118,14 @@ Open a separate terminal and run the following CLI commands. ```bash # List all workflows -dapr workflow list --app-id orderprocessing --connection-string=redis://127.0.0.1:6379 +dapr workflow list --app-id order-processing --connection-string=redis://127.0.0.1:6379 -o wide ``` You should see output like: ``` -INSTANCE ID WORKFLOW NAME CREATED LAST UPDATED RUNTIME STATUS -order-20240312-001 OrderProcessingWorkflow 2024-03-12 10:00:00 2024-03-12 10:00:05 RUNNING +NAMESPACE APP ID NAME INSTANCE ID CREATED LAST UPDATE STATUS +default order-processor OrderProcessingWorkflow order-20251107114222 2025-11-07T11:42:22Z 2025-11-07T11:42:22Z COMPLETED ``` ### Check Workflow History @@ -2091,18 +2133,43 @@ order-20240312-001 OrderProcessingWorkflow 2024-03-12 10:00:00 2024-03-12 View the detailed execution history of your workflow: ```bash -dapr workflow history order-20240312-001 --app-id orderprocessing +dapr workflow history order-20251107114222 --app-id order-processor +``` + +You should see output like: + +``` +TYPE NAME EVENTID ELAPSED STATUS DETAILS +ExecutionStarted OrderProcessingWorkflow - Age:1.1m RUNNING orchestration start +OrchestratorStarted - - 13.4ms RUNNING replay cycle start +TaskScheduled NotifyActivity 0 1.3ms RUNNING activity=NotifyActivity +TaskCompleted - - 2.6ms RUNNING eventId=0 +OrchestratorStarted - - 2.6ms RUNNING replay cycle start +TaskScheduled VerifyInventoryActivity 1 637.6µs RUNNING activity=VerifyInventoryActivity +TaskCompleted - - 2.4ms RUNNING eventId=1 +OrchestratorStarted - - 1.7ms RUNNING replay cycle start +TaskScheduled ProcessPaymentActivity 2 439.3µs RUNNING activity=ProcessPaymentActivity +TaskCompleted - - 1.6ms RUNNING eventId=2 +OrchestratorStarted - - 1.5ms RUNNING replay cycle start +TaskScheduled UpdateInventoryActivity 3 311.2µs RUNNING activity=UpdateInventoryActivity +TaskCompleted - - 2.4ms RUNNING eventId=3 +OrchestratorStarted - - 2.7ms RUNNING replay cycle start +TaskScheduled NotifyActivity 4 354.1µs RUNNING activity=NotifyActivity +TaskCompleted - - 2.5ms RUNNING eventId=4 +OrchestratorStarted - - 1.6ms RUNNING replay cycle start +ExecutionCompleted - 5 517.1µs COMPLETED execDuration=38.7ms ``` ### Interact with Your Workflow #### Raise an External Event -If your workflow is waiting for an external event: +If your workflow is waiting for an [external event]({{% ref "workflow-patterns.md#external-system-interaction" %}}), you can raise one. +It takes a single argument in the format of `/`. ```bash -dapr workflow raise-event order-20240312-001/ApprovalEvent \ - --app-id orderprocessing \ +dapr workflow raise-event order-20251107114222/ApprovalEvent \ + --app-id order-processor \ --input '{"paymentId": "pay-123", "amount": 100.00}' ``` @@ -2110,26 +2177,34 @@ dapr workflow raise-event order-20240312-001/ApprovalEvent \ ```bash # Suspend a workflow -dapr workflow suspend order-20240312-001 \ - --app-id orderprocessing \ +dapr workflow suspend order-20251107114222 \ + --app-id order-processor \ --reason "Waiting for inventory" # Resume when ready -dapr workflow resume order-20240312-001 \ - --app-id orderprocessing \ +dapr workflow resume order-20251107114222 \ + --app-id order-processor \ --reason "Inventory received" ``` ### Clean Up -After testing, purge completed workflows: +After testing, purge completed workflows. + +{{% alert title="Important" color="warning" %}} +In order to preserve the workflow state machine integrity and prevent corruption, purging workflow requires that the workflow client for that app ID is running. +Errors like the following suggest that the workflow client is not running: +``` +failed to purge orchestration state: rpc error: code = FailedPrecondition desc = failed to purge orchestration state: failed to lookup actor: api error: code = FailedPrecondition desc = did not find address for actor +``` +{{% /alert %}} ```bash # Purge a specific workflow -dapr workflow purge order-20240312-001 --app-id orderprocessing --connection-string=redis://127.0.0.1:6379 +dapr workflow purge order-20251107114222 --app-id order-processor --connection-string=redis://127.0.0.1:6379 # Or purge all completed workflows -dapr workflow purge --app-id orderprocessing --connection-string=redis://127.0.0.1:6379 --all-older-than 1h +dapr workflow purge --app-id order-processor --connection-string=redis://127.0.0.1:6379 --all-older-than 1h ``` ## Tell us what you think! From dcb0d0ad028b8e82e41048e02d51d2648a223447 Mon Sep 17 00:00:00 2001 From: joshvanl Date: Fri, 7 Nov 2025 12:37:42 +0000 Subject: [PATCH 8/9] Update important purge note Signed-off-by: joshvanl --- .../workflow/howto-manage-workflow.md | 2 +- .../quickstarts/workflow-quickstart.md | 19 ++++++++++--------- 2 files changed, 11 insertions(+), 10 deletions(-) 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 2631174d749..071281140a3 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 @@ -180,7 +180,7 @@ dapr workflow rerun order-12345 \ Note that purging a workflow from the CLI will also delete all associated Scheduler reminders. {{% alert title="Important" color="warning" %}} -In order to preserve the workflow state machine integrity and prevent corruption, purging workflow requires that the workflow client for that app ID is running. +In order to preserve the workflow state machine integrity and prevent corruption, purging workflows require that the workflow client is running in the application. Errors like the following suggest that the workflow client is not running: ``` failed to purge orchestration state: rpc error: code = FailedPrecondition desc = failed to purge orchestration state: failed to lookup actor: api error: code = FailedPrecondition desc = did not find address for actor diff --git a/daprdocs/content/en/getting-started/quickstarts/workflow-quickstart.md b/daprdocs/content/en/getting-started/quickstarts/workflow-quickstart.md index 61010e1f6a0..65b7795a561 100644 --- a/daprdocs/content/en/getting-started/quickstarts/workflow-quickstart.md +++ b/daprdocs/content/en/getting-started/quickstarts/workflow-quickstart.md @@ -2118,14 +2118,14 @@ Open a separate terminal and run the following CLI commands. ```bash # List all workflows -dapr workflow list --app-id order-processing --connection-string=redis://127.0.0.1:6379 -o wide +dapr workflow list --app-id order-processor --connection-string=redis://127.0.0.1:6379 -o wide ``` You should see output like: ``` -NAMESPACE APP ID NAME INSTANCE ID CREATED LAST UPDATE STATUS -default order-processor OrderProcessingWorkflow order-20251107114222 2025-11-07T11:42:22Z 2025-11-07T11:42:22Z COMPLETED +NAMESPACE APP ID NAME INSTANCE ID CREATED LAST UPDATE STATUS +default order-processor OrderProcessingWorkflow e4d3807c 2025-11-07T12:29:37Z 2025-11-07T12:29:52Z COMPLETED ``` ### Check Workflow History @@ -2133,7 +2133,7 @@ default order-processor OrderProcessingWorkflow order-20251107114222 2025- View the detailed execution history of your workflow: ```bash -dapr workflow history order-20251107114222 --app-id order-processor +dapr workflow history e4d3807c --app-id order-processor ``` You should see output like: @@ -2168,7 +2168,7 @@ If your workflow is waiting for an [external event]({{% ref "workflow-patterns.m It takes a single argument in the format of `/`. ```bash -dapr workflow raise-event order-20251107114222/ApprovalEvent \ +dapr workflow raise-event e4d3807c/ApprovalEvent \ --app-id order-processor \ --input '{"paymentId": "pay-123", "amount": 100.00}' ``` @@ -2177,12 +2177,12 @@ dapr workflow raise-event order-20251107114222/ApprovalEvent \ ```bash # Suspend a workflow -dapr workflow suspend order-20251107114222 \ +dapr workflow suspend e4d3807c \ --app-id order-processor \ --reason "Waiting for inventory" # Resume when ready -dapr workflow resume order-20251107114222 \ +dapr workflow resume e4d3807c \ --app-id order-processor \ --reason "Inventory received" ``` @@ -2192,7 +2192,7 @@ dapr workflow resume order-20251107114222 \ After testing, purge completed workflows. {{% alert title="Important" color="warning" %}} -In order to preserve the workflow state machine integrity and prevent corruption, purging workflow requires that the workflow client for that app ID is running. +In order to preserve the workflow state machine integrity and prevent corruption, purging workflows require that the workflow client is running in the application. Errors like the following suggest that the workflow client is not running: ``` failed to purge orchestration state: rpc error: code = FailedPrecondition desc = failed to purge orchestration state: failed to lookup actor: api error: code = FailedPrecondition desc = did not find address for actor @@ -2201,7 +2201,7 @@ failed to purge orchestration state: rpc error: code = FailedPrecondition desc = ```bash # Purge a specific workflow -dapr workflow purge order-20251107114222 --app-id order-processor --connection-string=redis://127.0.0.1:6379 +dapr workflow purge e4d3807c --app-id order-processor --connection-string=redis://127.0.0.1:6379 # Or purge all completed workflows dapr workflow purge --app-id order-processor --connection-string=redis://127.0.0.1:6379 --all-older-than 1h @@ -2218,5 +2218,6 @@ Join the discussion in our [discord channel](https://discord.com/channels/778680 - Set up Dapr Workflow with any programming language using [HTTP instead of an SDK]({{% ref howto-manage-workflow.md %}}) - Walk through a more in-depth [.NET SDK example workflow](https://github.com/dapr/dotnet-sdk/tree/master/examples/Workflow) - Learn more about [Workflow as a Dapr building block]({{% ref workflow-overview %}}) +``` {{< button text="Explore Dapr tutorials >>" page="getting-started/tutorials/_index.md" >}} From c5fd0356d3a86417f6df90b271f9d64c15b4f4cf Mon Sep 17 00:00:00 2001 From: joshvanl Date: Mon, 10 Nov 2025 12:53:50 +0000 Subject: [PATCH 9/9] Make clear about workflow client connection for purging Signed-off-by: joshvanl --- .../building-blocks/workflow/howto-manage-workflow.md | 3 ++- .../en/getting-started/quickstarts/workflow-quickstart.md | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) 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 071281140a3..db41b48205a 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 @@ -180,7 +180,8 @@ dapr workflow rerun order-12345 \ Note that purging a workflow from the CLI will also delete all associated Scheduler reminders. {{% alert title="Important" color="warning" %}} -In order to preserve the workflow state machine integrity and prevent corruption, purging workflows require that the workflow client is running in the application. +It is required that a workflow client is running in the application to perform purge operations. +The workflow client connection is required in order to preserve the workflow state machine integrity and prevent corruption. Errors like the following suggest that the workflow client is not running: ``` failed to purge orchestration state: rpc error: code = FailedPrecondition desc = failed to purge orchestration state: failed to lookup actor: api error: code = FailedPrecondition desc = did not find address for actor diff --git a/daprdocs/content/en/getting-started/quickstarts/workflow-quickstart.md b/daprdocs/content/en/getting-started/quickstarts/workflow-quickstart.md index 65b7795a561..35839f5c511 100644 --- a/daprdocs/content/en/getting-started/quickstarts/workflow-quickstart.md +++ b/daprdocs/content/en/getting-started/quickstarts/workflow-quickstart.md @@ -2192,7 +2192,8 @@ dapr workflow resume e4d3807c \ After testing, purge completed workflows. {{% alert title="Important" color="warning" %}} -In order to preserve the workflow state machine integrity and prevent corruption, purging workflows require that the workflow client is running in the application. +It is required that a workflow client is running in the application to perform purge operations. +The workflow client connection is required in order to preserve the workflow state machine integrity and prevent corruption. Errors like the following suggest that the workflow client is not running: ``` failed to purge orchestration state: rpc error: code = FailedPrecondition desc = failed to purge orchestration state: failed to lookup actor: api error: code = FailedPrecondition desc = did not find address for actor