2022-01-09 20:20:20 +01:00
|
|
|
package it.tdlight.reactiveapi;
|
|
|
|
|
2022-01-23 12:58:10 +01:00
|
|
|
import static it.tdlight.reactiveapi.AtomixUtils.fromCf;
|
|
|
|
|
2022-01-09 20:20:20 +01:00
|
|
|
import io.atomix.cluster.messaging.ClusterEventService;
|
|
|
|
import io.atomix.cluster.messaging.MessagingException;
|
|
|
|
import it.tdlight.jni.TdApi;
|
|
|
|
import it.tdlight.reactiveapi.Event.ClientBoundEvent;
|
2022-05-05 20:25:00 +02:00
|
|
|
import it.tdlight.reactiveapi.Event.OnRequest.Request;
|
2022-01-23 14:52:08 +01:00
|
|
|
import java.net.ConnectException;
|
2022-01-09 20:20:20 +01:00
|
|
|
import java.time.Duration;
|
|
|
|
import java.time.Instant;
|
|
|
|
import java.util.concurrent.CompletableFuture;
|
2022-01-23 12:58:10 +01:00
|
|
|
import java.util.concurrent.CompletionException;
|
|
|
|
import java.util.concurrent.TimeoutException;
|
2022-01-09 20:20:20 +01:00
|
|
|
import reactor.core.publisher.Flux;
|
|
|
|
import reactor.core.publisher.Mono;
|
2022-01-11 19:59:27 +01:00
|
|
|
import reactor.core.scheduler.Schedulers;
|
2022-01-09 20:20:20 +01:00
|
|
|
|
|
|
|
public class AtomixReactiveApiMultiClient implements ReactiveApiMultiClient, AutoCloseable {
|
|
|
|
|
|
|
|
private final ClusterEventService eventService;
|
2022-01-13 01:59:26 +01:00
|
|
|
private final KafkaConsumer kafkaConsumer;
|
2022-01-13 16:19:10 +01:00
|
|
|
private final String subGroupId;
|
2022-01-09 20:20:20 +01:00
|
|
|
|
2022-01-09 20:50:58 +01:00
|
|
|
private volatile boolean closed = false;
|
|
|
|
|
2022-01-13 16:19:10 +01:00
|
|
|
AtomixReactiveApiMultiClient(AtomixReactiveApi api, KafkaConsumer kafkaConsumer, String subGroupId) {
|
2022-01-09 20:20:20 +01:00
|
|
|
this.eventService = api.getAtomix().getEventService();
|
2022-01-13 01:59:26 +01:00
|
|
|
this.kafkaConsumer = kafkaConsumer;
|
2022-01-13 16:19:10 +01:00
|
|
|
this.subGroupId = subGroupId;
|
2022-01-09 20:20:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2022-01-13 01:59:26 +01:00
|
|
|
public Flux<ClientBoundEvent> clientBoundEvents(boolean ack) {
|
|
|
|
if (closed) {
|
|
|
|
return Flux.empty();
|
|
|
|
}
|
2022-01-22 17:45:56 +01:00
|
|
|
return kafkaConsumer.consumeMessages(subGroupId).map(TimestampedClientBoundEvent::event).takeUntil(s -> closed);
|
2022-01-09 20:20:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public <T extends TdApi.Object> Mono<T> request(long userId, long liveId, TdApi.Function<T> request, Instant timeout) {
|
2022-01-23 12:58:10 +01:00
|
|
|
return fromCf(() -> {
|
2022-01-09 20:50:58 +01:00
|
|
|
if (closed) {
|
|
|
|
return CompletableFuture.failedFuture(new TdError(500, "Session is closed"));
|
|
|
|
}
|
|
|
|
return eventService.send("session-" + liveId + "-requests",
|
|
|
|
new Request<>(liveId, request, timeout),
|
|
|
|
LiveAtomixReactiveApiClient::serializeRequest,
|
|
|
|
LiveAtomixReactiveApiClient::deserializeResponse,
|
|
|
|
Duration.between(Instant.now(), timeout)
|
|
|
|
);
|
2022-01-11 19:59:27 +01:00
|
|
|
}).subscribeOn(Schedulers.boundedElastic()).<T>handle((item, sink) -> {
|
2022-01-09 20:50:58 +01:00
|
|
|
if (item instanceof TdApi.Error error) {
|
|
|
|
sink.error(new TdError(error.code, error.message));
|
|
|
|
} else {
|
|
|
|
//noinspection unchecked
|
|
|
|
sink.next((T) item);
|
|
|
|
}
|
|
|
|
}).onErrorMap(ex -> {
|
|
|
|
if (ex instanceof MessagingException.NoRemoteHandler) {
|
|
|
|
return new TdError(404, "Bot #IDU" + userId + " (live id: " + liveId + ") is not found on the cluster");
|
2022-01-23 14:52:08 +01:00
|
|
|
} else if (ex instanceof TimeoutException || ex instanceof ConnectException) {
|
2022-01-23 12:58:10 +01:00
|
|
|
return new TdError(408, "Request Timeout", ex);
|
2022-01-09 20:50:58 +01:00
|
|
|
} else {
|
|
|
|
return ex;
|
|
|
|
}
|
|
|
|
});
|
2022-01-09 20:20:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void close() {
|
2022-01-09 20:50:58 +01:00
|
|
|
closed = true;
|
2022-01-09 20:20:20 +01:00
|
|
|
}
|
|
|
|
}
|