Skip to content

feat!: unify the durable task client into dapr-sdk-workflows - #1800

Open
javier-aliaga wants to merge 6 commits into
dapr:masterfrom
javier-aliaga:feat/workflows-v2
Open

javier-aliaga wants to merge 6 commits into
dapr:masterfrom
javier-aliaga:feat/workflows-v2

Conversation

@javier-aliaga

@javier-aliaga javier-aliaga commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

Description

durabletask-client is now part of dapr-sdk-workflows and is no longer published as a separate artifact. Its classes move from io.dapr.durabletask.* to io.dapr.workflows.task.*.

Until now both modules carried their own copy of several types, with an adapter layer in between to convert one into the other. Those copies are merged into a single set, so the adapter layer is gone. A few types are renamed, and the DaprWorkflowClient methods that were already marked for removal are removed.

One behaviour change: when you pass your own executor to WorkflowRuntimeBuilder.withExecutorService(...), the runtime no longer shuts it down on close. It only shuts down an executor it created itself.

This is a breaking change for workflow code. MIGRATION.md has the details: which type maps to which, what was removed, and what happens to workflows that are already running when you upgrade.

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:

  • Code compiles correctly
  • Created/updated tests
  • Extended the documentation

@javier-aliaga javier-aliaga changed the title Feat/workflows v2 feat!: unify the durable task client into dapr-sdk-workflows Sep 1, 2026
@javier-aliaga
javier-aliaga marked this pull request as ready for review September 1, 2026 11:36
@javier-aliaga
javier-aliaga requested review from a team as code owners September 1, 2026 11:36
The durabletask-client module duplicated much of the workflows API across
a module boundary, which forced an adapter layer and a second copy of a
dozen types. Fold it into dapr-sdk-workflows and remove it.

The absorbed types move from io.dapr.durabletask.* to
io.dapr.workflows.task.*, split into client, worker, history, exception,
serialization and internal subpackages. Twelve duplicate type-pairs
collapse to one each. Most significantly TaskOrchestrationContext becomes
WorkflowContext and is implemented directly by the replay executor, so
the DefaultWorkflowContext adapter and the converter and wrapper classes
it required are gone.

Two behaviour changes come with the merge:

- The runtime's default executor is a virtual-thread-per-task executor on
  Java 21+, resolved reflectively so the module still compiles at
  release 17 and never names a Java 21 API. WorkflowRuntime now tracks
  whether it created the executor and no longer shuts down one supplied
  by the caller, so handing it a framework-managed executor is safe.
- WorkflowRuntimeStatus absorbs the protobuf mapping and gains STALLED,
  which the deleted converter rejected with an exception.

isCausedBy maps the exception names that shipped under io.dapr.durabletask
onto their current types, so a workflow started before the upgrade still
resolves its failure type after it.

The CI job that built durabletask-client now installs its reactor
dependencies first: unlike the old module, the merged one depends on the
sibling dapr-sdk and cannot be built standalone.

BREAKING CHANGE: io.dapr:durabletask-client is removed and its classes
ship in io.dapr:dapr-sdk-workflows. Types move from io.dapr.durabletask.*
to io.dapr.workflows.task.*, seven types are renamed, and the four
@deprecated(forRemoval) DaprWorkflowClient methods together with
WorkflowInstanceStatus are removed. See MIGRATION.md for the full type
mapping and for what it means for workflows that are already running.

Signed-off-by: Javier Aliaga <javier@diagrid.io>
Folding durabletask-client into dapr-sdk-workflows is a breaking change,
so document it where an upgrader will look: MIGRATION.md carries the full
old-to-new type mapping, the renames, the removed API, the behaviour
changes that are invisible to the compiler, and a tested rewrite script
for the mechanical import changes.

The section on workflows that are already running is the important one.
The error type is persisted into workflow history, so a workflow started
before the upgrade carries the old exception names; the guide explains
what the SDK maps for you and what it does not.

Link the guide from README.md and SUPPORT.md, drop durabletask-client
from the module lists in both, and record that Java 21 is recommended for
workflows now that the default executor uses virtual threads there.

Signed-off-by: Javier Aliaga <javier@diagrid.io>
…private

Splitting the folded durable task types into subpackages moved the
executor away from the exceptions it constructs, and the visibility was
widened to compensate. It was widened further than the split required:
every constructor on both classes became public where only the two the
executor actually calls needed to be.

Restore the rest to package-private, matching what they were before the
merge. The two that stay public are the ones the executor constructs from
io.dapr.workflows.task.internal, and their javadoc now says so accurately
— the previous note claimed a sibling-package caller for members that
have none.

No test used any of these constructors, and no behaviour changes.

Signed-off-by: Javier Aliaga <javier@diagrid.io>
State in SUPPORT.md that durabletask-client is folded into dapr-sdk-workflows
in 1.19.x, so a user reading the version table knows which upgrade requires the
source changes described in MIGRATION.md.

Signed-off-by: Javier Aliaga <javier@diagrid.io>
@javier-aliaga

Copy link
Copy Markdown
Contributor Author

@siri-varma @salaboy what do you think? This was a pending task we are lagging between versions. Would be nice to do it.

The durabletask-client module had no jacoco configuration, so none of its
sources were measured. Folding them into dapr-sdk-workflows brings them into
the report, where the untested ones stood out: the activity and orchestration
runners had no tests at all.

Adds unit tests for the runners, the orchestration context operations that fan
tasks in and out, the gRPC client management operations, the client convenience
overloads and their cross-app guard, and the argument checks on the helpers,
converters, factories and builders. Line coverage for the module goes from 70%
to 86%, so the temporary 60% jacoco threshold this branch introduced is removed
and the module is back on the repo-wide 80% default.

Signed-off-by: Javier Aliaga <javier@diagrid.io>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Unresolved critical issues remain in the Maven reactor configuration and public Task API, with additional status-contract and lifecycle-test gaps.

Get a fresh assessment by requesting another Copilot review.

Pull request overview

This breaking-change PR unifies durabletask-client into dapr-sdk-workflows, relocating APIs, removing adapters and the standalone artifact, and updating consumers.

Changes:

  • Consolidates task, client, history, worker, and exception APIs.
  • Updates runtime lifecycle, retry/status handling, examples, tests, documentation, Maven, BOM, and CI.
  • Removes deprecated workflow APIs and duplicate durable-task sources.
File summaries
File Summary
SUPPORT.md Documents workflow migration.
spring-boot-sdk-tests/src/test/java/io/dapr/it/springboot/testcontainers/workflows/TestExecutionKeysWorkflow.java Updates task imports.
spring-boot-examples/workflows/patterns/src/main/java/io/dapr/springboot/examples/wfp/historypropagation/SettlePaymentActivity.java Updates history imports.
spring-boot-examples/workflows/patterns/src/main/java/io/dapr/springboot/examples/wfp/historypropagation/ProcessPaymentWorkflow.java Updates history imports.
spring-boot-examples/workflows/patterns/src/main/java/io/dapr/springboot/examples/wfp/historypropagation/FraudDetectionWorkflow.java Updates history imports.
spring-boot-examples/workflows/patterns/src/main/java/io/dapr/springboot/examples/wfp/historypropagation/FraudCheckActivity.java Updates history imports.
spring-boot-examples/workflows/patterns/src/main/java/io/dapr/springboot/examples/wfp/fanoutin/FanOutInWorkflow.java Updates task imports.
spring-boot-examples/workflows/multi-app/orchestrator/src/main/java/io/dapr/springboot/examples/orchestrator/CustomerWorkflow.java Updates exception imports.
sdk-workflows/src/test/java/io/dapr/workflows/WorkflowTest.java Updates test imports.
sdk-workflows/src/test/java/io/dapr/workflows/WorkflowTaskRetryPolicyTest.java Tests retry-policy validation.
sdk-workflows/src/test/java/io/dapr/workflows/WorkflowTaskRetryPolicyBuilderTest.java Tests retry-policy builder behavior.
sdk-workflows/src/test/java/io/dapr/workflows/WorkflowTaskOptionsTest.java Updates task-options tests.
sdk-workflows/src/test/java/io/dapr/workflows/WorkflowTaskOptionsMergedTest.java Migrates merged options tests.
sdk-workflows/src/test/java/io/dapr/workflows/WorkflowContextDefaultsTest.java Tests workflow-context defaults.
sdk-workflows/src/test/java/io/dapr/workflows/task/WorkItemObserver.java Relocates a test helper.
sdk-workflows/src/test/java/io/dapr/workflows/task/SubOrchestrationCrossAppTest.java Migrates cross-app tests.
sdk-workflows/src/test/java/io/dapr/workflows/task/StatefulHistoryIT.java Migrates stateful-history tests.
sdk-workflows/src/test/java/io/dapr/workflows/task/serialization/JacksonDataConverterTest.java Tests serialization behavior.
sdk-workflows/src/test/java/io/dapr/workflows/task/orchestration/TaskOrchestrationFactoriesTest.java Tests orchestration registration.
sdk-workflows/src/test/java/io/dapr/workflows/task/internal/WorkflowHistoryCacheTest.java Tests history caching.
sdk-workflows/src/test/java/io/dapr/workflows/task/internal/WorkflowContextLoggerTest.java Tests replay logging.
sdk-workflows/src/test/java/io/dapr/workflows/task/internal/TimerOriginTest.java Tests retry timer behavior.
sdk-workflows/src/test/java/io/dapr/workflows/task/internal/runner/OrchestratorRunnerHistoryTest.java Tests runner history handling.
sdk-workflows/src/test/java/io/dapr/workflows/task/internal/HistoryPropagationTest.java Tests history propagation.
sdk-workflows/src/test/java/io/dapr/workflows/task/internal/HelpersTest.java Tests internal helpers.
sdk-workflows/src/test/java/io/dapr/workflows/task/internal/AgentLoopEventDeliveryTest.java Tests event delivery.
sdk-workflows/src/test/java/io/dapr/workflows/task/IntegrationTestBase.java Updates integration-test setup.
sdk-workflows/src/test/java/io/dapr/workflows/task/HistoryPropagationIntegrationTest.java Tests propagation integration.
sdk-workflows/src/test/java/io/dapr/workflows/task/history/HistoryPropagationScopeTest.java Tests propagation-scope conversion.
sdk-workflows/src/test/java/io/dapr/workflows/task/exception/WorkflowFailureDetailsTest.java Tests failure mappings.
sdk-workflows/src/test/java/io/dapr/workflows/task/exception/CompositeTaskFailedExceptionTest.java Tests composite failures.
sdk-workflows/src/test/java/io/dapr/workflows/task/DurableTaskGrpcWorkerStatefulHistoryTest.java Tests worker stateful history.
sdk-workflows/src/test/java/io/dapr/workflows/task/DurableTaskGrpcWorkerShutdownTest.java Tests worker shutdown.
sdk-workflows/src/test/java/io/dapr/workflows/task/DurableTaskGrpcWorkerReconnectTest.java Tests worker reconnects.
sdk-workflows/src/test/java/io/dapr/workflows/task/DurableTaskGrpcWorkerChannelBackoffTest.java Tests channel backoff.
sdk-workflows/src/test/java/io/dapr/workflows/task/DurableTaskGrpcClientTracingTest.java Tests client tracing.
sdk-workflows/src/test/java/io/dapr/workflows/task/DurableTaskGrpcClientTlsTest.java Updates TLS test packaging.
sdk-workflows/src/test/java/io/dapr/workflows/task/DurableTaskGrpcClientScheduleTest.java Tests scheduling.
sdk-workflows/src/test/java/io/dapr/workflows/task/DurableTaskGrpcClientRoutingTest.java Tests client routing.
sdk-workflows/src/test/java/io/dapr/workflows/task/client/PurgeInstanceCriteriaTest.java Tests purge criteria.
sdk-workflows/src/test/java/io/dapr/workflows/task/client/DurableTaskGrpcClientBuilderTest.java Tests client builder behavior.
sdk-workflows/src/test/java/io/dapr/workflows/task/client/DurableTaskClientTest.java Tests unified client APIs.
sdk-workflows/src/test/java/io/dapr/workflows/task/ActivityHistoryPropagationTest.java Tests activity history propagation.
sdk-workflows/src/test/java/io/dapr/workflows/runtime/WorkflowVersionWrapperTest.java Tests version wrapping.
sdk-workflows/src/test/java/io/dapr/workflows/runtime/WorkflowRuntimeTest.java Tests runtime lifecycle.
sdk-workflows/src/test/java/io/dapr/workflows/runtime/WorkflowRuntimeStatusConverterTest.java Removes obsolete converter coverage.
sdk-workflows/src/test/java/io/dapr/workflows/runtime/WorkflowRuntimeBuilderTest.java Tests runtime builder behavior.
sdk-workflows/src/test/java/io/dapr/workflows/runtime/WorkflowInstanceWrapperTest.java Tests instance wrapping.
sdk-workflows/src/test/java/io/dapr/workflows/runtime/WorkflowClassWrapperTest.java Tests workflow-class wrapping.
sdk-workflows/src/test/java/io/dapr/workflows/runtime/WorkflowActivityInstanceWrapperTest.java Tests activity-instance wrapping.
sdk-workflows/src/test/java/io/dapr/workflows/runtime/WorkflowActivityClassWrapperTest.java Tests activity-class wrapping.
sdk-workflows/src/test/java/io/dapr/workflows/runtime/DefaultWorkflowActivityContextTest.java Tests activity context behavior.
sdk-workflows/src/test/java/io/dapr/workflows/client/WorkflowStateTest.java Tests workflow state.
sdk-workflows/src/test/java/io/dapr/workflows/client/WorkflowRuntimeStatusTest.java Tests runtime status mapping.
sdk-workflows/src/test/java/io/dapr/workflows/client/WorkflowInstanceStatusTest.java Removes obsolete status coverage.
sdk-workflows/src/test/java/io/dapr/workflows/client/DaprWorkflowClientTest.java Tests unified client behavior.
sdk-workflows/src/main/java/io/dapr/workflows/WorkflowTaskRetryPolicy.java Adds retry-policy validation and defaults.
sdk-workflows/src/main/java/io/dapr/workflows/WorkflowTaskRetryContext.java Unifies retry context types.
sdk-workflows/src/main/java/io/dapr/workflows/WorkflowTaskOptions.java Unifies task options and builders.
sdk-workflows/src/main/java/io/dapr/workflows/WorkflowActivityContext.java Uses unified history types.
sdk-workflows/src/main/java/io/dapr/workflows/WorkflowActivity.java Updates workflow API documentation.
sdk-workflows/src/main/java/io/dapr/workflows/task/worker/DurableTaskGrpcWorkerBuilder.java Relocates the worker builder.
sdk-workflows/src/main/java/io/dapr/workflows/task/worker/DurableTaskGrpcWorker.java Relocates the worker implementation.
sdk-workflows/src/main/java/io/dapr/workflows/task/TaskOrchestration.java Relocates orchestration APIs.
sdk-workflows/src/main/java/io/dapr/workflows/task/TaskActivityFactory.java Relocates activity factories.
sdk-workflows/src/main/java/io/dapr/workflows/task/TaskActivityContext.java Relocates activity context.
sdk-workflows/src/main/java/io/dapr/workflows/task/TaskActivity.java Relocates activity APIs.
sdk-workflows/src/main/java/io/dapr/workflows/task/Task.java Relocates the task abstraction.
sdk-workflows/src/main/java/io/dapr/workflows/task/serialization/JacksonDataConverter.java Relocates the Jackson converter.
sdk-workflows/src/main/java/io/dapr/workflows/task/serialization/DataConverter.java Relocates the serialization API.
sdk-workflows/src/main/java/io/dapr/workflows/task/OrchestratorFunction.java Uses unified orchestration types.
sdk-workflows/src/main/java/io/dapr/workflows/task/orchestration/TaskOrchestrationFactory.java Relocates orchestration factories.
sdk-workflows/src/main/java/io/dapr/workflows/task/orchestration/TaskOrchestrationFactories.java Relocates the orchestration registry.
sdk-workflows/src/main/java/io/dapr/workflows/task/interruption/OrchestratorBlockedException.java Relocates orchestration interruption.
sdk-workflows/src/main/java/io/dapr/workflows/task/interruption/ContinueAsNewInterruption.java Relocates continuation interruption.
sdk-workflows/src/main/java/io/dapr/workflows/task/internal/WorkflowHistoryCache.java Relocates the history cache.
sdk-workflows/src/main/java/io/dapr/workflows/task/internal/UuidGenerator.java Relocates UUID utilities.
sdk-workflows/src/main/java/io/dapr/workflows/task/internal/TaskOrchestratorResult.java Relocates orchestration results.
sdk-workflows/src/main/java/io/dapr/workflows/task/internal/TaskActivityExecutor.java Relocates activity execution.
sdk-workflows/src/main/java/io/dapr/workflows/task/internal/runner/OrchestratorRunner.java Relocates orchestrator execution.
sdk-workflows/src/main/java/io/dapr/workflows/task/internal/runner/OrchestrationRunner.java Relocates orchestration execution.
sdk-workflows/src/main/java/io/dapr/workflows/task/internal/runner/DurableRunner.java Relocates durable execution.
sdk-workflows/src/main/java/io/dapr/workflows/task/internal/runner/ActivityRunner.java Relocates activity execution.
sdk-workflows/src/main/java/io/dapr/workflows/task/internal/Helpers.java Adds unified internal helpers.
sdk-workflows/src/main/java/io/dapr/workflows/task/history/WorkflowResult.java Relocates workflow history results.
sdk-workflows/src/main/java/io/dapr/workflows/task/history/PropagatedHistoryException.java Relocates history exceptions.
sdk-workflows/src/main/java/io/dapr/workflows/task/history/PropagatedHistory.java Relocates propagated history.
sdk-workflows/src/main/java/io/dapr/workflows/task/history/HistoryPropagationScope.java Relocates propagation scopes.
sdk-workflows/src/main/java/io/dapr/workflows/task/history/ChildWorkflowResult.java Relocates child-workflow results.
sdk-workflows/src/main/java/io/dapr/workflows/task/history/ActivityResult.java Relocates activity results.
sdk-workflows/src/main/java/io/dapr/workflows/task/exception/WorkflowFailureDetails.java Adds failure compatibility mappings.
sdk-workflows/src/main/java/io/dapr/workflows/task/exception/VersionNotRegisteredException.java Relocates version exceptions.
sdk-workflows/src/main/java/io/dapr/workflows/task/exception/TaskFailedException.java Relocates task failures.
sdk-workflows/src/main/java/io/dapr/workflows/task/exception/TaskCanceledException.java Relocates task cancellations.
sdk-workflows/src/main/java/io/dapr/workflows/task/exception/NonDeterministicOrchestratorException.java Relocates nondeterminism exceptions.
sdk-workflows/src/main/java/io/dapr/workflows/task/exception/CompositeTaskFailedException.java Relocates composite failures.
sdk-workflows/src/main/java/io/dapr/workflows/task/client/PurgeResult.java Relocates purge results.
sdk-workflows/src/main/java/io/dapr/workflows/task/client/PurgeInstanceCriteria.java Uses unified workflow statuses.
sdk-workflows/src/main/java/io/dapr/workflows/task/client/OrchestrationMetadata.java Uses unified status and failure types.
sdk-workflows/src/main/java/io/dapr/workflows/task/client/NewOrchestrationInstanceOptions.java Relocates orchestration options.
sdk-workflows/src/main/java/io/dapr/workflows/task/client/DurableTaskGrpcClient.java Relocates the gRPC client.
sdk-workflows/src/main/java/io/dapr/workflows/task/client/DurableTaskClient.java Relocates the client API.
sdk-workflows/src/main/java/io/dapr/workflows/runtime/WorkflowVersionWrapper.java Uses unified orchestration factories.
sdk-workflows/src/main/java/io/dapr/workflows/runtime/WorkflowRuntimeStatusConverter.java Removes the obsolete converter.
sdk-workflows/src/main/java/io/dapr/workflows/runtime/WorkflowRuntimeBuilder.java Preserves caller-owned executors.
sdk-workflows/src/main/java/io/dapr/workflows/runtime/WorkflowRuntime.java Tracks executor ownership.
sdk-workflows/src/main/java/io/dapr/workflows/runtime/WorkflowInstanceWrapper.java Removes orchestration adapters.
sdk-workflows/src/main/java/io/dapr/workflows/runtime/WorkflowClassWrapper.java Removes orchestration adapters.
sdk-workflows/src/main/java/io/dapr/workflows/runtime/WorkflowActivityInstanceWrapper.java Uses unified activity types.
sdk-workflows/src/main/java/io/dapr/workflows/runtime/WorkflowActivityClassWrapper.java Uses unified activity types.
sdk-workflows/src/main/java/io/dapr/workflows/runtime/DefaultWorkflowState.java Removes state adapters.
sdk-workflows/src/main/java/io/dapr/workflows/runtime/DefaultWorkflowInstanceStatus.java Removes the deprecated adapter.
sdk-workflows/src/main/java/io/dapr/workflows/runtime/DefaultWorkflowFailureDetails.java Removes the failure adapter.
sdk-workflows/src/main/java/io/dapr/workflows/runtime/DefaultWorkflowActivityContext.java Uses unified activity types.
sdk-workflows/src/main/java/io/dapr/workflows/client/WorkflowState.java Uses unified failure details.
sdk-workflows/src/main/java/io/dapr/workflows/client/WorkflowRuntimeStatus.java Integrates runtime status conversion.
sdk-workflows/src/main/java/io/dapr/workflows/client/WorkflowInstanceStatus.java Removes the deprecated status API.
sdk-workflows/src/main/java/io/dapr/workflows/client/WorkflowFailureDetails.java Removes the duplicate interface.
sdk-workflows/src/main/java/io/dapr/workflows/client/DaprWorkflowClient.java Removes deprecated client methods.
sdk-tests/src/test/java/io/dapr/it/testcontainers/workflows/TestExecutionKeysWorkflow.java Updates task imports.
sdk-bom/pom.xml Removes durable-task dependency management.
README.md Updates module and migration documentation.
pom.xml Removes the standalone module and updates integration modules.
examples/src/main/java/io/dapr/examples/workflows/historypropagation/multiapp/App2AuditActivity.java Updates history imports.
examples/src/main/java/io/dapr/examples/workflows/historypropagation/multiapp/App1Workflow.java Updates propagation imports.
examples/src/main/java/io/dapr/examples/workflows/historypropagation/DemoFraudCheckChildWorkflow.java Updates history imports.
examples/src/main/java/io/dapr/examples/workflows/historypropagation/AuditActivity.java Updates history imports.
examples/src/main/java/io/dapr/examples/workflows/faninout/DemoFanInOutWorkflow.java Updates task imports.
examples/src/main/java/io/dapr/examples/workflows/compensation/BookTripWorkflow.java Updates exception imports.
examples/src/main/java/io/dapr/examples/workflows/childworkflow/DemoChildWorkflow.java Updates interruption imports.
examples/src/main/java/io/dapr/examples/unittesting/DaprWorkflowExampleTest.java Updates task and exception imports.
durabletask-client/src/main/java/io/dapr/durabletask/TaskOptions.java Removes duplicate task options.
durabletask-client/src/main/java/io/dapr/durabletask/RetryPolicy.java Removes duplicate retry policy.
durabletask-client/src/main/java/io/dapr/durabletask/RetryHandler.java Removes duplicate retry handling.
durabletask-client/src/main/java/io/dapr/durabletask/RetryContext.java Removes duplicate retry context.
durabletask-client/src/main/java/io/dapr/durabletask/OrchestrationRuntimeStatus.java Removes duplicate status types.
durabletask-client/src/main/java/io/dapr/durabletask/Helpers.java Removes duplicate helpers.
dapr-spring/dapr-spring-boot-observation/src/test/java/io/dapr/spring/observation/client/ObservationDaprWorkflowClientTest.java Removes deprecated-client coverage.
dapr-spring/dapr-spring-boot-observation/src/main/java/io/dapr/spring/observation/client/ObservationDaprWorkflowClient.java Removes deprecated-method documentation.
.github/workflows/build.yml Updates workflow build and integration jobs.
Review details

Suppressed comments (2)

sdk-workflows/src/main/java/io/dapr/workflows/WorkflowTaskRetryPolicy.java:96

  • maxNumberOfAttempts includes the initial invocation, not just retries. This wording contradicts the retry-policy semantics and can lead callers to configure the wrong number of attempts; describe it as the maximum number of task invocation attempts, including the initial attempt.
    sdk-workflows/src/main/java/io/dapr/workflows/task/Task.java:48
  • Making the backing CompletableFuture public lets workflow code complete or fail a returned task directly (for example, ctx.callActivity(...).future.complete(...)). CompletableTask.await() returns immediately whenever this future is done, so this bypasses durable history and can produce a value the sidecar never recorded. Keep the future and construction mechanism out of the supported API and expose only an internal completion/access path.
  • Files reviewed: 156/156 changed files
  • Comments generated: 3
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread pom.xml
Copilot AI review requested due to automatic review settings September 18, 2026 08:54
…ecision

WorkflowRuntimeStatus.fromProtobuf threw NullPointerException on a null
status, where the converter it replaced threw IllegalArgumentException with a
message and had a test for it. Restores that behaviour.

WorkflowRuntimeBuilder decides whether the runtime owns the executor it was
built with, but the lifecycle tests passed that flag straight to the
WorkflowRuntime constructor, so nothing pinned the decision itself. Adds two
tests that go through build(), one per outcome; inverting the decision fails
both.

Signed-off-by: Javier Aliaga <javier@diagrid.io>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

Three unresolved findings remain, including one critical replay-safety issue and two moderate validation issues.

Review details

Suppressed comments (3)

Previously missed (1) — in code that hasn't changed since the last review.

sdk-workflows/src/main/java/io/dapr/workflows/WorkflowTaskRetryPolicy.java:64

  • This validation accepts Double.NaN (and positive infinity), because both values make backoffCoefficient < 1.0 false. A policy built with NaN reaches Helpers.powExact, produces NaN, and is then cast to a zero millisecond delay, so retries run immediately; positive infinity fails only during retry execution. Reject non-finite coefficients at this validation boundary, and apply the same check in Builder.setBackoffCoefficient so both construction paths behave consistently.

sdk-workflows/src/main/java/io/dapr/workflows/client/WorkflowRuntimeStatus.java:121

  • This newly public conversion method switches directly on status, so toProtobuf(null) throws NullPointerException even though the paired fromProtobuf method normalizes null to IllegalArgumentException. Add the same explicit null check here so callers get a predictable documented argument error.
    sdk-workflows/src/main/java/io/dapr/workflows/task/Task.java:48
  • Making the backing CompletableFuture public exposes a mutable completion primitive to workflow code. A caller can invoke complete, completeExceptionally, or cancel on a returned task, making await/allOf observe a result without the corresponding durable history event and breaking replay semantics. Keep this state encapsulated and provide an internal-only access path for the executor instead of widening the public API.
  • Files reviewed: 156/156 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

Copilot AI review requested due to automatic review settings September 18, 2026 09:03
@codecov

codecov Bot commented Sep 18, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 93.08511% with 13 lines in your changes missing coverage. Please review.
✅ Project coverage is 78.67%. Comparing base (ca8df1f) to head (158920c).

Files with missing lines Patch % Lines
...flows/task/internal/TaskOrchestrationExecutor.java 66.66% 4 Missing and 2 partials ⚠️
...c/main/java/io/dapr/workflows/WorkflowContext.java 84.61% 2 Missing ⚠️
...o/dapr/workflows/client/WorkflowRuntimeStatus.java 92.30% 1 Missing and 1 partial ⚠️
.../java/io/dapr/workflows/task/internal/Helpers.java 92.00% 1 Missing and 1 partial ⚠️
...va/io/dapr/workflows/WorkflowTaskRetryContext.java 66.66% 1 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff              @@
##             master    #1800      +/-   ##
============================================
+ Coverage     78.41%   78.67%   +0.25%     
- Complexity     2492     2936     +444     
============================================
  Files           253      285      +32     
  Lines          7561     9725    +2164     
  Branches        785     1091     +306     
============================================
+ Hits           5929     7651    +1722     
- Misses         1269     1585     +316     
- Partials        363      489     +126     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

One or more issues must be addressed before approval.

Get a fresh assessment by requesting another Copilot review.

Review details

Suppressed comments (3)

sdk-workflows/src/main/java/io/dapr/workflows/WorkflowTaskRetryPolicy.java:58

  • These constructor checks make the previously accepted WorkflowTaskRetryPolicy.newBuilder().build() fail immediately; the updated WorkflowTaskOptionsTest had to add both required values to its formerly empty policies. That is an additional upgrade-time compatibility change beyond the documented ZERO defaults, so either preserve the old empty-builder behavior or document the required fields and new exception in MIGRATION.md.
    sdk-workflows/src/main/java/io/dapr/workflows/client/WorkflowRuntimeStatus.java:121
  • toProtobuf is now a public mapper, but a null argument reaches the switch and throws NullPointerException, while the method contract says invalid statuses throw IllegalArgumentException and fromProtobuf already handles null that way. Add the same explicit null check here so callers get the documented exception type.
    sdk-workflows/src/main/java/io/dapr/workflows/task/Task.java:48
  • Making the backing CompletableFuture and constructor public exposes a mutable completion source that workflow callers can complete, fail, or cancel directly, bypassing durable history and allowing an orchestration task to report a result the sidecar never produced. Keep this state inaccessible to application code and provide an internal/package-boundary bridge for the executor instead.
  • Files reviewed: 156/156 changed files
  • Comments generated: 1
  • Review effort level: Lite

Comment thread .github/workflows/build.yml

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants