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

feat!: unify the durable task client into dapr-sdk-workflows#1800
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 no longer ships as a separate artifact. Its classes move from io.dapr.durabletask.* to io.dapr.workflows.task.*. Twelve duplicated types are reduced to one copy each, which removes the adapter layer that sat between the two modules. Seven types are renamed. Four @Deprecated(forRemoval) methods on DaprWorkflowClient and the WorkflowInstanceStatus type are removed.

Two behaviour changes. The runtime now uses a virtual-thread-per-task executor on Java 21 and later; set dapr.workflows.virtual.threads.enabled to false to opt out. WorkflowRuntime no longer shuts down an executor supplied by the caller.

This is a breaking change for workflow code. MIGRATION.md has the type mapping, the removed API, and what happens to workflows that are already running during an 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

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>
The runtime defaults to a virtual-thread-per-task executor on Java 21+,
which existing deployments get without changing any code. That is the
right default — activities run user code and typically block on I/O — but
it is not right for everyone: activity code that holds a monitor across a
blocking call pins a carrier thread on Java 21 through 23.

Add dapr.workflows.virtual.threads.enabled (env
DAPR_WORKFLOWS_VIRTUAL_THREADS_ENABLED), default true, following the
existing workflow property convention. Setting it false keeps the cached
thread pool used on earlier runtimes. It only affects the executor the
runtime creates for itself, so it has no bearing on Java 17 through 20 or
on a runtime handed an executor via withExecutorService.

Document the opt-out in SUPPORT.md and MIGRATION.md, and correct a claim
in SUPPORT.md that spring.threads.virtual.enabled reaches the workflow
runtime: it switches Spring's own executors, but the Dapr
auto-configuration does not pass the application's task executor to
WorkflowRuntimeBuilder, so workflow execution is unaffected by it.

Signed-off-by: Javier Aliaga <javier@diagrid.io>
@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
…ronment

The workflow runtime resolves dapr.workflows.virtual.threads.enabled through
the SDK Properties, which consults only JVM system properties and environment
variables. Setting it in application.properties silently did nothing, because
the auto-configuration builds its property overrides from the connection
details alone.

The auto-configured WorkflowRuntimeBuilder now layers the Spring Environment
over those overrides, so the opt-out works like any other Spring property.
When the property is set nowhere no override is added and the SDK default
still applies.

spring.threads.virtual.enabled remains unrelated to the workflow runtime:
Spring's virtual-thread applicationTaskExecutor is a SimpleAsyncTaskExecutor,
which is not an ExecutorService and cannot be handed to withExecutorService
without an adapter. SUPPORT.md is corrected to say so, and to drop the advice
to define a custom builder bean, which is unnecessary now that virtual threads
are the default on Java 21.

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>
@codecov

codecov Bot commented Sep 2, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 70.26022% with 80 lines in your changes missing coverage. Please review.
✅ Project coverage is 70.91%. Comparing base (2edf16c) to head (b767341).
⚠️ Report is 1 commits behind head on master.

Files with missing lines Patch % Lines
.../java/io/dapr/workflows/task/internal/Helpers.java 20.00% 12 Missing and 8 partials ⚠️
...c/main/java/io/dapr/workflows/WorkflowContext.java 0.00% 13 Missing ⚠️
...lows/task/client/DurableTaskGrpcClientBuilder.java 33.33% 12 Missing ⚠️
...flows/task/internal/TaskOrchestrationExecutor.java 50.00% 5 Missing and 4 partials ⚠️
...apr/workflows/internal/DefaultExecutorService.java 38.46% 7 Missing and 1 partial ⚠️
sdk/src/main/java/io/dapr/config/Properties.java 93.44% 1 Missing and 3 partials ⚠️
...r/workflows/task/client/OrchestrationMetadata.java 0.00% 3 Missing ⚠️
...ava/io/dapr/workflows/WorkflowTaskRetryPolicy.java 90.00% 0 Missing and 2 partials ⚠️
...o/dapr/workflows/client/WorkflowRuntimeStatus.java 91.66% 1 Missing and 1 partial ⚠️
...dapr/workflows/runtime/WorkflowRuntimeBuilder.java 33.33% 0 Missing and 2 partials ⚠️
... and 5 more

❗ There is a different number of reports uploaded between BASE (2edf16c) and HEAD (b767341). Click for more details.

HEAD has 1 upload less than BASE
Flag BASE (2edf16c) HEAD (b767341)
2 1
Additional details and impacted files
@@             Coverage Diff              @@
##             master    #1800      +/-   ##
============================================
- Coverage     77.10%   70.91%   -6.20%     
- Complexity     2317     2490     +173     
============================================
  Files           245      277      +32     
  Lines          7186     9105    +1919     
  Branches        750     1012     +262     
============================================
+ Hits           5541     6457     +916     
- Misses         1284     2170     +886     
- Partials        361      478     +117     

☔ 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.

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.

1 participant