diff --git a/src/main/java/it/tdlight/common/internal/InternalClient.java b/src/main/java/it/tdlight/common/internal/InternalClient.java index 09a6f82..eb1f0c1 100644 --- a/src/main/java/it/tdlight/common/internal/InternalClient.java +++ b/src/main/java/it/tdlight/common/internal/InternalClient.java @@ -23,8 +23,11 @@ public final class InternalClient implements ClientEventsHandler, TelegramClient private static final Marker TG_MARKER = MarkerFactory.getMarker("TG"); private static final Logger logger = LoggerFactory.getLogger(TelegramClient.class); + private final ConcurrentHashMap handlers = new ConcurrentHashMap(); + private final Thread shutdownHook = new Thread(this::onJVMShutdown); + private volatile Integer clientId = null; private final InternalClientManager clientManager; private Handler updateHandler; @@ -35,6 +38,7 @@ public final class InternalClient implements ClientEventsHandler, TelegramClient public InternalClient(InternalClientManager clientManager) { this.clientManager = clientManager; + Runtime.getRuntime().addShutdownHook(shutdownHook); } @Override @@ -81,6 +85,11 @@ public final class InternalClient implements ClientEventsHandler, TelegramClient private void handleClose() { logger.trace(TG_MARKER, "Received close"); + try { + Runtime.getRuntime().removeShutdownHook(shutdownHook); + } catch (IllegalStateException ignored) { + logger.trace(TG_MARKER, "Can't remove shutdown hook because the JVM is already shutting down"); + } handlers.forEach((eventId, handler) -> { handleResponse(eventId, new Error(500, "Instance closed"), handler); }); @@ -181,6 +190,15 @@ public final class InternalClient implements ClientEventsHandler, TelegramClient return NativeClientAccess.execute(query); } + private void onJVMShutdown() { + try { + logger.info(TG_MARKER, "Client {} is shutting down because the JVM is shutting down", clientId); + this.send(new TdApi.Close(), result -> {}, ex -> {}); + } catch (Throwable ex) { + logger.debug("Failed to send shutdown request to session {}", clientId); + } + } + /** * * @param function function used to check if the check will be enforced or not. Can be null diff --git a/src/main/java/it/tdlight/common/internal/InternalReactiveClient.java b/src/main/java/it/tdlight/common/internal/InternalReactiveClient.java index f930740..079d533 100644 --- a/src/main/java/it/tdlight/common/internal/InternalReactiveClient.java +++ b/src/main/java/it/tdlight/common/internal/InternalReactiveClient.java @@ -38,6 +38,8 @@ public final class InternalReactiveClient implements ClientEventsHandler, Reacti private final ExceptionHandler defaultExceptionHandler; private final Handler updateHandler; + private final Thread shutdownHook = new Thread(this::onJVMShutdown); + private volatile Integer clientId = null; private final InternalClientManager clientManager; @@ -48,6 +50,7 @@ public final class InternalReactiveClient implements ClientEventsHandler, Reacti this.clientManager = clientManager; this.updateHandler = new Handler(this::onUpdateFromHandler, this::onUpdateException); this.defaultExceptionHandler = this::onDefaultException; + Runtime.getRuntime().addShutdownHook(shutdownHook); } @Override @@ -72,6 +75,12 @@ public final class InternalReactiveClient implements ClientEventsHandler, Reacti * This method will be called exactly once */ private void handleClose() { + logger.trace(TG_MARKER, "Received close"); + try { + Runtime.getRuntime().removeShutdownHook(shutdownHook); + } catch (IllegalStateException ignored) { + logger.trace(TG_MARKER, "Can't remove shutdown hook because the JVM is already shutting down"); + } TdApi.Error instanceClosedError = new Error(500, "Instance closed"); handlers.forEach((eventId, handler) -> this.handleResponse(eventId, instanceClosedError, handler)); handlers.clear(); @@ -90,6 +99,7 @@ public final class InternalReactiveClient implements ClientEventsHandler, Reacti if (signalListener != null) { signalListener.onSignal(Signal.ofClosed()); } + logger.info(TG_MARKER, "Client closed {}", clientId); } /** @@ -299,6 +309,15 @@ public final class InternalReactiveClient implements ClientEventsHandler, Reacti } } + private void onJVMShutdown() { + try { + logger.info(TG_MARKER, "Client {} is shutting down because the JVM is shutting down", clientId); + sendCloseAndIgnoreResponse(); + } catch (Throwable ex) { + logger.debug("Failed to send shutdown request to session {}", clientId); + } + } + /** * @param function function used to check if the check will be enforced or not. Can be null * @return true if closed