tdlib-session-container/src/main/java/it/tdlight/reactiveapi/TdlibChannelsSharedReceive....

112 lines
3.9 KiB
Java
Raw Normal View History

2022-09-10 20:25:54 +02:00
package it.tdlight.reactiveapi;
2022-10-07 00:48:10 +02:00
import static it.tdlight.reactiveapi.TdlibChannelsSharedHost.REPEAT_STRATEGY;
import static it.tdlight.reactiveapi.TdlibChannelsSharedHost.RETRY_STRATEGY;
2022-09-10 20:25:54 +02:00
import it.tdlight.jni.TdApi.Object;
import it.tdlight.reactiveapi.Event.ClientBoundEvent;
import it.tdlight.reactiveapi.Event.OnRequest;
import it.tdlight.reactiveapi.Event.OnResponse;
import java.io.Closeable;
2022-10-06 00:36:00 +02:00
import java.time.Duration;
2022-09-22 15:46:31 +02:00
import java.util.Map;
import java.util.Map.Entry;
2022-09-10 20:25:54 +02:00
import java.util.concurrent.atomic.AtomicReference;
2022-10-07 00:48:10 +02:00
import java.util.logging.Level;
2022-09-22 15:46:31 +02:00
import java.util.stream.Collectors;
2022-09-10 20:25:54 +02:00
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import reactor.core.Disposable;
import reactor.core.publisher.Flux;
2022-10-06 00:36:00 +02:00
import reactor.core.publisher.Mono;
2022-09-10 20:25:54 +02:00
import reactor.core.publisher.Sinks;
2022-10-06 00:36:00 +02:00
import reactor.core.publisher.Sinks.EmitFailureHandler;
2022-09-10 20:25:54 +02:00
import reactor.core.publisher.Sinks.Many;
import reactor.core.scheduler.Schedulers;
import reactor.util.concurrent.Queues;
2022-10-06 00:36:00 +02:00
import reactor.util.retry.Retry;
import reactor.util.retry.RetryBackoffSpec;
2022-09-10 20:25:54 +02:00
2022-10-06 00:36:00 +02:00
public class TdlibChannelsSharedReceive implements Closeable {
2022-09-10 20:25:54 +02:00
2022-10-06 00:36:00 +02:00
private static final Logger LOG = LogManager.getLogger(TdlibChannelsSharedReceive.class);
2022-10-05 02:26:30 +02:00
private final TdlibChannelsClients tdClientsChannels;
2022-09-10 20:25:54 +02:00
private final AtomicReference<Disposable> responsesSub = new AtomicReference<>();
private final Disposable requestsSub;
private final AtomicReference<Disposable> eventsSub = new AtomicReference<>();
private final Flux<Timestamped<OnResponse<Object>>> responses;
2022-09-22 15:46:31 +02:00
private final Map<String, Flux<Timestamped<ClientBoundEvent>>> events;
2022-10-07 00:48:10 +02:00
private final Many<OnRequest<?>> requests = Sinks.many().multicast().directAllOrNothing();
2022-09-10 20:25:54 +02:00
2022-10-06 00:36:00 +02:00
public TdlibChannelsSharedReceive(TdlibChannelsClients tdClientsChannels) {
2022-10-05 02:26:30 +02:00
this.tdClientsChannels = tdClientsChannels;
2022-10-07 00:48:10 +02:00
this.responses = Flux
.defer(() -> tdClientsChannels.response().consumeMessages())
//.log("responses", Level.FINE)
2022-10-07 00:48:10 +02:00
.repeatWhen(REPEAT_STRATEGY)
2022-10-06 00:36:00 +02:00
.retryWhen(RETRY_STRATEGY)
2022-10-07 00:48:10 +02:00
.publish()
.autoConnect()
2022-10-06 00:36:00 +02:00
.doFinally(s -> LOG.debug("Input responses flux terminated with signal {}", s));
2022-10-05 02:26:30 +02:00
this.events = tdClientsChannels.events().entrySet().stream()
2022-10-06 00:36:00 +02:00
.collect(Collectors.toUnmodifiableMap(Entry::getKey,
2022-10-07 00:48:10 +02:00
e -> Flux
.defer(() -> e.getValue().consumeMessages())
.repeatWhen(REPEAT_STRATEGY)
2022-10-06 00:36:00 +02:00
.retryWhen(RETRY_STRATEGY)
.doFinally(s -> LOG.debug("Input events flux of lane \"{}\" terminated with signal {}", e.getKey(), s))
));
2022-10-07 00:48:10 +02:00
this.requestsSub = tdClientsChannels
.request()
.sendMessages(Flux
.defer(() -> requests
.asFlux()
.doFinally(s -> LOG.debug("Output requests flux terminated with signal {}", s))))
.doFinally(s -> LOG.debug("Output requests sender terminated with signal {}", s))
.repeatWhen(REPEAT_STRATEGY)
2022-10-06 00:36:00 +02:00
.retryWhen(RETRY_STRATEGY)
2022-09-10 20:25:54 +02:00
.subscribeOn(Schedulers.parallel())
2022-10-07 00:48:10 +02:00
.subscribe(n -> {}, ex -> {
LOG.error("An error when handling requests killed the requests subscriber!", ex);
requests.emitError(ex, EmitFailureHandler.busyLooping(Duration.ofMillis(100)));
});
2022-09-10 20:25:54 +02:00
}
2022-09-13 22:15:18 +02:00
public Flux<Timestamped<OnResponse<Object>>> responses() {
return responses;
2022-09-10 20:25:54 +02:00
}
2022-09-22 15:46:31 +02:00
public Flux<Timestamped<ClientBoundEvent>> events(String lane) {
var result = events.get(lane);
if (result == null) {
throw new IllegalArgumentException("No lane " + lane);
}
return result;
}
public Map<String, Flux<Timestamped<ClientBoundEvent>>> events() {
2022-09-13 22:15:18 +02:00
return events;
2022-09-10 20:25:54 +02:00
}
2022-10-07 00:48:10 +02:00
public void emitRequest(OnRequest<?> request) {
synchronized (requests) {
requests.emitNext(request, EmitFailureHandler.FAIL_FAST);
}
2022-09-10 20:25:54 +02:00
}
@Override
public void close() {
requestsSub.dispose();
var responsesSub = this.responsesSub.get();
if (responsesSub != null) {
responsesSub.dispose();
}
var eventsSub = this.eventsSub.get();
if (eventsSub != null) {
eventsSub.dispose();
}
2022-10-05 02:26:30 +02:00
tdClientsChannels.close();
2022-09-10 20:25:54 +02:00
}
}