Skip to content

Commit 1094f3f

Browse files
Бацура Сергей АлександровичБацура Сергей Александрович
Бацура Сергей Александрович
authored and
Бацура Сергей Александрович
committed
Feat(deadline) add deadline property for client
1 parent a18aeeb commit 1094f3f

File tree

6 files changed

+180
-1
lines changed

6 files changed

+180
-1
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
/*
2+
* Copyright (c) 2016-2024 The gRPC-Spring Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package net.devh.boot.grpc.client.autoconfigure;
18+
19+
import static java.util.Objects.requireNonNull;
20+
21+
import java.util.concurrent.TimeUnit;
22+
23+
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
24+
import org.springframework.context.annotation.Bean;
25+
import org.springframework.context.annotation.Configuration;
26+
27+
import io.grpc.stub.AbstractStub;
28+
import lombok.extern.slf4j.Slf4j;
29+
import net.devh.boot.grpc.client.config.GrpcChannelProperties;
30+
import net.devh.boot.grpc.client.config.GrpcChannelsProperties;
31+
import net.devh.boot.grpc.client.inject.StubTransformer;
32+
33+
/**
34+
* The deadline auto configuration for the client.
35+
*
36+
* <p>
37+
* You can disable this config by using:
38+
* </p>
39+
*
40+
* <pre>
41+
* <code>@ImportAutoConfiguration(exclude = GrpcClientDeadlineAutoConfiguration.class)</code>
42+
* </pre>
43+
*
44+
* @author Sergei Batsura ([email protected])
45+
*/
46+
@Slf4j
47+
@Configuration(proxyBeanMethods = false)
48+
@AutoConfigureBefore(GrpcClientAutoConfiguration.class)
49+
public class GrpcClientDeadlineAutoConfiguration {
50+
51+
/**
52+
* Creates a {@link StubTransformer} bean that will add the call credentials to the created stubs.
53+
*
54+
* @param props The properties for deadline configuration.
55+
* @return The StubTransformer bean that will add the deadline from properties.
56+
* @see AbstractStub#withDeadline(io.grpc.Deadline)
57+
*/
58+
@Bean
59+
StubTransformer deadlineStubTransformer(final GrpcChannelsProperties props) {
60+
requireNonNull(props, "properties");
61+
62+
return (name, stub) -> {
63+
GrpcChannelProperties channelProps = props.getChannel(name);
64+
if (channelProps != null && channelProps.getDeadline() != null) {
65+
return stub.withDeadlineAfter(channelProps.getDeadline().toMillis(), TimeUnit.MILLISECONDS);
66+
} else {
67+
return stub;
68+
}
69+
};
70+
}
71+
72+
}

grpc-client-spring-boot-starter/src/main/java/net/devh/boot/grpc/client/config/GrpcChannelProperties.java

+31
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,34 @@ public void setAddress(final String address) {
118118
this.address = address == null ? null : URI.create(address);
119119
}
120120

121+
// --------------------------------------------------
122+
// Target Deadline
123+
// --------------------------------------------------
124+
125+
private Duration deadline = null;
126+
127+
/**
128+
* Gets the connection deadline.
129+
*
130+
* @return The connection deadline or null
131+
* @see #setDeadline(Duration)
132+
*/
133+
public Duration getDeadline() {
134+
return this.deadline;
135+
}
136+
137+
/**
138+
* Set the deadline for the stub. If nothing is configured then the deadline will not be used by default. If zero
139+
* value is configured then the deadline will immediately.
140+
*
141+
* @param deadline The connection deadline or null.
142+
*
143+
* @see #setDeadline(Duration)
144+
*/
145+
public void setDeadline(Duration deadline) {
146+
this.deadline = deadline;
147+
}
148+
121149
// --------------------------------------------------
122150
// defaultLoadBalancingPolicy
123151
// --------------------------------------------------
@@ -477,6 +505,9 @@ public void copyDefaultsFrom(final GrpcChannelProperties config) {
477505
if (this == config) {
478506
return;
479507
}
508+
if (this.deadline == null) {
509+
this.deadline = config.deadline;
510+
}
480511
if (this.address == null) {
481512
this.address = config.address;
482513
}

grpc-client-spring-boot-starter/src/main/resources/META-INF/additional-spring-configuration-metadata.json

+6
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,12 @@
107107
"description": "Connection timeout at application startup. If set to a positive duration instructs a client to connect to GRPC-endpoint when GRPC stub is created.",
108108
"defaultValue": 0
109109
},
110+
{
111+
"name": "grpc.client.GLOBAL.deadline",
112+
"type": "java.time.Duration",
113+
"sourceType": "net.devh.boot.grpc.client.config.GrpcChannelProperties",
114+
"description": "A deadline is used to specify a point in time past which a client is unwilling to wait for a response from a server"
115+
},
110116
{
111117
"name": "grpc.client.GLOBAL.security.authority-override",
112118
"type": "java.lang.String",

grpc-client-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports

+1
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@ net.devh.boot.grpc.client.autoconfigure.GrpcClientHealthAutoConfiguration
44
net.devh.boot.grpc.client.autoconfigure.GrpcClientMicrometerTraceAutoConfiguration
55
net.devh.boot.grpc.client.autoconfigure.GrpcClientSecurityAutoConfiguration
66
net.devh.boot.grpc.client.autoconfigure.GrpcDiscoveryClientAutoConfiguration
7+
net.devh.boot.grpc.client.autoconfigure.GrpcClientDeadlineAutoConfiguration

tests/src/test/java/net/devh/boot/grpc/test/config/BaseAutoConfiguration.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import org.springframework.context.annotation.Configuration;
2121

2222
import net.devh.boot.grpc.client.autoconfigure.GrpcClientAutoConfiguration;
23+
import net.devh.boot.grpc.client.autoconfigure.GrpcClientDeadlineAutoConfiguration;
2324
import net.devh.boot.grpc.common.autoconfigure.GrpcCommonCodecAutoConfiguration;
2425
import net.devh.boot.grpc.server.autoconfigure.GrpcServerAutoConfiguration;
2526
import net.devh.boot.grpc.server.autoconfigure.GrpcServerFactoryAutoConfiguration;
@@ -28,7 +29,7 @@
2829
@Configuration
2930
@ImportAutoConfiguration({GrpcCommonCodecAutoConfiguration.class, GrpcServerAutoConfiguration.class,
3031
GrpcServerFactoryAutoConfiguration.class, GrpcServerSecurityAutoConfiguration.class,
31-
GrpcClientAutoConfiguration.class})
32+
GrpcClientAutoConfiguration.class, GrpcClientDeadlineAutoConfiguration.class})
3233
public class BaseAutoConfiguration {
3334

3435
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
/*
2+
* Copyright (c) 2016-2024 The gRPC-Spring Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package net.devh.boot.grpc.test.setup;
18+
19+
import static io.grpc.Status.DEADLINE_EXCEEDED;
20+
import static net.devh.boot.grpc.test.util.GrpcAssertions.assertStatus;
21+
import static org.junit.jupiter.api.Assertions.assertEquals;
22+
import static org.junit.jupiter.api.Assertions.assertNotNull;
23+
import static org.junit.jupiter.api.Assertions.assertThrows;
24+
25+
import java.util.concurrent.ExecutionException;
26+
27+
import org.junit.jupiter.api.Test;
28+
import org.springframework.boot.test.context.SpringBootTest;
29+
import org.springframework.test.annotation.DirtiesContext;
30+
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
31+
32+
import io.grpc.StatusRuntimeException;
33+
import io.grpc.internal.testing.StreamRecorder;
34+
import lombok.SneakyThrows;
35+
import lombok.extern.slf4j.Slf4j;
36+
import net.devh.boot.grpc.client.config.GrpcChannelProperties;
37+
import net.devh.boot.grpc.test.config.BaseAutoConfiguration;
38+
import net.devh.boot.grpc.test.config.ServiceConfiguration;
39+
import net.devh.boot.grpc.test.proto.SomeType;
40+
41+
/**
42+
* These tests check the property {@link GrpcChannelProperties#getDeadline()}.
43+
*/
44+
@Slf4j
45+
@SpringBootTest(properties = {
46+
"grpc.client.GLOBAL.address=localhost:9090",
47+
"grpc.client.GLOBAL.deadline=1s",
48+
"grpc.client.GLOBAL.negotiationType=PLAINTEXT",
49+
})
50+
@SpringJUnitConfig(classes = {ServiceConfiguration.class, BaseAutoConfiguration.class})
51+
@DirtiesContext
52+
public class DeadlineTests extends AbstractSimpleServerClientTest {
53+
54+
@Test
55+
@DirtiesContext
56+
@SneakyThrows
57+
void testServiceStubDeadlineEnabledAndUnsuccessful() {
58+
log.info("--- Starting test with unsuccessful call ---");
59+
final StreamRecorder<SomeType> streamRecorder = StreamRecorder.create();
60+
this.testServiceStub.echo(streamRecorder);
61+
assertThrows(ExecutionException.class, () -> streamRecorder.firstValue().get());
62+
assertNotNull(streamRecorder.getError());
63+
assertEquals(StatusRuntimeException.class, streamRecorder.getError().getClass());
64+
assertStatus(DEADLINE_EXCEEDED.getCode(), (StatusRuntimeException) streamRecorder.getError());
65+
log.info("--- Test completed --- ");
66+
}
67+
68+
}

0 commit comments

Comments
 (0)