Skip to content

Commit

Permalink
Feat(deadline) add deadline property for client
Browse files Browse the repository at this point in the history
  • Loading branch information
Бацура Сергей Александрович authored and Бацура Сергей Александрович committed Sep 3, 2024
1 parent a18aeeb commit a19dbef
Show file tree
Hide file tree
Showing 6 changed files with 193 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/*
* Copyright (c) 2016-2024 The gRPC-Spring Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package net.devh.boot.grpc.client.autoconfigure;

import static java.util.Objects.requireNonNull;

import java.util.concurrent.TimeUnit;

import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import io.grpc.stub.AbstractStub;
import lombok.extern.slf4j.Slf4j;
import net.devh.boot.grpc.client.config.GrpcChannelProperties;
import net.devh.boot.grpc.client.config.GrpcChannelsProperties;
import net.devh.boot.grpc.client.inject.StubTransformer;

/**
* The deadline auto configuration for the client.
*
* <p>
* You can disable this config by using:
* </p>
*
* <pre>
* <code>@ImportAutoConfiguration(exclude = GrpcClientDeadlineAutoConfiguration.class)</code>
* </pre>
*
* @author Sergei Batsura ([email protected])
*/
@Slf4j
@Configuration(proxyBeanMethods = false)
@AutoConfigureBefore(GrpcClientAutoConfiguration.class)
public class GrpcClientDeadlineAutoConfiguration {

/**
* Creates a {@link StubTransformer} bean that will add the call credentials to the created stubs.
*
* @param props The properties for deadline configuration.
* @return The StubTransformer bean that will add the deadline from properties.
* @see AbstractStub#withDeadline(io.grpc.Deadline)
*/
@Bean
StubTransformer deadlineStubTransformer(final GrpcChannelsProperties props) {
requireNonNull(props, "properties");

return (name, stub) -> {
GrpcChannelProperties channelProps = props.getChannel(name);
if (channelProps != null && channelProps.getDeadline() != null) {
return stub.withDeadlineAfter(channelProps.getDeadline().toMillis(), TimeUnit.MILLISECONDS);
} else {
return stub;
}
};
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,34 @@ public void setAddress(final String address) {
this.address = address == null ? null : URI.create(address);
}

// --------------------------------------------------
// Target Deadline
// --------------------------------------------------

private Duration deadline = null;

/**
* Gets the connection deadline.
*
* @return The connection deadline or null
* @see #setDeadline(Duration)
*/
public Duration getDeadline() {
return this.deadline;
}

/**
* Set the deadline for the stub. If nothing is configured then the deadline will not be used by default. If zero
* value is configured then the deadline will immediately.
*
* @param deadline The connection deadline or null.
*
* @see #setDeadline(Duration)
*/
public void setDeadline(Duration deadline) {
this.deadline = deadline;
}

// --------------------------------------------------
// defaultLoadBalancingPolicy
// --------------------------------------------------
Expand Down Expand Up @@ -480,6 +508,9 @@ public void copyDefaultsFrom(final GrpcChannelProperties config) {
if (this.address == null) {
this.address = config.address;
}
if (this.deadline == null) {
this.deadline = config.deadline;
}
if (this.defaultLoadBalancingPolicy == null) {
this.defaultLoadBalancingPolicy = config.defaultLoadBalancingPolicy;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,12 @@
"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.",
"defaultValue": 0
},
{
"name": "grpc.client.GLOBAL.deadline",
"type": "java.time.Duration",
"sourceType": "net.devh.boot.grpc.client.config.GrpcChannelProperties",
"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"
},
{
"name": "grpc.client.GLOBAL.security.authority-override",
"type": "java.lang.String",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ net.devh.boot.grpc.client.autoconfigure.GrpcClientHealthAutoConfiguration
net.devh.boot.grpc.client.autoconfigure.GrpcClientMicrometerTraceAutoConfiguration
net.devh.boot.grpc.client.autoconfigure.GrpcClientSecurityAutoConfiguration
net.devh.boot.grpc.client.autoconfigure.GrpcDiscoveryClientAutoConfiguration
net.devh.boot.grpc.client.autoconfigure.GrpcClientDeadlineAutoConfiguration
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import org.springframework.context.annotation.Configuration;

import net.devh.boot.grpc.client.autoconfigure.GrpcClientAutoConfiguration;
import net.devh.boot.grpc.client.autoconfigure.GrpcClientDeadlineAutoConfiguration;
import net.devh.boot.grpc.common.autoconfigure.GrpcCommonCodecAutoConfiguration;
import net.devh.boot.grpc.server.autoconfigure.GrpcServerAutoConfiguration;
import net.devh.boot.grpc.server.autoconfigure.GrpcServerFactoryAutoConfiguration;
Expand All @@ -28,7 +29,7 @@
@Configuration
@ImportAutoConfiguration({GrpcCommonCodecAutoConfiguration.class, GrpcServerAutoConfiguration.class,
GrpcServerFactoryAutoConfiguration.class, GrpcServerSecurityAutoConfiguration.class,
GrpcClientAutoConfiguration.class})
GrpcClientAutoConfiguration.class, GrpcClientDeadlineAutoConfiguration.class})
public class BaseAutoConfiguration {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/*
* Copyright (c) 2016-2024 The gRPC-Spring Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package net.devh.boot.grpc.test.setup;

import static io.grpc.Status.DEADLINE_EXCEEDED;
import static net.devh.boot.grpc.test.util.GrpcAssertions.assertStatus;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertThrows;

import java.util.concurrent.ExecutionException;

import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;

import io.grpc.StatusRuntimeException;
import io.grpc.internal.testing.StreamRecorder;
import io.grpc.stub.StreamObserver;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import net.devh.boot.grpc.client.config.GrpcChannelProperties;
import net.devh.boot.grpc.test.config.BaseAutoConfiguration;
import net.devh.boot.grpc.test.config.ServiceConfiguration;
import net.devh.boot.grpc.test.proto.SomeType;

/**
* These tests check the property {@link GrpcChannelProperties#getDeadline()}.
*/
@Slf4j
@SpringBootTest(properties = {
"grpc.client.GLOBAL.address=localhost:9090",
"grpc.client.GLOBAL.deadline=1s",
"grpc.client.GLOBAL.negotiationType=PLAINTEXT",
})
@SpringJUnitConfig(classes = {ServiceConfiguration.class, BaseAutoConfiguration.class})
@DirtiesContext
public class DeadlineTests extends AbstractSimpleServerClientTest {

@Test
@SneakyThrows
void testServiceStubDeadlineEnabledAndSuccessful() {
log.info("--- Starting test with successful call ---");
final StreamRecorder<SomeType> streamRecorder = StreamRecorder.create();
StreamObserver<SomeType> echo = this.testServiceStub.echo(streamRecorder);
echo.onNext(SomeType.getDefaultInstance());
assertNull(streamRecorder.getError());
assertNotNull(streamRecorder.firstValue().get().getVersion());
log.info("--- Test completed --- ");
}

@Test
@SneakyThrows
void testServiceStubDeadlineEnabledAndUnsuccessful() {
log.info("--- Starting test with unsuccessful call ---");
final StreamRecorder<SomeType> streamRecorder = StreamRecorder.create();
this.testServiceStub.echo(streamRecorder);
assertThrows(ExecutionException.class, () -> streamRecorder.firstValue().get());
assertNotNull(streamRecorder.getError());
assertEquals(StatusRuntimeException.class, streamRecorder.getError().getClass());
assertStatus(DEADLINE_EXCEEDED.getCode(), (StatusRuntimeException) streamRecorder.getError());
log.info("--- Test completed --- ");
}

}

0 comments on commit a19dbef

Please sign in to comment.