Skip to content

Commit d60805f

Browse files
authored
Merge branch 'master' into actor_ttl
2 parents 5760b84 + be5530f commit d60805f

20 files changed

+410
-174
lines changed

sdk-workflows/src/main/java/io/dapr/workflows/Workflow.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
import com.microsoft.durabletask.interruption.ContinueAsNewInterruption;
1717
import com.microsoft.durabletask.interruption.OrchestratorBlockedException;
1818
import io.dapr.workflows.saga.SagaCompensationException;
19-
import io.dapr.workflows.saga.SagaOption;
19+
import io.dapr.workflows.saga.SagaOptions;
2020

2121
/**
2222
* Common interface for workflow implementations.
@@ -74,7 +74,7 @@ default boolean isSagaEnabled() {
7474
*
7575
* @return saga configuration
7676
*/
77-
default SagaOption getSagaOption() {
77+
default SagaOptions getSagaOption() {
7878
// by default, saga is disabled
7979
return null;
8080
}

sdk-workflows/src/main/java/io/dapr/workflows/WorkflowActivityContext.java

+2
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,9 @@
1414
package io.dapr.workflows;
1515

1616
public interface WorkflowActivityContext {
17+
1718
String getName();
1819

1920
<T> T getInput(Class<T> targetType);
21+
2022
}

sdk-workflows/src/main/java/io/dapr/workflows/WorkflowContext.java

+19-20
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
import com.microsoft.durabletask.Task;
1818
import com.microsoft.durabletask.TaskCanceledException;
1919
import com.microsoft.durabletask.TaskFailedException;
20-
import com.microsoft.durabletask.TaskOptions;
2120
import io.dapr.workflows.saga.SagaContext;
2221
import org.slf4j.Logger;
2322

@@ -153,24 +152,24 @@ default <V> Task<V> waitForExternalEvent(String name, Class<V> dataType) {
153152
* @param <V> the expected type of the activity output
154153
* @return a new {@link Task} that completes when the activity completes or fails
155154
*/
156-
<V> Task<V> callActivity(String name, Object input, TaskOptions options, Class<V> returnType);
155+
<V> Task<V> callActivity(String name, Object input, WorkflowTaskOptions options, Class<V> returnType);
157156

158157
/**
159158
* Asynchronously invokes an activity by name and returns a new {@link Task} that completes when the activity
160-
* completes. See {@link #callActivity(String, Object, TaskOptions, Class)} for a complete description.
159+
* completes. See {@link #callActivity(String, Object, WorkflowTaskOptions, Class)} for a complete description.
161160
*
162161
* @param name the name of the activity to call
163162
* @return a new {@link Task} that completes when the activity completes or fails
164-
* @see #callActivity(String, Object, TaskOptions, Class)
163+
* @see #callActivity(String, Object, WorkflowTaskOptions, Class)
165164
*/
166165
default Task<Void> callActivity(String name) {
167166
return this.callActivity(name, null, null, Void.class);
168167
}
169168

170169
/**
171170
* Asynchronously invokes an activity by name and with the specified input value and returns a new {@link Task}
172-
* that completes when the activity completes. See {@link #callActivity(String, Object, TaskOptions, Class)} for a
173-
* complete description.
171+
* that completes when the activity completes.
172+
* See {@link #callActivity(String, Object, WorkflowTaskOptions, Class)} for a complete description.
174173
*
175174
* @param name the name of the activity to call
176175
* @param input the serializable input to pass to the activity
@@ -183,7 +182,7 @@ default Task<Void> callActivity(String name, Object input) {
183182
/**
184183
* Asynchronously invokes an activity by name and returns a new {@link Task} that completes when the activity
185184
* completes. If the activity completes successfully, the returned {@code Task}'s value will be the activity's
186-
* output. See {@link #callActivity(String, Object, TaskOptions, Class)} for a complete description.
185+
* output. See {@link #callActivity(String, Object, WorkflowTaskOptions, Class)} for a complete description.
187186
*
188187
* @param name the name of the activity to call
189188
* @param returnType the expected class type of the activity output
@@ -197,8 +196,8 @@ default <V> Task<V> callActivity(String name, Class<V> returnType) {
197196
/**
198197
* Asynchronously invokes an activity by name and with the specified input value and returns a new {@link Task}
199198
* that completes when the activity completes.If the activity completes successfully, the returned {@code Task}'s
200-
* value will be the activity's output. See {@link #callActivity(String, Object, TaskOptions, Class)} for a
201-
* complete description.
199+
* value will be the activity's output.
200+
* See {@link #callActivity(String, Object, WorkflowTaskOptions, Class)} for a complete description.
202201
*
203202
* @param name the name of the activity to call
204203
* @param input the serializable input to pass to the activity
@@ -212,15 +211,15 @@ default <V> Task<V> callActivity(String name, Object input, Class<V> returnType)
212211

213212
/**
214213
* Asynchronously invokes an activity by name and with the specified input value and returns a new {@link Task}
215-
* that completes when the activity completes. See {@link #callActivity(String, Object, TaskOptions, Class)} for a
216-
* complete description.
214+
* that completes when the activity completes.
215+
* See {@link #callActivity(String, Object, WorkflowTaskOptions, Class)} for a complete description.
217216
*
218217
* @param name the name of the activity to call
219218
* @param input the serializable input to pass to the activity
220219
* @param options additional options that control the execution and processing of the activity
221220
* @return a new {@link Task} that completes when the activity completes or fails
222221
*/
223-
default Task<Void> callActivity(String name, Object input, TaskOptions options) {
222+
default Task<Void> callActivity(String name, Object input, WorkflowTaskOptions options) {
224223
return this.callActivity(name, input, options, Void.class);
225224
}
226225

@@ -367,11 +366,11 @@ default Task<Void> createTimer(ZonedDateTime zonedDateTime) {
367366
* Asynchronously invokes another workflow as a child-workflow and returns a {@link Task} that completes
368367
* when the child-workflow completes.
369368
*
370-
* <p>See {@link #callChildWorkflow(String, Object, String, TaskOptions, Class)} for a full description.
369+
* <p>See {@link #callChildWorkflow(String, Object, String, WorkflowTaskOptions, Class)} for a full description.
371370
*
372371
* @param name the name of the workflow to invoke
373372
* @return a new {@link Task} that completes when the child-workflow completes or fails
374-
* @see #callChildWorkflow(String, Object, String, TaskOptions, Class)
373+
* @see #callChildWorkflow(String, Object, String, WorkflowTaskOptions, Class)
375374
*/
376375
default Task<Void> callChildWorkflow(String name) {
377376
return this.callChildWorkflow(name, null);
@@ -381,7 +380,7 @@ default Task<Void> callChildWorkflow(String name) {
381380
* Asynchronously invokes another workflow as a child-workflow and returns a {@link Task} that completes
382381
* when the child-workflow completes.
383382
*
384-
* <p>See {@link #callChildWorkflow(String, Object, String, TaskOptions, Class)} for a full description.
383+
* <p>See {@link #callChildWorkflow(String, Object, String, WorkflowTaskOptions, Class)} for a full description.
385384
*
386385
* @param name the name of the workflow to invoke
387386
* @param input the serializable input to send to the child-workflow
@@ -395,7 +394,7 @@ default Task<Void> callChildWorkflow(String name, Object input) {
395394
* Asynchronously invokes another workflow as a child-workflow and returns a {@link Task} that completes
396395
* when the child-workflow completes.
397396
*
398-
* <p>See {@link #callChildWorkflow(String, Object, String, TaskOptions, Class)} for a full description.
397+
* <p>See {@link #callChildWorkflow(String, Object, String, WorkflowTaskOptions, Class)} for a full description.
399398
*
400399
* @param name the name of the workflow to invoke
401400
* @param input the serializable input to send to the child-workflow
@@ -411,7 +410,7 @@ default <V> Task<V> callChildWorkflow(String name, Object input, Class<V> return
411410
* Asynchronously invokes another workflow as a child-workflow and returns a {@link Task} that completes
412411
* when the child-workflow completes.
413412
*
414-
* <p>See {@link #callChildWorkflow(String, Object, String, TaskOptions, Class)} for a full description.
413+
* <p>See {@link #callChildWorkflow(String, Object, String, WorkflowTaskOptions, Class)} for a full description.
415414
*
416415
* @param name the name of the workflow to invoke
417416
* @param input the serializable input to send to the child-workflow
@@ -428,15 +427,15 @@ default <V> Task<V> callChildWorkflow(String name, Object input, String instance
428427
* Asynchronously invokes another workflow as a child-workflow and returns a {@link Task} that completes
429428
* when the child-workflow completes.
430429
*
431-
* <p>See {@link #callChildWorkflow(String, Object, String, TaskOptions, Class)} for a full description.
430+
* <p>See {@link #callChildWorkflow(String, Object, String, WorkflowTaskOptions, Class)} for a full description.
432431
*
433432
* @param name the name of the workflow to invoke
434433
* @param input the serializable input to send to the child-workflow
435434
* @param instanceID the unique ID of the child-workflow
436435
* @param options additional options that control the execution and processing of the activity
437436
* @return a new {@link Task} that completes when the child-workflow completes or fails
438437
*/
439-
default Task<Void> callChildWorkflow(String name, Object input, String instanceID, TaskOptions options) {
438+
default Task<Void> callChildWorkflow(String name, Object input, String instanceID, WorkflowTaskOptions options) {
440439
return this.callChildWorkflow(name, input, instanceID, options, Void.class);
441440
}
442441

@@ -478,7 +477,7 @@ default Task<Void> callChildWorkflow(String name, Object input, String instanceI
478477
<V> Task<V> callChildWorkflow(String name,
479478
@Nullable Object input,
480479
@Nullable String instanceID,
481-
@Nullable TaskOptions options,
480+
@Nullable WorkflowTaskOptions options,
482481
Class<V> returnType);
483482

484483
/**

sdk-workflows/src/main/java/io/dapr/workflows/WorkflowStub.java

+2
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,7 @@
1515

1616
@FunctionalInterface
1717
public interface WorkflowStub {
18+
1819
void run(WorkflowContext ctx);
20+
1921
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/*
2+
* Copyright 2025 The Dapr Authors
3+
* Licensed under the Apache License, Version 2.0 (the "License");
4+
* you may not use this file except in compliance with the License.
5+
* You may obtain a copy of the License at
6+
* http://www.apache.org/licenses/LICENSE-2.0
7+
* Unless required by applicable law or agreed to in writing, software
8+
* distributed under the License is distributed on an "AS IS" BASIS,
9+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10+
* See the License for the specific language governing permissions and
11+
limitations under the License.
12+
*/
13+
14+
package io.dapr.workflows;
15+
16+
public class WorkflowTaskOptions {
17+
18+
private final WorkflowTaskRetryPolicy retryPolicy;
19+
20+
public WorkflowTaskOptions(WorkflowTaskRetryPolicy retryPolicy) {
21+
this.retryPolicy = retryPolicy;
22+
}
23+
24+
public WorkflowTaskRetryPolicy getRetryPolicy() {
25+
return retryPolicy;
26+
}
27+
28+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
/*
2+
* Copyright 2025 The Dapr Authors
3+
* Licensed under the Apache License, Version 2.0 (the "License");
4+
* you may not use this file except in compliance with the License.
5+
* You may obtain a copy of the License at
6+
* http://www.apache.org/licenses/LICENSE-2.0
7+
* Unless required by applicable law or agreed to in writing, software
8+
* distributed under the License is distributed on an "AS IS" BASIS,
9+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10+
* See the License for the specific language governing permissions and
11+
limitations under the License.
12+
*/
13+
14+
package io.dapr.workflows;
15+
16+
import javax.annotation.Nullable;
17+
18+
import java.time.Duration;
19+
20+
public final class WorkflowTaskRetryPolicy {
21+
22+
private final Integer maxNumberOfAttempts;
23+
private final Duration firstRetryInterval;
24+
private final Double backoffCoefficient;
25+
private final Duration maxRetryInterval;
26+
private final Duration retryTimeout;
27+
28+
/**
29+
* Constructor for WorkflowTaskRetryPolicy.
30+
* @param maxNumberOfAttempts Maximum number of attempts to retry the workflow.
31+
* @param firstRetryInterval Interval to wait before the first retry.
32+
* @param backoffCoefficient Coefficient to increase the retry interval.
33+
* @param maxRetryInterval Maximum interval to wait between retries.
34+
* @param retryTimeout Timeout for the whole retry process.
35+
*/
36+
public WorkflowTaskRetryPolicy(
37+
Integer maxNumberOfAttempts,
38+
Duration firstRetryInterval,
39+
Double backoffCoefficient,
40+
Duration maxRetryInterval,
41+
Duration retryTimeout
42+
) {
43+
this.maxNumberOfAttempts = maxNumberOfAttempts;
44+
this.firstRetryInterval = firstRetryInterval;
45+
this.backoffCoefficient = backoffCoefficient;
46+
this.maxRetryInterval = maxRetryInterval;
47+
this.retryTimeout = retryTimeout;
48+
}
49+
50+
public int getMaxNumberOfAttempts() {
51+
return maxNumberOfAttempts;
52+
}
53+
54+
public Duration getFirstRetryInterval() {
55+
return firstRetryInterval;
56+
}
57+
58+
public double getBackoffCoefficient() {
59+
return backoffCoefficient;
60+
}
61+
62+
public Duration getMaxRetryInterval() {
63+
return maxRetryInterval;
64+
}
65+
66+
public Duration getRetryTimeout() {
67+
return retryTimeout;
68+
}
69+
70+
public static Builder newBuilder() {
71+
return new Builder();
72+
}
73+
74+
public static class Builder {
75+
76+
private Integer maxNumberOfAttempts;
77+
private Duration firstRetryInterval;
78+
private Double backoffCoefficient = 1.0;
79+
private Duration maxRetryInterval;
80+
private Duration retryTimeout;
81+
82+
private Builder() {
83+
}
84+
85+
/**
86+
* Build the WorkflowTaskRetryPolicy.
87+
* @return WorkflowTaskRetryPolicy
88+
*/
89+
public WorkflowTaskRetryPolicy build() {
90+
return new WorkflowTaskRetryPolicy(
91+
this.maxNumberOfAttempts,
92+
this.firstRetryInterval,
93+
this.backoffCoefficient,
94+
this.maxRetryInterval,
95+
this.retryTimeout
96+
);
97+
}
98+
99+
/**
100+
* Set the maximum number of attempts to retry the workflow.
101+
* @param maxNumberOfAttempts Maximum number
102+
* @return This builder
103+
*/
104+
public Builder setMaxNumberOfAttempts(int maxNumberOfAttempts) {
105+
if (maxNumberOfAttempts <= 0) {
106+
throw new IllegalArgumentException("The value for maxNumberOfAttempts must be greater than zero.");
107+
}
108+
109+
this.maxNumberOfAttempts = maxNumberOfAttempts;
110+
111+
return this;
112+
}
113+
114+
/**
115+
* Set the interval to wait before the first retry.
116+
* @param firstRetryInterval Interval
117+
* @return This builder
118+
*/
119+
public Builder setFirstRetryInterval(Duration firstRetryInterval) {
120+
if (firstRetryInterval == null) {
121+
throw new IllegalArgumentException("firstRetryInterval cannot be null.");
122+
}
123+
if (firstRetryInterval.isZero() || firstRetryInterval.isNegative()) {
124+
throw new IllegalArgumentException("The value for firstRetryInterval must be greater than zero.");
125+
}
126+
127+
this.firstRetryInterval = firstRetryInterval;
128+
129+
return this;
130+
}
131+
132+
/**
133+
* Set the backoff coefficient.
134+
* @param backoffCoefficient Double value
135+
* @return This builder
136+
*/
137+
public Builder setBackoffCoefficient(double backoffCoefficient) {
138+
if (backoffCoefficient < 1.0) {
139+
throw new IllegalArgumentException("The value for backoffCoefficient must be greater or equal to 1.0.");
140+
}
141+
142+
this.backoffCoefficient = backoffCoefficient;
143+
144+
return this;
145+
}
146+
147+
/**
148+
* Set the maximum interval to wait between retries.
149+
* @param maxRetryInterval Maximum interval
150+
* @return This builder
151+
*/
152+
public Builder setMaxRetryInterval(@Nullable Duration maxRetryInterval) {
153+
if (maxRetryInterval != null && maxRetryInterval.compareTo(this.firstRetryInterval) < 0) {
154+
throw new IllegalArgumentException(
155+
"The value for maxRetryInterval must be greater than or equal to the value for firstRetryInterval.");
156+
}
157+
158+
this.maxRetryInterval = maxRetryInterval;
159+
160+
return this;
161+
}
162+
163+
/**
164+
* Set the maximum retry timeout.
165+
* @param retryTimeout Maximum retry timeout
166+
* @return This builder
167+
*/
168+
public Builder setRetryTimeout(Duration retryTimeout) {
169+
if (retryTimeout != null && retryTimeout.compareTo(this.firstRetryInterval) < 0) {
170+
throw new IllegalArgumentException(
171+
"The value for retryTimeout must be greater than or equal to the value for firstRetryInterval.");
172+
}
173+
174+
this.retryTimeout = retryTimeout;
175+
176+
return this;
177+
}
178+
}
179+
180+
}

0 commit comments

Comments
 (0)