tmp
This commit is contained in:
parent
798f77ddbc
commit
703e9b1044
|
@ -48,6 +48,8 @@ public class AsyncTdMiddleEventBusClient implements AsyncTdMiddle {
|
||||||
private final Empty<Void> updatesStreamEnd = Sinks.one();
|
private final Empty<Void> updatesStreamEnd = Sinks.one();
|
||||||
// This will only result in a crash, never completes in other ways
|
// This will only result in a crash, never completes in other ways
|
||||||
private final Empty<Void> crash = Sinks.one();
|
private final Empty<Void> crash = Sinks.one();
|
||||||
|
// This will only result in a successful completion, never completes in other ways
|
||||||
|
private final Empty<Void> pingFail = Sinks.one();
|
||||||
|
|
||||||
private int botId;
|
private int botId;
|
||||||
private String botAddress;
|
private String botAddress;
|
||||||
|
@ -131,29 +133,71 @@ public class AsyncTdMiddleEventBusClient implements AsyncTdMiddle {
|
||||||
if (local) {
|
if (local) {
|
||||||
return Mono.empty();
|
return Mono.empty();
|
||||||
}
|
}
|
||||||
|
logger.trace("Requesting bots.start-bot");
|
||||||
return cluster.getEventBus()
|
return cluster.getEventBus()
|
||||||
.<byte[]>rxRequest("bots.start-bot", msg).as(MonoUtils::toMono)
|
.<byte[]>rxRequest("bots.start-bot", msg).as(MonoUtils::toMono)
|
||||||
.publishOn(Schedulers.boundedElastic());
|
.doOnSuccess(s -> logger.trace("bots.start-bot returned successfully"))
|
||||||
|
.subscribeOn(Schedulers.boundedElastic());
|
||||||
}))
|
}))
|
||||||
.then();
|
.then(setupPing());
|
||||||
})
|
})
|
||||||
.publishOn(Schedulers.single());
|
.publishOn(Schedulers.single());
|
||||||
}
|
}
|
||||||
|
|
||||||
private Mono<Void> setupUpdatesListener() {
|
private Mono<Void> setupPing() {
|
||||||
return MonoUtils
|
return Mono.<Void>fromCallable(() -> {
|
||||||
.fromBlockingMaybe(() -> {
|
logger.trace("Setting up ping");
|
||||||
MessageConsumer<TdResultList> updateConsumer = MessageConsumer.newInstance(cluster.getEventBus().<TdResultList>consumer(
|
// Disable ping on local servers
|
||||||
botAddress + ".updates").setMaxBufferedMessages(5000).getDelegate());
|
if (!local) {
|
||||||
|
Mono
|
||||||
|
.defer(() -> cluster.getEventBus().<byte[]>rxRequest(botAddress + ".ping",
|
||||||
|
EMPTY,
|
||||||
|
deliveryOptionsWithTimeout
|
||||||
|
).as(MonoUtils::toMono))
|
||||||
|
.flatMap(msg -> Mono.fromCallable(msg::body).subscribeOn(Schedulers.boundedElastic()))
|
||||||
|
.repeatWhen(l -> l.delayElements(Duration.ofSeconds(10)).takeWhile(x -> true))
|
||||||
|
.takeUntilOther(Mono.firstWithSignal(this.updatesStreamEnd.asMono().doOnTerminate(() -> {
|
||||||
|
logger.trace("About to kill pinger because updates stream ended");
|
||||||
|
}), this.crash.asMono().onErrorResume(ex -> Mono.empty()).doOnTerminate(() -> {
|
||||||
|
logger.trace("About to kill pinger because it has seen a crash signal");
|
||||||
|
})))
|
||||||
|
.doOnNext(s -> logger.warn("REPEATING PING"))
|
||||||
|
.map(x -> 1)
|
||||||
|
.defaultIfEmpty(0)
|
||||||
|
.doOnNext(s -> logger.warn("PING"))
|
||||||
|
.then()
|
||||||
|
.doOnNext(s -> logger.warn("END PING"))
|
||||||
|
.then(MonoUtils.emitEmpty(this.pingFail))
|
||||||
|
.subscribeOn(Schedulers.single())
|
||||||
|
.subscribe();
|
||||||
|
}
|
||||||
|
logger.trace("Ping setup success");
|
||||||
|
return null;
|
||||||
|
}).subscribeOn(Schedulers.boundedElastic());
|
||||||
|
}
|
||||||
|
|
||||||
|
private Mono<Void> setupUpdatesListener() {
|
||||||
|
return Mono
|
||||||
|
.fromRunnable(() -> logger.trace("Setting up updates listener..."))
|
||||||
|
.then(MonoUtils.<MessageConsumer<TdResultList>>fromBlockingSingle(() -> {
|
||||||
|
return MessageConsumer.newInstance(cluster.getEventBus().<TdResultList>consumer(botAddress + ".updates")
|
||||||
|
.setMaxBufferedMessages(5000)
|
||||||
|
.getDelegate());
|
||||||
|
}))
|
||||||
|
.flatMap(updateConsumer -> {
|
||||||
// Here the updates will be piped from the server to the client
|
// Here the updates will be piped from the server to the client
|
||||||
var updateConsumerFlux = MonoUtils.fromConsumer(updateConsumer);
|
var updateConsumerFlux = MonoUtils.fromConsumer(updateConsumer);
|
||||||
|
|
||||||
// Return when the registration of all the consumers has been done across the cluster
|
// Return when the registration of all the consumers has been done across the cluster
|
||||||
return MonoUtils
|
return Mono
|
||||||
.emitValue(updates, updateConsumerFlux)
|
.fromRunnable(() -> logger.trace("Emitting updates flux to sink"))
|
||||||
.then(updateConsumer.rxCompletionHandler().as(MonoUtils::toMono));
|
.then(MonoUtils.emitValue(updates, updateConsumerFlux))
|
||||||
|
.doOnSuccess(s -> logger.trace("Emitted updates flux to sink"))
|
||||||
|
.doOnSuccess(s -> logger.trace("Waiting to register update consumer across the cluster"))
|
||||||
|
.then(updateConsumer.rxCompletionHandler().as(MonoUtils::toMono))
|
||||||
|
.doOnSuccess(s -> logger.trace("Registered update consumer across the cluster"));
|
||||||
})
|
})
|
||||||
|
.doOnSuccess(s ->logger.trace("Set up updates listener"))
|
||||||
.then();
|
.then();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -163,22 +207,24 @@ public class AsyncTdMiddleEventBusClient implements AsyncTdMiddle {
|
||||||
return Mono
|
return Mono
|
||||||
.fromRunnable(() -> logger.trace("Called receive() from parent"))
|
.fromRunnable(() -> logger.trace("Called receive() from parent"))
|
||||||
.doOnSuccess(s -> logger.trace("Sending ready-to-receive"))
|
.doOnSuccess(s -> logger.trace("Sending ready-to-receive"))
|
||||||
.then()
|
|
||||||
.doOnSuccess(s -> logger.trace("Sent ready-to-receive, received reply"))
|
.doOnSuccess(s -> logger.trace("Sent ready-to-receive, received reply"))
|
||||||
.doOnSuccess(s -> logger.trace("About to read updates flux"))
|
.doOnSuccess(s -> logger.trace("About to read updates flux"))
|
||||||
.then(updates.asMono().publishOn(Schedulers.single()))
|
.then(updates.asMono().publishOn(Schedulers.single()))
|
||||||
.timeout(Duration.ofSeconds(5))
|
.timeout(Duration.ofSeconds(5))
|
||||||
.publishOn(Schedulers.single())
|
.publishOn(Schedulers.single())
|
||||||
.flatMapMany(tdResultListFlux -> tdResultListFlux.publishOn(Schedulers.single()))
|
.flatMapMany(updatesFlux -> updatesFlux.publishOn(Schedulers.single()))
|
||||||
.timeout(Duration.ofMinutes(1), Mono.fromCallable(() -> {
|
.takeUntilOther(Flux
|
||||||
var ex = new ConnectException("Server did not respond to 12 pings after 1 minute (5 seconds per ping)");
|
.merge(
|
||||||
ex.setStackTrace(new StackTraceElement[0]);
|
crash.asMono()
|
||||||
throw ex;
|
.onErrorResume(ex -> Mono.empty()),
|
||||||
}))
|
pingFail.asMono()
|
||||||
.doOnSubscribe(s -> cluster.getEventBus().<byte[]>send(botAddress + ".ready-to-receive",
|
.then(Mono.fromCallable(() -> {
|
||||||
EMPTY,
|
var ex = new ConnectException("Server did not respond to ping");
|
||||||
deliveryOptionsWithTimeout
|
ex.setStackTrace(new StackTraceElement[0]);
|
||||||
))
|
throw ex;
|
||||||
|
}).onErrorResume(ex -> MonoUtils.emitError(crash, ex)))
|
||||||
|
)
|
||||||
|
)
|
||||||
.flatMapSequential(updates -> {
|
.flatMapSequential(updates -> {
|
||||||
if (updates.succeeded()) {
|
if (updates.succeeded()) {
|
||||||
return Flux.fromIterable(updates.value());
|
return Flux.fromIterable(updates.value());
|
||||||
|
@ -188,7 +234,10 @@ public class AsyncTdMiddleEventBusClient implements AsyncTdMiddle {
|
||||||
})
|
})
|
||||||
.publishOn(Schedulers.single())
|
.publishOn(Schedulers.single())
|
||||||
.flatMapSequential(this::interceptUpdate)
|
.flatMapSequential(this::interceptUpdate)
|
||||||
|
// Redirect errors to crash sink
|
||||||
.doOnError(crash::tryEmitError)
|
.doOnError(crash::tryEmitError)
|
||||||
|
.onErrorResume(ex -> Mono.empty())
|
||||||
|
|
||||||
.doOnTerminate(updatesStreamEnd::tryEmitEmpty)
|
.doOnTerminate(updatesStreamEnd::tryEmitEmpty)
|
||||||
.publishOn(Schedulers.single());
|
.publishOn(Schedulers.single());
|
||||||
}
|
}
|
||||||
|
|
|
@ -88,7 +88,7 @@ public class AsyncTdMiddleDirect extends AbstractVerticle implements AsyncTdMidd
|
||||||
return td
|
return td
|
||||||
.receive(new AsyncTdDirectOptions(WAIT_DURATION, 100))
|
.receive(new AsyncTdDirectOptions(WAIT_DURATION, 100))
|
||||||
.takeUntilOther(closeRequest.asMono())
|
.takeUntilOther(closeRequest.asMono())
|
||||||
.doOnNext(s -> logger.trace("Received update from tdlib: {}", s))
|
.doOnNext(s -> logger.trace("Received update from tdlib: {}", s.getClass().getSimpleName()))
|
||||||
.doOnError(ex -> logger.info("TdMiddle verticle error", ex))
|
.doOnError(ex -> logger.info("TdMiddle verticle error", ex))
|
||||||
.doOnTerminate(() -> logger.debug("TdMiddle verticle stopped"))
|
.doOnTerminate(() -> logger.debug("TdMiddle verticle stopped"))
|
||||||
.subscribeOn(Schedulers.boundedElastic())
|
.subscribeOn(Schedulers.boundedElastic())
|
||||||
|
|
|
@ -141,15 +141,21 @@ public class AsyncTdMiddleEventBusServer extends AbstractVerticle {
|
||||||
executeConsumer.handler(sink::next);
|
executeConsumer.handler(sink::next);
|
||||||
executeConsumer.endHandler(h -> sink.complete());
|
executeConsumer.endHandler(h -> sink.complete());
|
||||||
})
|
})
|
||||||
.flatMapSequential(msg -> {
|
.flatMapSequential(msg -> Mono
|
||||||
logger.trace("Received execute request {}", msg.body());
|
.fromCallable(() -> Tuples.of(msg, msg.body()))
|
||||||
var request = overrideRequest(msg.body().getRequest(), botId);
|
.subscribeOn(Schedulers.boundedElastic())
|
||||||
|
)
|
||||||
|
.flatMapSequential(tuple -> {
|
||||||
|
var msg = tuple.getT1();
|
||||||
|
var body = tuple.getT2();
|
||||||
|
logger.trace("Received execute request {}", body);
|
||||||
|
var request = overrideRequest(body.getRequest(), botId);
|
||||||
return td
|
return td
|
||||||
.execute(request, msg.body().isExecuteDirectly())
|
.execute(request, body.isExecuteDirectly())
|
||||||
.map(result -> Tuples.of(msg, result))
|
.map(result -> Tuples.of(msg, result))
|
||||||
.doOnSuccess(s -> logger.trace("Executed successfully"));
|
.doOnSuccess(s -> logger.trace("Executed successfully"));
|
||||||
})
|
})
|
||||||
.handle((tuple, sink) -> {
|
.flatMapSequential(tuple -> Mono.fromCallable(() -> {
|
||||||
var msg = tuple.getT1();
|
var msg = tuple.getT1();
|
||||||
var response = tuple.getT2();
|
var response = tuple.getT2();
|
||||||
var replyOpts = new DeliveryOptions().setLocalOnly(local);
|
var replyOpts = new DeliveryOptions().setLocalOnly(local);
|
||||||
|
@ -157,13 +163,13 @@ public class AsyncTdMiddleEventBusServer extends AbstractVerticle {
|
||||||
try {
|
try {
|
||||||
logger.trace("Replying with success response");
|
logger.trace("Replying with success response");
|
||||||
msg.reply(replyValue, replyOpts);
|
msg.reply(replyValue, replyOpts);
|
||||||
sink.next(response);
|
return response;
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
logger.trace("Replying with error response: {}", ex.getLocalizedMessage());
|
logger.debug("Replying with error response: {}", ex.getLocalizedMessage());
|
||||||
msg.fail(500, ex.getLocalizedMessage());
|
msg.fail(500, ex.getLocalizedMessage());
|
||||||
sink.error(ex);
|
throw ex;
|
||||||
}
|
}
|
||||||
})
|
}).subscribeOn(Schedulers.boundedElastic()))
|
||||||
.then()
|
.then()
|
||||||
.publishOn(Schedulers.single())
|
.publishOn(Schedulers.single())
|
||||||
.subscribe(v -> {},
|
.subscribe(v -> {},
|
||||||
|
@ -214,7 +220,7 @@ public class AsyncTdMiddleEventBusServer extends AbstractVerticle {
|
||||||
})
|
})
|
||||||
.then()
|
.then()
|
||||||
.doOnSuccess(s -> logger.trace("Finished handling ready-to-receive requests (updates pipe ended)"))
|
.doOnSuccess(s -> logger.trace("Finished handling ready-to-receive requests (updates pipe ended)"))
|
||||||
.publishOn(Schedulers.single())
|
.subscribeOn(Schedulers.boundedElastic())
|
||||||
// Don't handle errors here. Handle them in pipeFlux
|
// Don't handle errors here. Handle them in pipeFlux
|
||||||
.subscribe(v -> {});
|
.subscribe(v -> {});
|
||||||
|
|
||||||
|
@ -228,12 +234,13 @@ public class AsyncTdMiddleEventBusServer extends AbstractVerticle {
|
||||||
pingConsumer.handler(sink::next);
|
pingConsumer.handler(sink::next);
|
||||||
pingConsumer.endHandler(h -> sink.complete());
|
pingConsumer.endHandler(h -> sink.complete());
|
||||||
})
|
})
|
||||||
.doOnNext(msg -> {
|
.flatMapSequential(msg -> Mono.fromCallable(() -> {
|
||||||
var opts = new DeliveryOptions().setLocalOnly(local).setSendTimeout(Duration.ofSeconds(10).toMillis());
|
var opts = new DeliveryOptions().setLocalOnly(local).setSendTimeout(Duration.ofSeconds(10).toMillis());
|
||||||
msg.reply(EMPTY, opts);
|
msg.reply(EMPTY, opts);
|
||||||
})
|
return null;
|
||||||
|
}))
|
||||||
.then()
|
.then()
|
||||||
.publishOn(Schedulers.single())
|
.subscribeOn(Schedulers.boundedElastic())
|
||||||
.subscribe(v -> {},
|
.subscribe(v -> {},
|
||||||
ex -> logger.error("Error when processing a ping request", ex),
|
ex -> logger.error("Error when processing a ping request", ex),
|
||||||
() -> logger.trace("Finished handling ping requests")
|
() -> logger.trace("Finished handling ping requests")
|
||||||
|
|
|
@ -261,23 +261,23 @@ public class MonoUtils {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T> Mono<Void> emitValue(One<T> sink, T value) {
|
public static <T> Mono<Void> emitValue(One<T> sink, T value) {
|
||||||
return fromEmitResult(sink.tryEmitValue(value));
|
return Mono.defer(() -> fromEmitResult(sink.tryEmitValue(value)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T> Mono<Void> emitNext(Many<T> sink, T value) {
|
public static <T> Mono<Void> emitNext(Many<T> sink, T value) {
|
||||||
return fromEmitResult(sink.tryEmitNext(value));
|
return Mono.defer(() -> fromEmitResult(sink.tryEmitNext(value)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T> Mono<Void> emitComplete(Many<T> sink) {
|
public static <T> Mono<Void> emitComplete(Many<T> sink) {
|
||||||
return fromEmitResult(sink.tryEmitComplete());
|
return Mono.defer(() -> fromEmitResult(sink.tryEmitComplete()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> Mono<Void> emitEmpty(Empty<T> sink) {
|
||||||
|
return Mono.defer(() -> fromEmitResult(sink.tryEmitEmpty()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T> Mono<Void> emitError(Empty<T> sink, Throwable value) {
|
public static <T> Mono<Void> emitError(Empty<T> sink, Throwable value) {
|
||||||
return fromEmitResult(sink.tryEmitError(value));
|
return Mono.defer(() -> fromEmitResult(sink.tryEmitError(value)));
|
||||||
}
|
|
||||||
|
|
||||||
public static <T> Future<Void> emitEmpty(Empty<T> sink) {
|
|
||||||
return fromEmitResultFuture(sink.tryEmitEmpty());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T> Future<Void> emitValueFuture(One<T> sink, T value) {
|
public static <T> Future<Void> emitValueFuture(One<T> sink, T value) {
|
||||||
|
@ -343,12 +343,13 @@ public class MonoUtils {
|
||||||
|
|
||||||
public static <T> Flux<T> fromConsumer(MessageConsumer<T> messageConsumer) {
|
public static <T> Flux<T> fromConsumer(MessageConsumer<T> messageConsumer) {
|
||||||
return Flux.<Message<T>>create(sink -> {
|
return Flux.<Message<T>>create(sink -> {
|
||||||
messageConsumer.handler(sink::next);
|
messageConsumer.handler(sink::next);
|
||||||
messageConsumer.endHandler(e -> sink.complete());
|
messageConsumer.endHandler(e -> sink.complete());
|
||||||
sink.onDispose(messageConsumer::unregister);
|
sink.onDispose(messageConsumer::unregister);
|
||||||
})
|
})
|
||||||
.subscribeOn(Schedulers.boundedElastic())
|
.startWith(MonoUtils.castVoid(messageConsumer.rxCompletionHandler().as(MonoUtils::toMono)))
|
||||||
.flatMapSequential(msg -> Mono.fromCallable(msg::body).subscribeOn(Schedulers.boundedElastic()));
|
.flatMapSequential(msg -> Mono.fromCallable(msg::body).subscribeOn(Schedulers.boundedElastic()))
|
||||||
|
.subscribeOn(Schedulers.boundedElastic());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class SinkRWStream<T> implements io.vertx.core.streams.WriteStream<T>, io.vertx.core.streams.ReadStream<T> {
|
public static class SinkRWStream<T> implements io.vertx.core.streams.WriteStream<T>, io.vertx.core.streams.ReadStream<T> {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user