Use timeouts

This commit is contained in:
Andrea Cavalli 2021-10-02 16:48:56 +02:00
parent 82050a5f0b
commit 714081a93c
12 changed files with 110 additions and 66 deletions

View File

@ -63,6 +63,11 @@
<artifactId>fastutil</artifactId> <artifactId>fastutil</artifactId>
<version>8.5.6</version> <version>8.5.6</version>
</dependency> </dependency>
<dependency>
<groupId>it.tdlight</groupId>
<artifactId>tdlight-java</artifactId>
<version>2.7.8.11</version>
</dependency>
</dependencies> </dependencies>
</dependencyManagement> </dependencyManagement>
<dependencies> <dependencies>
@ -154,7 +159,6 @@
<dependency> <dependency>
<groupId>it.tdlight</groupId> <groupId>it.tdlight</groupId>
<artifactId>tdlight-java</artifactId> <artifactId>tdlight-java</artifactId>
<version>2.7.8.9</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>it.cavallium</groupId> <groupId>it.cavallium</groupId>

View File

@ -2,6 +2,7 @@ package it.tdlight.tdlibsession.td;
import it.tdlight.jni.TdApi; import it.tdlight.jni.TdApi;
import it.tdlight.jni.TdApi.Object; import it.tdlight.jni.TdApi.Object;
import java.time.Duration;
import reactor.core.publisher.Flux; import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono; import reactor.core.publisher.Mono;
@ -11,7 +12,7 @@ public interface ReactorTelegramClient {
Flux<Object> receive(); Flux<Object> receive();
Mono<TdApi.Object> send(TdApi.Function query); Mono<TdApi.Object> send(TdApi.Function query, Duration timeout);
TdApi.Object execute(TdApi.Function query); TdApi.Object execute(TdApi.Function query);
} }

View File

@ -4,6 +4,7 @@ import it.tdlight.common.ReactiveItem;
import it.tdlight.common.ReactiveTelegramClient; import it.tdlight.common.ReactiveTelegramClient;
import it.tdlight.jni.TdApi; import it.tdlight.jni.TdApi;
import it.tdlight.utils.MonoUtils; import it.tdlight.utils.MonoUtils;
import java.time.Duration;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.reactivestreams.Subscriber; import org.reactivestreams.Subscriber;
import org.reactivestreams.Subscription; import org.reactivestreams.Subscription;
@ -67,13 +68,14 @@ public class WrappedReactorTelegramClient implements ReactorTelegramClient {
/** /**
* Sends a request to the TDLib. * Sends a request to the TDLib.
* *
* @param query Object representing a query to the TDLib. * @param query Object representing a query to the TDLib.
* @throws NullPointerException if query is null. * @param timeout Response timeout.
* @return a publisher that will emit exactly one item, or an error * @return a publisher that will emit exactly one item, or an error
* @throws NullPointerException if query is null.
*/ */
@Override @Override
public Mono<TdApi.Object> send(TdApi.Function query) { public Mono<TdApi.Object> send(TdApi.Function query, Duration timeout) {
return Mono.from(reactiveTelegramClient.send(query)).single(); return Mono.from(reactiveTelegramClient.send(query, timeout)).single();
} }
/** /**

View File

@ -3,6 +3,7 @@ package it.tdlight.tdlibsession.td.direct;
import it.tdlight.jni.TdApi; import it.tdlight.jni.TdApi;
import it.tdlight.jni.TdApi.Function; import it.tdlight.jni.TdApi.Function;
import it.tdlight.tdlibsession.td.TdResult; import it.tdlight.tdlibsession.td.TdResult;
import java.time.Duration;
import reactor.core.publisher.Flux; import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono; import reactor.core.publisher.Mono;
@ -22,9 +23,10 @@ public interface AsyncTdDirect {
* Should be called after receive. * Should be called after receive.
* *
* @param request Request to TDLib. * @param request Request to TDLib.
* @param timeout Response timeout.
* @param synchronous Execute synchronously. * @param synchronous Execute synchronously.
* @return The request response or {@link it.tdlight.jni.TdApi.Error}. * @return The request response or {@link it.tdlight.jni.TdApi.Error}.
*/ */
<T extends TdApi.Object> Mono<TdResult<T>> execute(Function request, boolean synchronous); <T extends TdApi.Object> Mono<TdResult<T>> execute(Function request, Duration timeout, boolean synchronous);
} }

View File

@ -39,7 +39,7 @@ public class AsyncTdDirectImpl implements AsyncTdDirect {
} }
@Override @Override
public <T extends TdApi.Object> Mono<TdResult<T>> execute(Function request, boolean synchronous) { public <T extends TdApi.Object> Mono<TdResult<T>> execute(Function request, Duration timeout, boolean synchronous) {
if (synchronous) { if (synchronous) {
return Mono return Mono
.firstWithSignal(td.asMono(), Mono.empty()) .firstWithSignal(td.asMono(), Mono.empty())
@ -61,7 +61,7 @@ public class AsyncTdDirectImpl implements AsyncTdDirect {
if (td != null) { if (td != null) {
return Mono return Mono
.fromRunnable(() -> logger.trace("Sending request to TDLib {}", request)) .fromRunnable(() -> logger.trace("Sending request to TDLib {}", request))
.then(td.send(request)) .then(td.send(request, timeout))
.single() .single()
.<TdResult<T>>map(TdResult::of) .<TdResult<T>>map(TdResult::of)
.doOnSuccess(s -> logger.trace("Sent request to TDLib {}", request)); .doOnSuccess(s -> logger.trace("Sent request to TDLib {}", request));

View File

@ -25,6 +25,7 @@ import it.tdlight.jni.TdApi.UpdateConnectionState;
import it.tdlight.jni.TdApi.UpdateNewMessage; import it.tdlight.jni.TdApi.UpdateNewMessage;
import it.tdlight.jni.TdApi.User; import it.tdlight.jni.TdApi.User;
import it.tdlight.tdlibsession.td.ReactorTelegramClient; import it.tdlight.tdlibsession.td.ReactorTelegramClient;
import java.time.Duration;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
@ -112,7 +113,7 @@ public class TestClient implements ReactorTelegramClient {
} }
@Override @Override
public Mono<TdApi.Object> send(Function query) { public Mono<TdApi.Object> send(Function query, Duration timeout) {
return Mono.fromCallable(() -> { return Mono.fromCallable(() -> {
TdApi.Object result = executeCommon(query); TdApi.Object result = executeCommon(query);
if (result != null) { if (result != null) {

View File

@ -39,6 +39,7 @@ import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.time.Duration;
import java.util.Comparator; import java.util.Comparator;
import java.util.Objects; import java.util.Objects;
import java.util.Set; import java.util.Set;
@ -57,6 +58,7 @@ import reactor.core.scheduler.Schedulers;
public class AsyncTdEasy { public class AsyncTdEasy {
private final Logger logger; private final Logger logger;
private static final Duration DEFAULT_TIMEOUT = Duration.ofMinutes(1);
private final Many<AuthorizationState> authState = Sinks.many().replay().latest(); private final Many<AuthorizationState> authState = Sinks.many().replay().latest();
private final Many<Boolean> requestedDefinitiveExit = Sinks.many().replay().latestOrDefault(false); private final Many<Boolean> requestedDefinitiveExit = Sinks.many().replay().latestOrDefault(false);
@ -181,14 +183,17 @@ public class AsyncTdEasy {
/** /**
* Sends request to TDLib. * Sends request to TDLib.
* @param timeout Timeout duration.
* @return The response or {@link TdApi.Error}. * @return The response or {@link TdApi.Error}.
*/ */
public <T extends Object> Mono<TdResult<T>> send(TdApi.Function request) { public <T extends Object> Mono<TdResult<T>> send(TdApi.Function request, Duration timeout) {
return td.<T>execute(request, false); return td.execute(request, timeout, false);
} }
private <T extends TdApi.Object> Mono<TdResult<T>> sendDirectly(TdApi.Function obj, boolean synchronous) { private <T extends TdApi.Object> Mono<TdResult<T>> sendDirectly(TdApi.Function obj,
return td.<T>execute(obj, synchronous); Duration timeout,
boolean synchronous) {
return td.execute(obj, timeout, synchronous);
} }
/** /**
@ -196,7 +201,7 @@ public class AsyncTdEasy {
* @param i level * @param i level
*/ */
public Mono<Void> setVerbosityLevel(int i) { public Mono<Void> setVerbosityLevel(int i) {
return thenOrFatalError(sendDirectly(new TdApi.SetLogVerbosityLevel(i), true)); return thenOrFatalError(sendDirectly(new TdApi.SetLogVerbosityLevel(i), DEFAULT_TIMEOUT, true));
} }
/** /**
@ -204,7 +209,10 @@ public class AsyncTdEasy {
* @param name option name * @param name option name
*/ */
public Mono<Void> clearOption(String name) { public Mono<Void> clearOption(String name) {
return thenOrFatalError(sendDirectly(new TdApi.SetOption(name, new TdApi.OptionValueEmpty()), false)); return thenOrFatalError(sendDirectly(new TdApi.SetOption(name, new TdApi.OptionValueEmpty()),
DEFAULT_TIMEOUT,
false
));
} }
/** /**
@ -213,7 +221,10 @@ public class AsyncTdEasy {
* @param value option value * @param value option value
*/ */
public Mono<Void> setOptionString(String name, String value) { public Mono<Void> setOptionString(String name, String value) {
return thenOrFatalError(sendDirectly(new TdApi.SetOption(name, new TdApi.OptionValueString(value)), false)); return thenOrFatalError(sendDirectly(new TdApi.SetOption(name, new TdApi.OptionValueString(value)),
DEFAULT_TIMEOUT,
false
));
} }
/** /**
@ -222,7 +233,10 @@ public class AsyncTdEasy {
* @param value option value * @param value option value
*/ */
public Mono<Void> setOptionInteger(String name, long value) { public Mono<Void> setOptionInteger(String name, long value) {
return thenOrFatalError(sendDirectly(new TdApi.SetOption(name, new TdApi.OptionValueInteger(value)), false)); return thenOrFatalError(sendDirectly(new TdApi.SetOption(name, new TdApi.OptionValueInteger(value)),
DEFAULT_TIMEOUT,
false
));
} }
/** /**
@ -231,7 +245,10 @@ public class AsyncTdEasy {
* @param value option value * @param value option value
*/ */
public Mono<Void> setOptionBoolean(String name, boolean value) { public Mono<Void> setOptionBoolean(String name, boolean value) {
return thenOrFatalError(sendDirectly(new TdApi.SetOption(name, new TdApi.OptionValueBoolean(value)), false)); return thenOrFatalError(sendDirectly(new TdApi.SetOption(name, new TdApi.OptionValueBoolean(value)),
DEFAULT_TIMEOUT,
false
));
} }
/** /**
@ -240,7 +257,10 @@ public class AsyncTdEasy {
* @return The value or nothing * @return The value or nothing
*/ */
public Mono<String> getOptionString(String name) { public Mono<String> getOptionString(String name) {
return this.<TdApi.OptionValue>sendDirectly(new TdApi.GetOption(name), false).<OptionValue>flatMap(MonoUtils::orElseThrow).flatMap((TdApi.OptionValue value) -> { return this
.<TdApi.OptionValue>sendDirectly(new TdApi.GetOption(name), DEFAULT_TIMEOUT, false)
.flatMap(MonoUtils::orElseThrow)
.flatMap((TdApi.OptionValue value) -> {
switch (value.getConstructor()) { switch (value.getConstructor()) {
case OptionValueString.CONSTRUCTOR: case OptionValueString.CONSTRUCTOR:
return Mono.just(((OptionValueString) value).value); return Mono.just(((OptionValueString) value).value);
@ -259,17 +279,20 @@ public class AsyncTdEasy {
* @return The value or nothing * @return The value or nothing
*/ */
public Mono<Long> getOptionInteger(String name) { public Mono<Long> getOptionInteger(String name) {
return this.<TdApi.OptionValue>sendDirectly(new TdApi.GetOption(name), false).<TdApi.OptionValue>flatMap(MonoUtils::orElseThrow).flatMap((TdApi.OptionValue value) -> { return this
switch (value.getConstructor()) { .<TdApi.OptionValue>sendDirectly(new TdApi.GetOption(name), DEFAULT_TIMEOUT, false)
case OptionValueInteger.CONSTRUCTOR: .flatMap(MonoUtils::orElseThrow)
return Mono.just(((OptionValueInteger) value).value); .flatMap((TdApi.OptionValue value) -> {
case OptionValueEmpty.CONSTRUCTOR: switch (value.getConstructor()) {
return Mono.empty(); case OptionValueInteger.CONSTRUCTOR:
default: return Mono.just(((OptionValueInteger) value).value);
return Mono.error(new UnsupportedOperationException("The option " + name + " is of type " case OptionValueEmpty.CONSTRUCTOR:
+ value.getClass().getSimpleName())); return Mono.empty();
} default:
}); return Mono.error(new UnsupportedOperationException(
"The option " + name + " is of type " + value.getClass().getSimpleName()));
}
});
} }
/** /**
@ -278,17 +301,20 @@ public class AsyncTdEasy {
* @return The value or nothing * @return The value or nothing
*/ */
public Mono<Boolean> getOptionBoolean(String name) { public Mono<Boolean> getOptionBoolean(String name) {
return this.<TdApi.OptionValue>sendDirectly(new TdApi.GetOption(name), false).<TdApi.OptionValue>flatMap(MonoUtils::orElseThrow).flatMap((TdApi.OptionValue value) -> { return this
switch (value.getConstructor()) { .<TdApi.OptionValue>sendDirectly(new TdApi.GetOption(name), DEFAULT_TIMEOUT, false)
case OptionValueBoolean.CONSTRUCTOR: .flatMap(MonoUtils::orElseThrow)
return Mono.just(((OptionValueBoolean) value).value); .flatMap((TdApi.OptionValue value) -> {
case OptionValueEmpty.CONSTRUCTOR: switch (value.getConstructor()) {
return Mono.empty(); case OptionValueBoolean.CONSTRUCTOR:
default: return Mono.just(((OptionValueBoolean) value).value);
return Mono.error(new UnsupportedOperationException("The option " + name + " is of type " case OptionValueEmpty.CONSTRUCTOR:
+ value.getClass().getSimpleName())); return Mono.empty();
} default:
}); return Mono.error(new UnsupportedOperationException(
"The option " + name + " is of type " + value.getClass().getSimpleName()));
}
});
} }
/** /**
@ -296,10 +322,11 @@ public class AsyncTdEasy {
* be called from any thread. * be called from any thread.
* *
* @param request Request to the TDLib. * @param request Request to the TDLib.
* @param timeout Timeout.
* @return The request response. * @return The request response.
*/ */
public <T extends Object> Mono<TdResult<T>> execute(TdApi.Function request) { public <T extends Object> Mono<TdResult<T>> execute(TdApi.Function request, Duration timeout) {
return td.<T>execute(request, true); return td.execute(request, timeout, true);
} }
/** /**
@ -322,7 +349,7 @@ public class AsyncTdEasy {
logger.debug("Setting requestedDefinitiveExit: true"); logger.debug("Setting requestedDefinitiveExit: true");
requestedDefinitiveExit.tryEmitNext(true); requestedDefinitiveExit.tryEmitNext(true);
}) })
.then(td.execute(new TdApi.Close(), false).doOnSubscribe(s -> { .then(td.execute(new TdApi.Close(), DEFAULT_TIMEOUT, false).doOnSubscribe(s -> {
logger.debug("Sending TdApi.Close"); logger.debug("Sending TdApi.Close");
})) }))
.doOnNext(closeResponse -> logger.debug("TdApi.Close response is: \"{}\"", .doOnNext(closeResponse -> logger.debug("TdApi.Close response is: \"{}\"",
@ -342,7 +369,7 @@ public class AsyncTdEasy {
} }
private Mono<Update> catchErrors(Object obj) { private Mono<Update> catchErrors(Object obj) {
return Mono.<Update>fromCallable(() -> { return Mono.fromCallable(() -> {
if (obj.getConstructor() == Error.CONSTRUCTOR) { if (obj.getConstructor() == Error.CONSTRUCTOR) {
var error = (Error) obj; var error = (Error) obj;
@ -419,27 +446,27 @@ public class AsyncTdEasy {
parameters.enableStorageOptimizer = settings.enableStorageOptimizer; parameters.enableStorageOptimizer = settings.enableStorageOptimizer;
parameters.ignoreFileNames = settings.ignoreFileNames; parameters.ignoreFileNames = settings.ignoreFileNames;
return new SetTdlibParameters(parameters); return new SetTdlibParameters(parameters);
}).flatMap((SetTdlibParameters obj1) -> sendDirectly(obj1, false))); }).flatMap((SetTdlibParameters obj1) -> sendDirectly(obj1, DEFAULT_TIMEOUT, false)));
case AuthorizationStateWaitEncryptionKey.CONSTRUCTOR: case AuthorizationStateWaitEncryptionKey.CONSTRUCTOR:
return thenOrFatalError(sendDirectly(new CheckDatabaseEncryptionKey(), false)) return thenOrFatalError(sendDirectly(new CheckDatabaseEncryptionKey(), DEFAULT_TIMEOUT, false))
.onErrorResume((error) -> { .onErrorResume((error) -> {
logger.error("Error while checking TDLib encryption key", error); logger.error("Error while checking TDLib encryption key", error);
return sendDirectly(new TdApi.Close(), false).then(); return sendDirectly(new TdApi.Close(), DEFAULT_TIMEOUT, false).then();
}); });
case AuthorizationStateWaitPhoneNumber.CONSTRUCTOR: case AuthorizationStateWaitPhoneNumber.CONSTRUCTOR:
return thenOrFatalError(Mono.from(this.settings.asFlux()).flatMap(settings -> { return thenOrFatalError(Mono.from(this.settings.asFlux()).flatMap(settings -> {
if (settings.isPhoneNumberSet()) { if (settings.isPhoneNumberSet()) {
return sendDirectly(new SetAuthenticationPhoneNumber(String.valueOf(settings.getPhoneNumber()), return sendDirectly(new SetAuthenticationPhoneNumber(String.valueOf(settings.getPhoneNumber()),
new PhoneNumberAuthenticationSettings(false, false, false) new PhoneNumberAuthenticationSettings(false, false, false)
), false); ), DEFAULT_TIMEOUT, false);
} else if (settings.isBotTokenSet()) { } else if (settings.isBotTokenSet()) {
return sendDirectly(new CheckAuthenticationBotToken(settings.getBotToken()), false); return sendDirectly(new CheckAuthenticationBotToken(settings.getBotToken()), DEFAULT_TIMEOUT, false);
} else { } else {
return Mono.error(new IllegalArgumentException("A bot is neither an user or a bot")); return Mono.error(new IllegalArgumentException("A bot is neither an user or a bot"));
} }
})).onErrorResume((error) -> { })).onErrorResume((error) -> {
logger.error("Error while waiting for phone number", error); logger.error("Error while waiting for phone number", error);
return sendDirectly(new TdApi.Close(), false).then(); return sendDirectly(new TdApi.Close(), DEFAULT_TIMEOUT, false).then();
}); });
case AuthorizationStateWaitRegistration.CONSTRUCTOR: case AuthorizationStateWaitRegistration.CONSTRUCTOR:
var authorizationStateWaitRegistration = (AuthorizationStateWaitRegistration) obj; var authorizationStateWaitRegistration = (AuthorizationStateWaitRegistration) obj;
@ -471,7 +498,7 @@ public class AsyncTdEasy {
.defaultIfEmpty("") .defaultIfEmpty("")
.doOnNext(lastName -> registerUser.lastName = lastName) .doOnNext(lastName -> registerUser.lastName = lastName)
) )
.then(sendDirectly(registerUser, false))); .then(sendDirectly(registerUser, DEFAULT_TIMEOUT, false)));
}); });
case TdApi.AuthorizationStateWaitOtherDeviceConfirmation.CONSTRUCTOR: case TdApi.AuthorizationStateWaitOtherDeviceConfirmation.CONSTRUCTOR:
var authorizationStateWaitOtherDeviceConfirmation = (AuthorizationStateWaitOtherDeviceConfirmation) obj; var authorizationStateWaitOtherDeviceConfirmation = (AuthorizationStateWaitOtherDeviceConfirmation) obj;
@ -495,7 +522,7 @@ public class AsyncTdEasy {
authorizationStateWaitCode.codeInfo.timeout, authorizationStateWaitCode.codeInfo.timeout,
authorizationStateWaitCode.codeInfo.type authorizationStateWaitCode.codeInfo.type
) )
).flatMap(code -> sendDirectly(new CheckAuthenticationCode(code), false))); ).flatMap(code -> sendDirectly(new CheckAuthenticationCode(code), DEFAULT_TIMEOUT, false)));
}); });
case AuthorizationStateWaitPassword.CONSTRUCTOR: case AuthorizationStateWaitPassword.CONSTRUCTOR:
var authorizationStateWaitPassword = (AuthorizationStateWaitPassword) obj; var authorizationStateWaitPassword = (AuthorizationStateWaitPassword) obj;
@ -505,7 +532,7 @@ public class AsyncTdEasy {
.flatMap(handler -> { .flatMap(handler -> {
return MonoUtils.thenOrLogRepeatError(() -> handler.onParameterRequest(Parameter.ASK_PASSWORD, return MonoUtils.thenOrLogRepeatError(() -> handler.onParameterRequest(Parameter.ASK_PASSWORD,
new ParameterInfoPasswordHint(authorizationStateWaitPassword.passwordHint) new ParameterInfoPasswordHint(authorizationStateWaitPassword.passwordHint)
).flatMap(password -> sendDirectly(new CheckAuthenticationPassword(password), false))); ).flatMap(password -> sendDirectly(new CheckAuthenticationPassword(password), DEFAULT_TIMEOUT, false)));
}); });
case AuthorizationStateReady.CONSTRUCTOR: { case AuthorizationStateReady.CONSTRUCTOR: {
this.authState.tryEmitNext(new AuthorizationStateReady()); this.authState.tryEmitNext(new AuthorizationStateReady());

View File

@ -2,6 +2,7 @@ package it.tdlight.tdlibsession.td.middle;
import it.tdlight.jni.TdApi; import it.tdlight.jni.TdApi;
import it.tdlight.tdlibsession.td.TdResult; import it.tdlight.tdlibsession.td.TdResult;
import java.time.Duration;
import reactor.core.publisher.Flux; import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono; import reactor.core.publisher.Mono;
@ -20,7 +21,8 @@ public interface AsyncTdMiddle {
* Sends request to TDLib. May be called from any thread. * Sends request to TDLib. May be called from any thread.
* *
* @param request Request to TDLib. * @param request Request to TDLib.
* @param executeDirectly Execute the function synchronously. * @param timeout Timeout.
* @param executeSync Execute the function synchronously.
*/ */
<T extends TdApi.Object> Mono<TdResult<T>> execute(TdApi.Function request, boolean executeDirectly); <T extends TdApi.Object> Mono<TdResult<T>> execute(TdApi.Function request, Duration timeout, boolean executeSync);
} }

View File

@ -343,8 +343,9 @@ public class AsyncTdMiddleEventBusClient implements AsyncTdMiddle {
} }
@Override @Override
public <T extends TdApi.Object> Mono<TdResult<T>> execute(Function request, boolean executeDirectly) { public <T extends TdApi.Object> Mono<TdResult<T>> execute(Function request, Duration timeout, boolean executeSync) {
var req = new ExecuteObject(executeDirectly, request); var req = new ExecuteObject(executeSync, request);
var deliveryOptions = new DeliveryOptions(this.deliveryOptions).setSendTimeout(timeout.toMillis());
var crashMono = crash.asMono() var crashMono = crash.asMono()
.doOnSuccess(s -> logger.debug("Failed request {} because the TDLib session was already crashed", request)) .doOnSuccess(s -> logger.debug("Failed request {} because the TDLib session was already crashed", request))

View File

@ -16,6 +16,7 @@ import it.tdlight.tdlibsession.td.direct.TelegramClientFactory;
import it.tdlight.tdlibsession.td.middle.AsyncTdMiddle; import it.tdlight.tdlibsession.td.middle.AsyncTdMiddle;
import it.tdlight.tdlibsession.td.middle.TdClusterManager; import it.tdlight.tdlibsession.td.middle.TdClusterManager;
import it.tdlight.utils.MonoUtils; import it.tdlight.utils.MonoUtils;
import java.time.Duration;
import org.warp.commonutils.log.Logger; import org.warp.commonutils.log.Logger;
import org.warp.commonutils.log.LoggerFactory; import org.warp.commonutils.log.LoggerFactory;
import reactor.core.publisher.Flux; import reactor.core.publisher.Flux;
@ -101,9 +102,11 @@ public class AsyncTdMiddleDirect extends AbstractVerticle implements AsyncTdMidd
} }
@Override @Override
public <T extends Object> Mono<TdResult<T>> execute(Function requestFunction, boolean executeDirectly) { public <T extends Object> Mono<TdResult<T>> execute(Function requestFunction,
Duration timeout,
boolean executeDirectly) {
return td return td
.<T>execute(requestFunction, executeDirectly) .<T>execute(requestFunction, timeout, executeDirectly)
.onErrorMap(error -> ResponseError.newResponseError(requestFunction, botAlias, error)); .onErrorMap(error -> ResponseError.newResponseError(requestFunction, botAlias, error));
} }
} }

View File

@ -13,6 +13,7 @@ import it.tdlight.tdlibsession.td.middle.client.AsyncTdMiddleEventBusClient;
import it.tdlight.tdlibsession.td.middle.server.AsyncTdMiddleEventBusServer; import it.tdlight.tdlibsession.td.middle.server.AsyncTdMiddleEventBusServer;
import it.tdlight.utils.MonoUtils; import it.tdlight.utils.MonoUtils;
import java.nio.file.Path; import java.nio.file.Path;
import java.time.Duration;
import org.warp.commonutils.error.InitializationException; import org.warp.commonutils.error.InitializationException;
import reactor.core.publisher.Flux; import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono; import reactor.core.publisher.Mono;
@ -79,7 +80,7 @@ public class AsyncTdMiddleLocal implements AsyncTdMiddle {
} }
@Override @Override
public <T extends Object> Mono<TdResult<T>> execute(Function request, boolean executeDirectly) { public <T extends Object> Mono<TdResult<T>> execute(Function request, Duration timeout, boolean executeDirectly) {
return cli.asMono().single().flatMap(c -> c.execute(request, executeDirectly)); return cli.asMono().single().flatMap(c -> c.execute(request, timeout, executeDirectly));
} }
} }

View File

@ -149,9 +149,8 @@ public class AsyncTdMiddleEventBusServer extends AbstractVerticle {
logger.trace("Received execute request {}", request); logger.trace("Received execute request {}", request);
} }
return td return td
.execute(request, body.isExecuteDirectly()) .execute(request, Duration.ofSeconds(60 + 30), body.isExecuteDirectly())
.single() .single()
.timeout(Duration.ofSeconds(60 + 30))
.doOnSuccess(s -> logger.trace("Executed successfully. Request was {}", request)) .doOnSuccess(s -> logger.trace("Executed successfully. Request was {}", request))
.onErrorResume(ex -> Mono.fromRunnable(() -> msg.fail(500, ex.getLocalizedMessage()))) .onErrorResume(ex -> Mono.fromRunnable(() -> msg.fail(500, ex.getLocalizedMessage())))
.flatMap(response -> Mono.fromCallable(() -> { .flatMap(response -> Mono.fromCallable(() -> {
@ -389,7 +388,8 @@ public class AsyncTdMiddleEventBusServer extends AbstractVerticle {
if (printDefaultException) { if (printDefaultException) {
logger.warn("Undeploying after a fatal error in a served flux", ex); logger.warn("Undeploying after a fatal error in a served flux", ex);
} }
return td.execute(new TdApi.Close(), false) return td
.execute(new TdApi.Close(), Duration.ofDays(1), false)
.doOnError(ex2 -> logger.error("Unexpected error", ex2)) .doOnError(ex2 -> logger.error("Unexpected error", ex2))
.doOnSuccess(s -> logger.debug("Emergency Close() signal has been sent successfully")) .doOnSuccess(s -> logger.debug("Emergency Close() signal has been sent successfully"))
.then(rxStop().as(MonoUtils::toMono)); .then(rxStop().as(MonoUtils::toMono));