Skip to content

Commit a654861

Browse files
authored
Add shutdown API support (dapr#530)
* Add shutdown API support dapr#529 * Utilize POST instead of GET for shutdown API
1 parent bdf8e86 commit a654861

File tree

9 files changed

+140
-20
lines changed

9 files changed

+140
-20
lines changed

.github/workflows/build.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ jobs:
2626
DAPR_RUNTIME_VER: 1.1.0-rc.1
2727
DAPR_INSTALL_URL: https://raw.githubusercontent.com/dapr/cli/3dacfb672d55f1436c249057aaebbe597e1066f3/install/install.sh
2828
DAPR_CLI_REF:
29-
DAPR_REF:
29+
DAPR_REF: 266eb0b5d300c576c3360c7f0582d795579ee457
3030
OSSRH_USER_TOKEN: ${{ secrets.OSSRH_USER_TOKEN }}
3131
OSSRH_PWD_TOKEN: ${{ secrets.OSSRH_PWD_TOKEN }}
3232
GPG_KEY: ${{ secrets.GPG_KEY }}

sdk-tests/src/test/java/io/dapr/it/DaprRun.java

Lines changed: 23 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -68,31 +68,16 @@ public void start() throws InterruptedException, IOException {
6868
this.stop();
6969
// Wait for the previous run to kill the prior process.
7070
long timeLeft = this.maxWaitMilliseconds - (System.currentTimeMillis() - start);
71-
callWithRetry(() -> {
72-
System.out.println("Checking if previous run for Dapr application has stopped ...");
73-
try {
74-
this.listCommand.run();
75-
throw new RuntimeException("Previous run for app has not stopped yet!");
76-
} catch (IllegalStateException e) {
77-
// Success because we the list command did not find the app id.
78-
} catch (Exception e) {
79-
throw new RuntimeException(e);
80-
}
81-
}, timeLeft);
71+
System.out.println("Checking if previous run for Dapr application has stopped ...");
72+
checkRunState(timeLeft, false);
8273

8374
System.out.println("Starting dapr application ...");
8475
this.startCommand.run();
8576
this.started.set(true);
8677

8778
timeLeft = this.maxWaitMilliseconds - (System.currentTimeMillis() - start);
88-
callWithRetry(() -> {
89-
System.out.println("Checking if Dapr application has started ...");
90-
try {
91-
this.listCommand.run();
92-
} catch (Exception e) {
93-
throw new RuntimeException(e);
94-
}
95-
}, timeLeft);
79+
System.out.println("Checking if Dapr application has started ...");
80+
checkRunState(timeLeft, true);
9681

9782
if (this.ports.getAppPort() != null) {
9883
timeLeft = this.maxWaitMilliseconds - (System.currentTimeMillis() - start);
@@ -180,6 +165,25 @@ public String getAppName() {
180165
return appName;
181166
}
182167

168+
public void checkRunState(long timeout, boolean shouldBeRunning) throws InterruptedException {
169+
callWithRetry(() -> {
170+
try {
171+
this.listCommand.run();
172+
173+
if (!shouldBeRunning) {
174+
throw new RuntimeException("Previous run for app has not stopped yet!");
175+
}
176+
} catch (IllegalStateException e) {
177+
// Bad case if the app is supposed to be running.
178+
if (shouldBeRunning) {
179+
throw e;
180+
}
181+
} catch (Exception e) {
182+
throw new RuntimeException(e);
183+
}
184+
}, timeout);
185+
}
186+
183187
private static String buildDaprCommand(
184188
String appName, Class serviceClass, DaprPorts ports, DaprApiProtocol protocol, DaprApiProtocol appProtocol) {
185189
StringBuilder stringBuilder =
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
package io.dapr.it.api;
2+
3+
import io.dapr.client.DaprClient;
4+
import io.dapr.client.DaprClientBuilder;
5+
import io.dapr.it.BaseIT;
6+
import io.dapr.it.DaprRun;
7+
import io.dapr.it.actors.ActorReminderRecoveryIT;
8+
import org.junit.Test;
9+
import org.junit.runner.RunWith;
10+
import org.junit.runners.Parameterized;
11+
import org.slf4j.Logger;
12+
import org.slf4j.LoggerFactory;
13+
14+
import java.util.Arrays;
15+
import java.util.Collection;
16+
17+
@RunWith(Parameterized.class)
18+
public class ApiIT extends BaseIT {
19+
20+
private static final Logger logger = LoggerFactory.getLogger(ApiIT.class);
21+
private static final int DEFAULT_TIMEOUT = 60000;
22+
23+
/**
24+
* Parameters for this test.
25+
* Param #1: useGrpc.
26+
*
27+
* @return Collection of parameter tuples.
28+
*/
29+
@Parameterized.Parameters
30+
public static Collection<Object[]> data() {
31+
return Arrays.asList(new Object[][]{{false}, {true}});
32+
}
33+
34+
@Parameterized.Parameter
35+
public boolean useGrpc;
36+
37+
@Test
38+
public void testShutdownAPI() throws Exception {
39+
DaprRun run = startDaprApp(this.getClass().getSimpleName(), DEFAULT_TIMEOUT);
40+
41+
if (this.useGrpc) {
42+
run.switchToGRPC();
43+
} else {
44+
run.switchToHTTP();
45+
}
46+
47+
try (DaprClient client = new DaprClientBuilder().build()) {
48+
logger.info("Sending shutdown request.");
49+
client.shutdown().block();
50+
51+
logger.info("Ensuring dapr has stopped.");
52+
run.checkRunState(DEFAULT_TIMEOUT, false);
53+
}
54+
}
55+
}

sdk/src/main/java/io/dapr/client/DaprClient.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -550,4 +550,11 @@ Mono<Void> executeStateTransaction(String storeName,
550550
* @return Key-value pairs for the secret.
551551
*/
552552
Mono<Map<String, Map<String, String>>> getBulkSecret(GetBulkSecretRequest request);
553+
554+
/**
555+
* Gracefully shutdown the dapr runtime.
556+
*
557+
* @return a Mono plan of type Void.
558+
*/
559+
Mono<Void> shutdown();
553560
}

sdk/src/main/java/io/dapr/client/DaprClientGrpc.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -659,6 +659,17 @@ public void close() throws Exception {
659659
}
660660
}
661661

662+
/**
663+
* {@inheritDoc}
664+
*/
665+
@Override
666+
public Mono<Void> shutdown() {
667+
return Mono.subscriberContext().flatMap(
668+
context -> this.<Empty>createMono(
669+
it -> intercept(context, asyncStub).shutdown(Empty.getDefaultInstance(), it))
670+
).then();
671+
}
672+
662673
/**
663674
* Populates GRPC client with interceptors.
664675
*

sdk/src/main/java/io/dapr/client/DaprClientHttp.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -644,6 +644,18 @@ public void close() {
644644
client.close();
645645
}
646646

647+
/**
648+
* {@inheritDoc}
649+
*/
650+
@Override
651+
public Mono<Void> shutdown() {
652+
String[] pathSegments = new String[]{ DaprHttp.API_VERSION, "shutdown" };
653+
return Mono.subscriberContext().flatMap(
654+
context -> client.invokeApi(DaprHttp.HttpMethods.POST.name(), pathSegments,
655+
null, null, context))
656+
.then();
657+
}
658+
647659
/**
648660
* Converts metadata map into Query params.
649661
* @param metadata metadata map

sdk/src/main/java/io/dapr/client/DaprClientProxy.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -499,4 +499,12 @@ public void close() throws Exception {
499499
methodInvocationOverrideClient.close();
500500
}
501501
}
502+
503+
/**
504+
* {@inheritDoc}
505+
*/
506+
@Override
507+
public Mono<Void> shutdown() {
508+
return client.shutdown();
509+
}
502510
}

sdk/src/test/java/io/dapr/client/DaprClientGrpcTest.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2142,6 +2142,19 @@ public void stateOptionsConcurrencyValuesHaveValidGrpcEnumMappings() {
21422142
}
21432143
}
21442144

2145+
@Test
2146+
public void shutdownTest() {
2147+
doAnswer((Answer<Void>) invocation -> {
2148+
StreamObserver<Empty> observer = (StreamObserver<Empty>) invocation.getArguments()[1];
2149+
observer.onNext(Empty.getDefaultInstance());
2150+
observer.onCompleted();
2151+
return null;
2152+
}).when(daprStub).shutdown(any(Empty.class), any());
2153+
2154+
Mono<Void> result = client.shutdown();
2155+
result.block();
2156+
}
2157+
21452158
private <T> DaprProtos.GetStateResponse buildFutureGetStateEnvelop(T value, String etag) throws IOException {
21462159
return buildGetStateResponse(value, etag);
21472160
}

sdk/src/test/java/io/dapr/client/DaprClientHttpTest.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1267,6 +1267,16 @@ public void close() throws Exception {
12671267
daprClientHttp.close();
12681268
}
12691269

1270+
@Test
1271+
public void shutdown() throws Exception {
1272+
mockInterceptor.addRule()
1273+
.post("http://127.0.0.1:3000/v1.0/shutdown")
1274+
.respond(204);
1275+
1276+
final Mono<Void> mono = daprClientHttp.shutdown();
1277+
assertNull(mono.block());
1278+
}
1279+
12701280
private static final class BodyMatcher implements Matcher {
12711281

12721282
private final String expected;

0 commit comments

Comments
 (0)