Workflow: cross-app client operations - #1806
Conversation
Adds an optional app ID to every client-level workflow operation on DaprWorkflowClient: scheduleNewWorkflow, getWorkflowState, waitForWorkflowStart, waitForWorkflowCompletion, raiseEvent, suspendWorkflow, resumeWorkflow, terminateWorkflow and purgeWorkflow. When set, the operation targets a workflow instance owned by another app in the same namespace, and the target app's WorkflowAccessPolicy decides whether it is permitted. The existing signatures stay and delegate with a null app ID, so local behaviour is unchanged. NewWorkflowOptions gains setAppId for scheduling a workflow on another app. DurableTaskClient mirrors the same overloads, and DurableTaskGrpcClient carries the value as a TaskRouter on each request via the new buildTaskRouter helper. An older runtime ignores the field and applies the operation to the caller's own app. Signed-off-by: joshvanl <me@joshvanl.dev>
There was a problem hiding this comment.
🟡 Changes recommended
The new abstract methods break external implementations, and empty app IDs are routed inconsistently.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
Adds cross-app routing to workflow client operations while retaining local-operation overloads.
Changes:
- Adds app-ID-aware workflow and durable-task APIs.
- Attaches
TaskRoutermetadata to gRPC requests. - Adds unit and multi-app integration coverage.
File summaries
| File | Description |
|---|---|
DaprWorkflowClientTest.java |
Tests app-ID forwarding. |
NewWorkflowOptions.java |
Adds target app ID configuration. |
DaprWorkflowClient.java |
Adds cross-app workflow operations. |
WorkflowsMultiAppCrossAppOperationsIT.java |
Tests remote workflow lifecycle operations. |
CrossAppEventWorkflow.java |
Provides the integration-test workflow. |
CrossAppEventWorker.java |
Hosts the integration-test workflow. |
ContainerConstants.java |
Adds the edge runtime image tag. |
DurableTaskGrpcClientRoutingTest.java |
Verifies request router metadata. |
DurableTaskGrpcClient.java |
Adds routers to gRPC requests. |
DurableTaskClient.java |
Adds app-ID overloads and compatibility delegates. |
Review details
- Files reviewed: 10/10 changed files
- Comments generated: 3
- Review effort level: Balanced
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Signed-off-by: joshvanl <me@joshvanl.dev>
There was a problem hiding this comment.
🟡 Changes recommended
The integration test uses a mutable runtime image, and two public API contracts need correction.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Review details
Suppressed comments (2)
Previously missed (2) — in code that hasn't changed since the last review.
sdk-tests/src/test/java/io/dapr/it/testcontainers/ContainerConstants.java:9
- This mutable
edgetag makes the integration suite depend on whatever dapr/dapr master produced most recently. A later image change can break CI—or become incompatible with the separately pinned 1.18 placement and scheduler images—without any SDK change. Please pin the tested edge build to an immutable tag or digest and update it deliberately.
sdk-workflows/src/main/java/io/dapr/workflows/client/NewWorkflowOptions.java:165 - Empty app IDs are also treated as local routing, but this return contract implies that only
nullrepresents the local app. AftersetAppId(""),getAppId()returns an empty string while routing locally, so callers could misinterpret the result.
- Files reviewed: 10/10 changed files
- Comments generated: 1
- Review effort level: Balanced
Signed-off-by: joshvanl <me@joshvanl.dev>
There was a problem hiding this comment.
🔵 Needs a closer look
The public API and routing changes depend on unreleased runtime behavior validated through a mutable, non-gating edge-image job.
Review details
- Files reviewed: 12/12 changed files
- Comments generated: 0 new
- Review effort level: Balanced
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #1806 +/- ##
=========================================
Coverage 78.17% 78.17%
- Complexity 2427 2438 +11
=========================================
Files 248 248
Lines 7438 7461 +23
Branches 774 780 +6
=========================================
+ Hits 5815 5833 +18
- Misses 1267 1268 +1
- Partials 356 360 +4 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Adds an optional app ID to every client-level workflow operation on DaprWorkflowClient: scheduleNewWorkflow, getWorkflowState, waitForWorkflowStart, waitForWorkflowCompletion, raiseEvent, suspendWorkflow, resumeWorkflow, terminateWorkflow and purgeWorkflow. When set, the operation targets a workflow instance owned by another app in the same namespace, and the target app's WorkflowAccessPolicy decides whether it is permitted. The existing signatures stay and delegate with a null app ID, so local behaviour is unchanged.
NewWorkflowOptions gains setAppId for scheduling a workflow on another app. DurableTaskClient mirrors the same overloads, and DurableTaskGrpcClient carries the value as a TaskRouter on each request via the new buildTaskRouter helper. An older runtime ignores the field and applies the operation to the caller's own app.
Description
Please explain the changes you've made
Issue reference
We strive to have all PR being opened based on an issue, where the problem or feature have been discussed prior to implementation.
Please reference the issue this PR will close: #[issue number]
Checklist
Please make sure you've completed the relevant tasks for this PR, out of the following list: