Skip to content

Commit 0a4499a

Browse files
authored
Merge branch 'main' into kaibocai/CVE-fix-1
2 parents d227de3 + 0ef8a3a commit 0a4499a

File tree

33 files changed

+1620
-233
lines changed

33 files changed

+1620
-233
lines changed

.github/workflows/build-validation.yml

+42-1
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ jobs:
9696
continue-on-error: true
9797

9898
- name: Setup azure functions runtime
99-
run: samples-azure-functions/e2e-test-setup.ps1 -DockerfilePath samples-azure-functions/Dockerfile
99+
run: endtoendtests/e2e-test-setup.ps1 -DockerfilePath endtoendtests/Dockerfile
100100
shell: pwsh
101101

102102
- name: End to End Tests with Gradle
@@ -109,3 +109,44 @@ jobs:
109109
with:
110110
name: Integration test report
111111
path: client/build/reports/tests/endToEndTest
112+
113+
functions-sample-tests:
114+
115+
needs: build
116+
runs-on: ubuntu-latest
117+
118+
steps:
119+
- uses: actions/checkout@v2
120+
with:
121+
submodules: true
122+
123+
- name: Set up JDK 8
124+
uses: actions/setup-java@v2
125+
with:
126+
java-version: '8'
127+
distribution: 'temurin'
128+
129+
- name: Setup Gradle
130+
uses: gradle/gradle-build-action@v2
131+
132+
- name: Publish to local
133+
run: ./gradlew publishToMavenLocal -x sign
134+
135+
- name: Build azure functions sample
136+
run: ./gradlew azureFunctionsPackage
137+
continue-on-error: true
138+
139+
- name: Setup azure functions runtime
140+
run: samples-azure-functions/e2e-test-setup.ps1 -DockerfilePath samples-azure-functions/Dockerfile
141+
shell: pwsh
142+
143+
- name: Sample Tests with Gradle
144+
uses: gradle/gradle-build-action@v2
145+
with:
146+
arguments: sampleTest
147+
148+
- name: Archive test report
149+
uses: actions/upload-artifact@v2
150+
with:
151+
name: Integration test report
152+
path: client/build/reports/tests/endToEndTest

CHANGELOG.md

+3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
## placeholder
22
* Remove unused dependency `protobuf-java` to resolve CVEs ([#180](https://github.com/microsoft/durabletask-java/pull/180))
3+
* Fix infinite loop when use continueasnew after wait external event ([#183](https://github.com/microsoft/durabletask-java/pull/183))
4+
* Fix the issue "Deserialize Exception got swallowed when use anyOf with external event." ([#185](https://github.com/microsoft/durabletask-java/pull/185))
5+
36

47
## v1.5.0
58
* Fix exception type issue when using `RetriableTask` in fan in/out pattern ([#174](https://github.com/microsoft/durabletask-java/pull/174))

azurefunctions/build.gradle

+4-3
Original file line numberDiff line numberDiff line change
@@ -73,9 +73,10 @@ publishing {
7373
}
7474
}
7575

76-
signing {
77-
sign publishing.publications.mavenJava
78-
}
76+
// TODO: manual signing temporarily disabled, in favor of 1ES signing utils
77+
//signing {
78+
// sign publishing.publications.mavenJava
79+
//}
7980

8081
java {
8182
withSourcesJar()

azurefunctions/src/main/java/com/microsoft/durabletask/azurefunctions/internal/middleware/OrchestrationMiddleware.java

+20
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,10 @@
99
import com.microsoft.azure.functions.internal.spi.middleware.Middleware;
1010
import com.microsoft.azure.functions.internal.spi.middleware.MiddlewareChain;
1111
import com.microsoft.azure.functions.internal.spi.middleware.MiddlewareContext;
12+
import com.microsoft.durabletask.CompositeTaskFailedException;
13+
import com.microsoft.durabletask.DataConverter;
1214
import com.microsoft.durabletask.OrchestrationRunner;
15+
import com.microsoft.durabletask.TaskFailedException;
1316
import com.microsoft.durabletask.interruption.ContinueAsNewInterruption;
1417
import com.microsoft.durabletask.interruption.OrchestratorBlockedException;
1518

@@ -48,6 +51,23 @@ public void invoke(MiddlewareContext context, MiddlewareChain chain) throws Exce
4851
if (cause instanceof ContinueAsNewInterruption) {
4952
throw (ContinueAsNewInterruption) cause;
5053
}
54+
// Below types of exception are raised by the client sdk, they data should be correctly pass back to
55+
// durable function host. We need to cast them to the correct type so later when build the FailureDetails
56+
// the correct exception data can be saved and pass back.
57+
if (cause instanceof TaskFailedException) {
58+
throw (TaskFailedException) cause;
59+
}
60+
61+
if (cause instanceof CompositeTaskFailedException) {
62+
throw (CompositeTaskFailedException) cause;
63+
}
64+
65+
if (cause instanceof DataConverter.DataConverterException) {
66+
throw (DataConverter.DataConverterException) cause;
67+
}
68+
// e will be InvocationTargetException as using reflection, so we wrap it into a RuntimeException, so it
69+
// won't change the current OrchestratorFunction API. We cannot throw the cause which is a Throwable, it
70+
// requires update on OrchestratorFunction API.
5171
throw new RuntimeException("Unexpected failure in the task execution", e);
5272
}
5373
});

client/build.gradle

+4-3
Original file line numberDiff line numberDiff line change
@@ -146,9 +146,10 @@ publishing {
146146
}
147147
}
148148

149-
signing {
150-
sign publishing.publications.mavenJava
151-
}
149+
// TODO: manual signing temporarily disabled, in favor of 1ES signing
150+
//signing {
151+
// sign publishing.publications.mavenJava
152+
//}
152153

153154
java {
154155
withSourcesJar()

client/src/main/java/com/microsoft/durabletask/TaskOrchestrationExecutor.java

+39-17
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
import java.util.function.Function;
2323
import java.util.function.IntFunction;
2424
import java.util.logging.Logger;
25-
import java.util.stream.Collectors;
2625

2726
final class TaskOrchestrationExecutor {
2827

@@ -511,10 +510,13 @@ private void handleTaskCompleted(HistoryEvent e) {
511510
rawResult != null ? rawResult : "(null)"));
512511

513512
}
514-
515-
Object result = this.dataConverter.deserialize(rawResult, record.getDataType());
516513
CompletableTask task = record.getTask();
517-
task.complete(result);
514+
try {
515+
Object result = this.dataConverter.deserialize(rawResult, record.getDataType());
516+
task.complete(result);
517+
} catch (Exception ex) {
518+
task.completeExceptionally(ex);
519+
}
518520
}
519521

520522
private void handleTaskFailed(HistoryEvent e) {
@@ -558,11 +560,15 @@ private void handleEventRaised(HistoryEvent e) {
558560
this.outstandingEvents.remove(eventName);
559561
}
560562
String rawResult = eventRaised.getInput().getValue();
561-
Object result = this.dataConverter.deserialize(
562-
rawResult,
563-
matchingTaskRecord.getDataType());
564563
CompletableTask task = matchingTaskRecord.getTask();
565-
task.complete(result);
564+
try {
565+
Object result = this.dataConverter.deserialize(
566+
rawResult,
567+
matchingTaskRecord.getDataType());
568+
task.complete(result);
569+
} catch (Exception ex) {
570+
task.completeExceptionally(ex);
571+
}
566572
}
567573

568574
private void handleEventWhileSuspended (HistoryEvent historyEvent){
@@ -694,10 +700,13 @@ private void handleSubOrchestrationCompleted(HistoryEvent e) {
694700
rawResult != null ? rawResult : "(null)"));
695701

696702
}
697-
698-
Object result = this.dataConverter.deserialize(rawResult, record.getDataType());
699703
CompletableTask task = record.getTask();
700-
task.complete(result);
704+
try {
705+
Object result = this.dataConverter.deserialize(rawResult, record.getDataType());
706+
task.complete(result);
707+
} catch (Exception ex) {
708+
task.completeExceptionally(ex);
709+
}
701710
}
702711

703712
private void handleSubOrchestrationFailed(HistoryEvent e){
@@ -787,12 +796,17 @@ private void addCarryoverEvents(CompleteOrchestrationAction.Builder builder) {
787796
// We don't check the event in the pass event list to avoid duplicated events.
788797
Set<HistoryEvent> externalEvents = new HashSet<>(this.unprocessedEvents);
789798
List<HistoryEvent> newEvents = this.historyEventPlayer.getNewEvents();
799+
int currentHistoryIndex = this.historyEventPlayer.getCurrentHistoryIndex();
800+
801+
// Only add events that haven't been processed to the carryOverEvents
802+
// currentHistoryIndex will point to the first unprocessed event
803+
for (int i = currentHistoryIndex; i < newEvents.size(); i++) {
804+
HistoryEvent historyEvent = newEvents.get(i);
805+
if (historyEvent.getEventTypeCase() == HistoryEvent.EventTypeCase.EVENTRAISED) {
806+
externalEvents.add(historyEvent);
807+
}
808+
}
790809

791-
Set<HistoryEvent> filteredEvents = newEvents.stream()
792-
.filter(e -> e.getEventTypeCase() == HistoryEvent.EventTypeCase.EVENTRAISED)
793-
.collect(Collectors.toSet());
794-
795-
externalEvents.addAll(filteredEvents);
796810
externalEvents.forEach(builder::addCarryoverEvents);
797811
}
798812

@@ -946,7 +960,11 @@ public boolean moveNext() {
946960
}
947961

948962
List<HistoryEvent> getNewEvents() {
949-
return newEvents;
963+
return this.newEvents;
964+
}
965+
966+
int getCurrentHistoryIndex() {
967+
return this.currentHistoryIndex;
950968
}
951969
}
952970

@@ -1322,6 +1340,10 @@ protected void handleException(Throwable e) {
13221340
throw (CompositeTaskFailedException)e;
13231341
}
13241342

1343+
if (e instanceof DataConverter.DataConverterException) {
1344+
throw (DataConverter.DataConverterException)e;
1345+
}
1346+
13251347
throw new RuntimeException("Unexpected failure in the task execution", e);
13261348
}
13271349

client/src/test/java/com/microsoft/durabletask/IntegrationTests.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -545,7 +545,7 @@ void restartOrchestrationThrowsException() {
545545

546546
}
547547

548-
@Test
548+
// @Test
549549
void suspendResumeOrchestration() throws TimeoutException, InterruptedException {
550550
final String orchestratorName = "suspend";
551551
final String eventName = "MyEvent";

endtoendtests/Dockerfile

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
FROM mcr.microsoft.com/azure-functions/java:4-java11
2+
3+
COPY endtoendtests/build/azure-functions/azure-functions-sample/ /home/site/wwwroot/
4+
ENV AzureWebJobsScriptRoot=/home/site/wwwroot \
5+
AzureFunctionsJobHost__Logging__Console__IsEnabled=true

endtoendtests/build.gradle

+56
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
plugins {
2+
id "com.microsoft.azure.azurefunctions" version "1.11.1"
3+
}
4+
apply plugin: 'java'
5+
apply plugin: "com.microsoft.azure.azurefunctions"
6+
7+
group 'com.durabletask.endtoend'
8+
version '0.0.0-SNAPSHOT'
9+
10+
repositories {
11+
mavenLocal()
12+
maven {
13+
url "https://oss.sonatype.org/content/repositories/snapshots/"
14+
}
15+
mavenCentral()
16+
}
17+
18+
dependencies {
19+
implementation project(':client')
20+
implementation project(':azurefunctions')
21+
22+
implementation 'com.microsoft.azure.functions:azure-functions-java-library:3.0.0'
23+
testImplementation 'org.junit.jupiter:junit-jupiter:5.6.2'
24+
testImplementation 'io.rest-assured:rest-assured:5.3.0'
25+
testImplementation 'io.rest-assured:json-path:5.3.0'
26+
27+
}
28+
29+
sourceCompatibility = '1.8'
30+
targetCompatibility = '1.8'
31+
32+
compileJava.options.encoding = 'UTF-8'
33+
34+
task endToEndTest(type: Test) {
35+
useJUnitPlatform {
36+
includeTags 'e2e'
37+
}
38+
dependsOn build
39+
testLogging.showStandardStreams = true
40+
}
41+
42+
43+
azurefunctions {
44+
resourceGroup = 'java-functions-group'
45+
appName = 'azure-functions-sample'
46+
pricingTier = 'Consumption'
47+
region = 'westus'
48+
runtime {
49+
os = 'Windows'
50+
javaVersion = 'Java 8'
51+
}
52+
auth {
53+
type = 'azure_cli'
54+
}
55+
localDebug = "transport=dt_socket,server=y,suspend=n,address=5005"
56+
}

endtoendtests/e2e-test-setup.ps1

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# Installing PowerShell: https://docs.microsoft.com/powershell/scripting/install/installing-powershell
2+
3+
param(
4+
[Parameter(Mandatory=$true)]
5+
[string]$DockerfilePath,
6+
[string]$ImageName="dfapp",
7+
[string]$ContainerName="app",
8+
[switch]$NoSetup=$false,
9+
[switch]$NoValidation=$false,
10+
[string]$AzuriteVersion="3.20.1",
11+
[int]$Sleep=30
12+
)
13+
14+
$ErrorActionPreference = "Stop"
15+
16+
if ($NoSetup -eq $false) {
17+
# Build the docker image first, since that's the most critical step
18+
Write-Host "Building sample app Docker container from '$DockerfilePath'..." -ForegroundColor Yellow
19+
docker build -f $DockerfilePath -t $ImageName --progress plain .
20+
21+
# Next, download and start the Azurite emulator Docker image
22+
Write-Host "Pulling down the mcr.microsoft.com/azure-storage/azurite:$AzuriteVersion image..." -ForegroundColor Yellow
23+
docker pull "mcr.microsoft.com/azure-storage/azurite:${AzuriteVersion}"
24+
25+
Write-Host "Starting Azurite storage emulator using default ports..." -ForegroundColor Yellow
26+
docker run --name 'azurite' -p 10000:10000 -p 10001:10001 -p 10002:10002 -d "mcr.microsoft.com/azure-storage/azurite:${AzuriteVersion}"
27+
28+
# Finally, start up the smoke test container, which will connect to the Azurite container
29+
docker run --name $ContainerName -p 8080:80 -it --add-host=host.docker.internal:host-gateway -d `
30+
--env 'AzureWebJobsStorage=UseDevelopmentStorage=true;DevelopmentStorageProxyUri=http://host.docker.internal' `
31+
--env 'WEBSITE_HOSTNAME=localhost:8080' `
32+
$ImageName
33+
}
34+
35+
if ($sleep -gt 0) {
36+
# The container needs a bit more time before it can start receiving requests
37+
Write-Host "Sleeping for $Sleep seconds to let the container finish initializing..." -ForegroundColor Yellow
38+
Start-Sleep -Seconds $Sleep
39+
}
40+
41+
# Check to see what containers are running
42+
docker ps

endtoendtests/host.json

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
{
2+
"version": "2.0",
3+
"logging": {
4+
"logLevel": {
5+
"DurableTask.AzureStorage": "Warning",
6+
"DurableTask.Core": "Warning"
7+
},
8+
"applicationInsights": {
9+
"samplingSettings": {
10+
"isEnabled": false
11+
}
12+
}
13+
},
14+
"extensions": {
15+
"durableTask": {
16+
"hubName": "DFJavaSmokeTest"
17+
}
18+
},
19+
"extensionBundle": {
20+
"id": "Microsoft.Azure.Functions.ExtensionBundle",
21+
"version": "[4.*, 5.0.0)"
22+
}
23+
}

endtoendtests/local.settings.json

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"IsEncrypted": false,
3+
"Values": {
4+
"AzureWebJobsStorage": "UseDevelopmentStorage=true",
5+
"FUNCTIONS_WORKER_RUNTIME": "java"
6+
}
7+
}

0 commit comments

Comments
 (0)