Skip to content

Commit 216be0c

Browse files
committed
merge in master
Signed-off-by: Cassandra Coyle <[email protected]>
2 parents 3302911 + 688b059 commit 216be0c

13 files changed

+200
-207
lines changed

.github/workflows/build-validation.yml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,9 +73,15 @@ jobs:
7373
if: env.UNIT_TEST_FAILED == 'true'
7474
run: exit 1
7575

76+
- name: Checkout Durable Task Sidecar
77+
uses: actions/checkout@v4
78+
with:
79+
repository: dapr/durabletask-go
80+
path: durabletask-sidecar
81+
7682
# TODO: Move the sidecar into a central image repository
7783
- name: Initialize Durable Task Sidecar
78-
run: docker run --name durabletask-sidecar -p 4001:4001 --env 'DURABLETASK_SIDECAR_LOGLEVEL=Debug' -d peterstone2019/durabletask-sidecar:latest start --backend Emulator
84+
run: docker run -d --name durabletask-sidecar -p 4001:4001 --rm -i $(docker build -q ./durabletask-sidecar)
7985

8086
- name: Display Durable Task Sidecar Logs
8187
run: nohup docker logs --since=0 durabletask-sidecar > durabletask-sidecar.log 2>&1 &

.github/workflows/release.yml

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,12 @@ jobs:
1515
timeout-minutes: 30
1616
env:
1717
JDK_VER: 11
18-
JRELEASER_GITHUB_TOKEN: $${{ secrets.GITHUB_TOKEN }}
18+
JRELEASER_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
1919
JRELEASER_GPG_PUBLIC_KEY: ${{ secrets.GPG_KEY }}
2020
JRELEASER_GPG_SECRET_KEY: ${{ secrets.GPG_PRIVATE_KEY }}
2121
JRELEASER_GPG_PASSPHRASE: ${{ secrets.GPG_PWD }}
2222
JRELEASER_NEXUS2_MAVEN_CENTRAL_USERNAME: dapr.io
23-
JRELEASER_NEXUS2_MAVEN_CENTRAL_TOKEN: ${{ secrets.OSSRH_USER_PASS }}
23+
JRELEASER_NEXUS2_MAVEN_CENTRAL_TOKEN: ${{ secrets.OSSRH_USER_PASS }}
2424
JRELEASER_DEPLOY_MAVEN_NEXUS2_USERNAME: ${{ secrets.OSSRH_USER_TOKEN }}
2525
JRELEASER_DEPLOY_MAVEN_NEXUS2_TOKEN: ${{ secrets.OSSRH_PWD_TOKEN }}
2626
steps:
@@ -86,4 +86,6 @@ jobs:
8686
run: ./gradlew publish --stacktrace
8787

8888
- name: Publish to ossrh
89-
run: ./gradlew jreleaserFullRelease --stacktrace
89+
run: |
90+
./gradlew jreleaserFullRelease --stacktrace
91+
curl -X POST https://ossrh-staging-api.central.sonatype.com/manual/upload/defaultRepository/io.dapr

client/build.gradle

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ plugins {
77
// id 'signing'
88
id 'com.github.spotbugs' version '5.2.1'
99
id 'org.jreleaser' version '1.18.0'
10+
id 'org.gradle.test-retry' version '1.4.1'
1011
}
1112

1213
group 'io.dapr'
@@ -39,6 +40,8 @@ dependencies {
3940

4041
testImplementation(platform('org.junit:junit-bom:5.7.2'))
4142
testImplementation('org.junit.jupiter:junit-jupiter')
43+
testRuntimeOnly('org.junit.platform:junit-platform-launcher')
44+
4245

4346
// Netty dependencies for TLS
4447
implementation "io.grpc:grpc-netty-shaded:${grpcVersion}"
@@ -123,6 +126,11 @@ test {
123126
// and require external dependencies.
124127
excludeTags "integration"
125128
}
129+
130+
retry {
131+
maxRetries = 2
132+
maxFailures = 5
133+
}
126134
}
127135

128136
// Unlike normal unit tests, some tests are considered "integration tests" and shouldn't be
@@ -138,6 +146,12 @@ task integrationTest(type: Test) {
138146
testLogging.showStandardStreams = true
139147

140148
ignoreFailures = false
149+
150+
// Add retry capability for flaky integration tests
151+
retry {
152+
maxRetries = 3
153+
maxFailures = 10
154+
}
141155
}
142156

143157
publishing {
@@ -248,12 +262,13 @@ jreleaser {
248262
armored = true
249263
verify = false
250264
}
265+
251266
deploy {
252267
maven {
253268
nexus2 {
254269
'maven-central' {
255270
active = 'ALWAYS'
256-
url = 'https://oss.sonatype.org/service/local'
271+
url = 'https://ossrh-staging-api.central.sonatype.com/service/local'
257272
closeRepository = true
258273
releaseRepository = true
259274
applyMavenCentralRules = true

client/src/main/java/io/dapr/durabletask/DurableTaskGrpcWorker.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,7 @@ public void startAndBlock() {
199199
output = taskActivityExecutor.execute(
200200
activityRequest.getName(),
201201
activityRequest.getInput().getValue(),
202+
activityRequest.getTaskExecutionId(),
202203
activityRequest.getTaskId());
203204
} catch (Throwable e) {
204205
failureDetails = TaskFailureDetails.newBuilder()

client/src/main/java/io/dapr/durabletask/DurableTaskGrpcWorkerBuilder.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,8 @@
66

77
import java.time.Duration;
88
import java.util.HashMap;
9-
import java.util.concurrent.Executor;
109
import java.util.concurrent.ExecutorService;
11-
import java.util.concurrent.Executors;
10+
1211

1312
/**
1413
* Builder object for constructing customized {@link DurableTaskGrpcWorker} instances.

client/src/main/java/io/dapr/durabletask/TaskActivityContext.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,17 @@ public interface TaskActivityContext {
2121
* @return the deserialized activity input value
2222
*/
2323
<T> T getInput(Class<T> targetType);
24+
25+
26+
/**
27+
* Gets the execution id of the current task activity.
28+
* @return the execution id of the current task activity
29+
*/
30+
String getTaskExecutionId();
31+
32+
/**
33+
* Gets the task id of the current task activity.
34+
* @return the task id of the current task activity
35+
*/
36+
int getTaskId();
2437
}

client/src/main/java/io/dapr/durabletask/TaskActivityExecutor.java

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ public TaskActivityExecutor(
1919
this.logger = logger;
2020
}
2121

22-
public String execute(String taskName, String input, int taskId) throws Throwable {
22+
public String execute(String taskName, String input, String taskExecutionId, int taskId) throws Throwable {
2323
TaskActivityFactory factory = this.activityFactories.get(taskName);
2424
if (factory == null) {
2525
throw new IllegalStateException(
@@ -32,7 +32,7 @@ public String execute(String taskName, String input, int taskId) throws Throwabl
3232
String.format("The task factory '%s' returned a null TaskActivity object.", taskName));
3333
}
3434

35-
TaskActivityContextImpl context = new TaskActivityContextImpl(taskName, input);
35+
TaskActivityContextImpl context = new TaskActivityContextImpl(taskName, input, taskExecutionId, taskId);
3636

3737
// Unhandled exceptions are allowed to escape
3838
Object output = activity.run(context);
@@ -46,12 +46,16 @@ public String execute(String taskName, String input, int taskId) throws Throwabl
4646
private class TaskActivityContextImpl implements TaskActivityContext {
4747
private final String name;
4848
private final String rawInput;
49+
private final String taskExecutionId;
50+
private final int taskId;
4951

5052
private final DataConverter dataConverter = TaskActivityExecutor.this.dataConverter;
5153

52-
public TaskActivityContextImpl(String activityName, String rawInput) {
54+
public TaskActivityContextImpl(String activityName, String rawInput, String taskExecutionId, int taskId) {
5355
this.name = activityName;
5456
this.rawInput = rawInput;
57+
this.taskExecutionId = taskExecutionId;
58+
this.taskId = taskId;
5559
}
5660

5761
@Override
@@ -67,5 +71,15 @@ public <T> T getInput(Class<T> targetType) {
6771

6872
return this.dataConverter.deserialize(this.rawInput, targetType);
6973
}
74+
75+
@Override
76+
public String getTaskExecutionId() {
77+
return this.taskExecutionId;
78+
}
79+
80+
@Override
81+
public int getTaskId() {
82+
return this.taskId;
83+
}
7084
}
7185
}

client/src/main/java/io/dapr/durabletask/TaskOrchestrationExecutor.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -275,7 +275,7 @@ public <V> Task<V> callActivity(
275275
}
276276

277277
String serializedInput = this.dataConverter.serialize(input);
278-
Builder scheduleTaskBuilder = ScheduleTaskAction.newBuilder().setName(name);
278+
Builder scheduleTaskBuilder = ScheduleTaskAction.newBuilder().setName(name).setTaskExecutionId(newUUID().toString());
279279
if (serializedInput != null) {
280280
scheduleTaskBuilder.setInput(StringValue.of(serializedInput));
281281
}

client/src/test/java/io/dapr/durabletask/ErrorHandlingIntegrationTests.java

Lines changed: 9 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,12 @@
77
import org.junit.jupiter.api.Test;
88
import org.junit.jupiter.params.ParameterizedTest;
99
import org.junit.jupiter.params.provider.ValueSource;
10-
import org.junit.jupiter.api.extension.ExtendWith;
1110

1211
import java.time.Duration;
1312
import java.util.concurrent.TimeoutException;
1413
import java.util.concurrent.atomic.AtomicBoolean;
1514
import java.util.concurrent.atomic.AtomicInteger;
1615

17-
import org.junit.jupiter.api.BeforeEach;
1816
import static org.junit.jupiter.api.Assertions.*;
1917

2018
/**
@@ -25,15 +23,8 @@
2523
* client operations and sends invocation instructions to the DurableTaskWorker).
2624
*/
2725
@Tag("integration")
28-
@ExtendWith(TestRetryExtension.class)
2926
public class ErrorHandlingIntegrationTests extends IntegrationTestBase {
30-
@BeforeEach
31-
private void startUp() {
32-
DurableTaskClient client = new DurableTaskGrpcClientBuilder().build();
33-
client.deleteTaskHub();
34-
}
35-
36-
@RetryingTest
27+
@Test
3728
void orchestratorException() throws TimeoutException {
3829
final String orchestratorName = "OrchestratorWithException";
3930
final String errorMessage = "Kah-BOOOOOM!!!";
@@ -59,7 +50,7 @@ void orchestratorException() throws TimeoutException {
5950
}
6051
}
6152

62-
@RetryingParameterizedTest
53+
@ParameterizedTest
6354
@ValueSource(booleans = {true, false})
6455
void activityException(boolean handleException) throws TimeoutException {
6556
final String orchestratorName = "OrchestratorWithActivityException";
@@ -111,7 +102,7 @@ void activityException(boolean handleException) throws TimeoutException {
111102
}
112103
}
113104

114-
@RetryingParameterizedTest
105+
@ParameterizedTest
115106
@ValueSource(ints = {1, 2, 10})
116107
public void retryActivityFailures(int maxNumberOfAttempts) throws TimeoutException {
117108
// There is one task for each activity call and one task between each retry
@@ -125,7 +116,7 @@ public void retryActivityFailures(int maxNumberOfAttempts) throws TimeoutExcepti
125116
});
126117
}
127118

128-
@RetryingParameterizedTest
119+
@ParameterizedTest
129120
@ValueSource(ints = {1, 2, 10})
130121
public void retryActivityFailuresWithCustomLogic(int maxNumberOfAttempts) throws TimeoutException {
131122
// This gets incremented every time the retry handler is invoked
@@ -142,7 +133,7 @@ public void retryActivityFailuresWithCustomLogic(int maxNumberOfAttempts) throws
142133
assertEquals(maxNumberOfAttempts, retryHandlerCalls.get());
143134
}
144135

145-
@RetryingParameterizedTest
136+
@ParameterizedTest
146137
@ValueSource(booleans = {true, false})
147138
void subOrchestrationException(boolean handleException) throws TimeoutException {
148139
final String orchestratorName = "OrchestrationWithBustedSubOrchestrator";
@@ -192,7 +183,7 @@ void subOrchestrationException(boolean handleException) throws TimeoutException
192183
}
193184
}
194185

195-
@RetryingParameterizedTest
186+
@ParameterizedTest
196187
@ValueSource(ints = {1, 2, 10})
197188
public void retrySubOrchestratorFailures(int maxNumberOfAttempts) throws TimeoutException {
198189
// There is one task for each sub-orchestrator call and one task between each retry
@@ -207,7 +198,7 @@ public void retrySubOrchestratorFailures(int maxNumberOfAttempts) throws Timeout
207198
});
208199
}
209200

210-
@RetryingParameterizedTest
201+
@ParameterizedTest
211202
@ValueSource(ints = {1, 2, 10})
212203
public void retrySubOrchestrationFailuresWithCustomLogic(int maxNumberOfAttempts) throws TimeoutException {
213204
// This gets incremented every time the retry handler is invoked
@@ -297,24 +288,8 @@ private FailureDetails retryOnFailuresCoreTest(
297288

298289
// Confirm the number of attempts
299290
assertEquals(maxNumberOfAttempts, actualAttemptCount.get());
300-
301-
// Make sure the surfaced exception is the last one. This is reflected in both the task ID and the
302-
// error message. Note that the final task ID depends on how many tasks get executed as part of the main
303-
// orchestration's definition. This includes any implicit timers created by a retry policy. Validating
304-
// the final task ID is useful to ensure that changes to retry policy implementations don't break backwards
305-
// compatibility due to an unexpected history change (this has happened before).
306-
String expectedExceptionMessage = "Error #" + maxNumberOfAttempts;
307-
int expectedTaskId = expectedTaskCount - 1; // Task IDs are zero-indexed
308-
String taskName = isActivityPath.get() ? "BustedActivity" : "BustedSubOrchestrator";
309-
String expectedMessage = String.format(
310-
"Task '%s' (#%d) failed with an unhandled exception: %s",
311-
taskName,
312-
expectedTaskId,
313-
expectedExceptionMessage);
314-
assertEquals(expectedMessage, details.getErrorMessage());
315-
assertEquals("io.dapr.durabletask.TaskFailedException", details.getErrorType());
316-
assertNotNull(details.getStackTrace());
291+
317292
return details;
318293
}
319294
}
320-
}
295+
}

0 commit comments

Comments
 (0)