Polishing contribution

Closes gh-30403
This commit is contained in:
rstoyanchev 2023-05-03 20:49:20 +01:00
parent 033548a760
commit 73d30dd875
6 changed files with 53 additions and 50 deletions

View File

@ -497,10 +497,12 @@ Annotated, HTTP exchange methods support the following return values:
TIP: You can also use any other async or reactive types registered in the TIP: You can also use any other async or reactive types registered in the
`ReactiveAdapterRegistry`. `ReactiveAdapterRegistry`.
TIP: For non-reactive types, blocking from a reactive publisher is performed By default, the behavior of HTTP service methods with synchronous (blocking) method
under the hood by the framework. By default, it is done without a timeout. signature depends on connection and timeout settings of the underlying HTTP client.
You can set a timeout for blocking by calling `blockTimeout(Duration blockTimeout)` `HttpServiceProxyFactory.Builder` does expose a `blockTimeout` option that also lets you
on `HttpServiceProxyFactory.Builder`. configure the maximum time to block for a response, but we recommend configuring timeout
values directly on the underlying HTTP client, which likely provides more control over
such settings.
[[rest-http-interface-exceptions]] [[rest-http-interface-exceptions]]

View File

@ -1064,7 +1064,9 @@ Annotated, RSocket exchange methods support return values that are concrete valu
any producer of value(s) that can be adapted to a Reactive Streams `Publisher` via any producer of value(s) that can be adapted to a Reactive Streams `Publisher` via
`ReactiveAdapterRegistry`. `ReactiveAdapterRegistry`.
TIP: For non-reactive types, blocking from a reactive publisher is performed By default, the behavior of RSocket service methods with synchronous (blocking) method
under the hood by the framework. By default, it is done without a timeout. signature depends on response timeout settings of the underlying RSocket `ClientTransport`
You can set a timeout for blocking by calling `blockTimeout(Duration blockTimeout)` as well as RSocket keep-alive settings. `RSocketServiceProxyFactory.Builder` does expose a
on `RSocketServiceProxyFactory.Builder`. `blockTimeout` option that also lets you configure the maximum time to block for a response,
but we recommend configuring timeout values at the RSocket level for more control.

View File

@ -73,8 +73,7 @@ final class RSocketServiceMethod {
this.parameters = initMethodParameters(method); this.parameters = initMethodParameters(method);
this.argumentResolvers = argumentResolvers; this.argumentResolvers = argumentResolvers;
this.route = initRoute(method, containingClass, rsocketRequester.strategies(), embeddedValueResolver); this.route = initRoute(method, containingClass, rsocketRequester.strategies(), embeddedValueResolver);
this.responseFunction = initResponseFunction( this.responseFunction = initResponseFunction(rsocketRequester, method, reactiveRegistry, blockTimeout);
rsocketRequester, method, reactiveRegistry, blockTimeout);
} }
private static MethodParameter[] initMethodParameters(Method method) { private static MethodParameter[] initMethodParameters(Method method) {
@ -163,11 +162,16 @@ final class RSocketServiceMethod {
if (reactiveAdapter != null) { if (reactiveAdapter != null) {
return reactiveAdapter.fromPublisher(responsePublisher); return reactiveAdapter.fromPublisher(responsePublisher);
} }
return (blockForOptional ? if (blockForOptional) {
(blockTimeout != null ? ((Mono<?>) responsePublisher).blockOptional(blockTimeout) : return (blockTimeout != null ?
((Mono<?>) responsePublisher).blockOptional()) : ((Mono<?>) responsePublisher).blockOptional(blockTimeout) :
(blockTimeout != null ? ((Mono<?>) responsePublisher).block(blockTimeout) : ((Mono<?>) responsePublisher).blockOptional());
((Mono<?>) responsePublisher).block())); }
else {
return (blockTimeout != null ?
((Mono<?>) responsePublisher).block(blockTimeout) :
((Mono<?>) responsePublisher).block());
}
}); });
} }

View File

@ -188,14 +188,17 @@ public final class RSocketServiceProxyFactory {
} }
/** /**
* Configure how long to wait for a response for an HTTP service method * Configure how long to block for the response of an RSocket service method
* with a synchronous (blocking) method signature. * with a synchronous (blocking) method signature.
* <p>By default this is {@code null}, * <p>By default this is not set, in which case the behavior depends on
* in which case means blocking on publishers is done without a timeout. * connection and response timeout settings of the underlying RSocket
* {@code ClientTransport} as well as RSocket keep-alive settings.
* We recommend configuring timeout values at the RSocket level which
* provides more control.
* @param blockTimeout the timeout value * @param blockTimeout the timeout value
* @return this same builder instance * @return this same builder instance
*/ */
public Builder blockTimeout(Duration blockTimeout) { public Builder blockTimeout(@Nullable Duration blockTimeout) {
this.blockTimeout = blockTimeout; this.blockTimeout = blockTimeout;
return this; return this;
} }
@ -208,8 +211,7 @@ public final class RSocketServiceProxyFactory {
return new RSocketServiceProxyFactory( return new RSocketServiceProxyFactory(
this.rsocketRequester, initArgumentResolvers(), this.rsocketRequester, initArgumentResolvers(),
this.embeddedValueResolver, this.reactiveAdapterRegistry, this.embeddedValueResolver, this.reactiveAdapterRegistry, this.blockTimeout);
this.blockTimeout);
} }
private List<RSocketServiceArgumentResolver> initArgumentResolvers() { private List<RSocketServiceArgumentResolver> initArgumentResolvers() {

View File

@ -123,15 +123,13 @@ final class HttpServiceMethod {
} }
} }
int index = i; int index = i;
Assert.state(resolved, () -> formatArgumentError(this.parameters[index], "No suitable resolver")); Assert.state(resolved, () ->
"Could not resolve parameter [" + this.parameters[index].getParameterIndex() + "] in " +
this.parameters[index].getExecutable().toGenericString() +
(StringUtils.hasText("No suitable resolver") ? ": " + "No suitable resolver" : ""));
} }
} }
private static String formatArgumentError(MethodParameter param, String message) {
return "Could not resolve parameter [" + param.getParameterIndex() + "] in " +
param.getExecutable().toGenericString() + (StringUtils.hasText(message) ? ": " + message : "");
}
/** /**
* Factory for {@link HttpRequestValues} with values extracted from the type * Factory for {@link HttpRequestValues} with values extracted from the type
@ -277,17 +275,6 @@ final class HttpServiceMethod {
@Nullable ReactiveAdapter returnTypeAdapter, @Nullable ReactiveAdapter returnTypeAdapter,
boolean blockForOptional, @Nullable Duration blockTimeout) { boolean blockForOptional, @Nullable Duration blockTimeout) {
private ResponseFunction(
Function<HttpRequestValues, Publisher<?>> responseFunction,
@Nullable ReactiveAdapter returnTypeAdapter,
boolean blockForOptional, Duration blockTimeout) {
this.responseFunction = responseFunction;
this.returnTypeAdapter = returnTypeAdapter;
this.blockForOptional = blockForOptional;
this.blockTimeout = blockTimeout;
}
@Nullable @Nullable
public Object execute(HttpRequestValues requestValues) { public Object execute(HttpRequestValues requestValues) {
@ -297,11 +284,16 @@ final class HttpServiceMethod {
return this.returnTypeAdapter.fromPublisher(responsePublisher); return this.returnTypeAdapter.fromPublisher(responsePublisher);
} }
return (this.blockForOptional ? if (this.blockForOptional) {
(this.blockTimeout != null ? ((Mono<?>) responsePublisher).blockOptional(this.blockTimeout) : return (this.blockTimeout != null ?
((Mono<?>) responsePublisher).blockOptional()) : ((Mono<?>) responsePublisher).blockOptional(this.blockTimeout) :
(this.blockTimeout != null ? ((Mono<?>) responsePublisher).block(this.blockTimeout) : ((Mono<?>) responsePublisher).blockOptional());
((Mono<?>) responsePublisher).block())); }
else {
return (this.blockTimeout != null ?
((Mono<?>) responsePublisher).block(this.blockTimeout) :
((Mono<?>) responsePublisher).block());
}
} }
@ -310,7 +302,7 @@ final class HttpServiceMethod {
*/ */
public static ResponseFunction create( public static ResponseFunction create(
HttpClientAdapter client, Method method, ReactiveAdapterRegistry reactiveRegistry, HttpClientAdapter client, Method method, ReactiveAdapterRegistry reactiveRegistry,
Duration blockTimeout) { @Nullable Duration blockTimeout) {
MethodParameter returnParam = new MethodParameter(method, -1); MethodParameter returnParam = new MethodParameter(method, -1);
Class<?> returnType = returnParam.getParameterType(); Class<?> returnType = returnParam.getParameterType();

View File

@ -207,14 +207,16 @@ public final class HttpServiceProxyFactory {
} }
/** /**
* Configure how long to wait for a response for an HTTP service method * Configure how long to block for the response of an HTTP service method
* with a synchronous (blocking) method signature. * with a synchronous (blocking) method signature.
* <p>By default this is {@code null}, * <p>By default this is not set, in which case the behavior depends on
* in which case means blocking on publishers is done without a timeout. * connection and request timeout settings of the underlying HTTP client.
* We recommend configuring timeout values directly on the underlying HTTP
* client, which provides more control over such settings.
* @param blockTimeout the timeout value * @param blockTimeout the timeout value
* @return this same builder instance * @return this same builder instance
*/ */
public Builder blockTimeout(Duration blockTimeout) { public Builder blockTimeout(@Nullable Duration blockTimeout) {
this.blockTimeout = blockTimeout; this.blockTimeout = blockTimeout;
return this; return this;
} }
@ -227,8 +229,7 @@ public final class HttpServiceProxyFactory {
return new HttpServiceProxyFactory( return new HttpServiceProxyFactory(
this.clientAdapter, initArgumentResolvers(), this.clientAdapter, initArgumentResolvers(),
this.embeddedValueResolver, this.reactiveAdapterRegistry, this.embeddedValueResolver, this.reactiveAdapterRegistry, this.blockTimeout);
this.blockTimeout);
} }
private List<HttpServiceArgumentResolver> initArgumentResolvers() { private List<HttpServiceArgumentResolver> initArgumentResolvers() {