From d7ac7e286ca9bd61b1b1e38496b7b7badeed3146 Mon Sep 17 00:00:00 2001 From: Nikita Fedkin Date: Thu, 8 Sep 2022 22:36:17 +0300 Subject: [PATCH] =?UTF-8?q?=D0=9D=D0=B0=D1=82=D0=B8=D0=B2=D0=BD=D0=B0?= =?UTF-8?q?=D1=8F=20=D1=80=D0=B5=D0=B0=D0=BB=D0=B8=D0=B7=D0=B0=D1=86=D0=B8?= =?UTF-8?q?=D1=8F=20=D1=81=D0=BB=D0=B5=D0=B6=D0=B5=D0=BD=D0=B8=D1=8F=20?= =?UTF-8?q?=D0=B7=D0=B0=20=D0=BE=D0=BA=D0=BE=D0=BD=D1=87=D0=B0=D0=BD=D0=B8?= =?UTF-8?q?=D0=B5=D0=BC=20=D1=80=D0=B0=D0=B1=D0=BE=D1=82=D1=8B=20=D0=BF?= =?UTF-8?q?=D1=80=D0=BE=D1=86=D0=B5=D1=81=D1=81=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Убран spring scheduler, error заменен на warn --- .../languageserver/ParentProcessWatcher.java | 33 ++++++-------- .../ParentProcessWatcherTest.java | 44 ++++++++++++------- 2 files changed, 41 insertions(+), 36 deletions(-) diff --git a/src/main/java/com/github/_1c_syntax/bsl/languageserver/ParentProcessWatcher.java b/src/main/java/com/github/_1c_syntax/bsl/languageserver/ParentProcessWatcher.java index d91c544dc43..7fa71dfbaa0 100644 --- a/src/main/java/com/github/_1c_syntax/bsl/languageserver/ParentProcessWatcher.java +++ b/src/main/java/com/github/_1c_syntax/bsl/languageserver/ParentProcessWatcher.java @@ -26,9 +26,11 @@ import lombok.extern.slf4j.Slf4j; import org.eclipse.lsp4j.services.LanguageServer; import org.springframework.context.event.EventListener; -import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; +import javax.annotation.CheckForNull; +import java.util.Optional; + /** * Наблюдатель за жизнью родительского процесса, запустившего Language Server. */ @@ -38,7 +40,6 @@ public class ParentProcessWatcher { private final LanguageServer languageServer; - private long parentProcessId; /** * Обработчик события {@link LanguageServerInitializeRequestReceivedEvent}. @@ -49,29 +50,23 @@ public class ParentProcessWatcher { */ @EventListener public void handleEvent(LanguageServerInitializeRequestReceivedEvent event) { - var processId = event.getParams().getProcessId(); + @CheckForNull Integer processId = event.getParams().getProcessId(); if (processId == null) { return; } - parentProcessId = processId; - } - /** - * Фоновая процедура, отслеживающая родительский процесс. - */ - @Scheduled(fixedDelay = 30000L) - public void watch() { - if (parentProcessId == 0) { + // Can't register onExit callback on current process. + if (ProcessHandle.current().pid() == processId) { return; } - boolean processIsAlive = ProcessHandle.of(parentProcessId) - .map(ProcessHandle::isAlive) - .orElse(false); - - if (!processIsAlive) { - LOGGER.error("Parent process with pid {} is not found. Closing application...", parentProcessId); - languageServer.exit(); - } + Optional.of(processId) + .flatMap(ProcessHandle::of) + .map(ProcessHandle::onExit) + .ifPresent(onExitCallback -> onExitCallback.thenRun(() -> { + LOGGER.warn("Parent process with pid {} is not found. Closing application...", processId); + languageServer.exit(); + })); } + } diff --git a/src/test/java/com/github/_1c_syntax/bsl/languageserver/ParentProcessWatcherTest.java b/src/test/java/com/github/_1c_syntax/bsl/languageserver/ParentProcessWatcherTest.java index 11d7c3a0235..4501d23c518 100644 --- a/src/test/java/com/github/_1c_syntax/bsl/languageserver/ParentProcessWatcherTest.java +++ b/src/test/java/com/github/_1c_syntax/bsl/languageserver/ParentProcessWatcherTest.java @@ -25,53 +25,63 @@ import org.eclipse.lsp4j.InitializeParams; import org.eclipse.lsp4j.services.LanguageServer; import org.junit.jupiter.api.Test; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.springframework.boot.test.context.SpringBootTest; +import java.io.IOException; +import java.time.Duration; + +import static org.awaitility.Awaitility.await; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; -@SpringBootTest class ParentProcessWatcherTest { - @InjectMocks - private ParentProcessWatcher parentProcessWatcher; - - @Mock - private LanguageServer languageServer; - @Test - void testParentProcessIsDead() { + void testParentProcessIsDead() throws IOException, InterruptedException { // given + var languageServer = mock(LanguageServer.class); + var parentProcessWatcher = new ParentProcessWatcher(languageServer); + var params = new InitializeParams(); - params.setProcessId(-1); + var process = new ProcessBuilder("timeout", "2").start(); + var pid = process.pid(); + params.setProcessId((int) pid); var event = new LanguageServerInitializeRequestReceivedEvent(languageServer, params); parentProcessWatcher.handleEvent(event); // when - parentProcessWatcher.watch(); + process.waitFor(); // then - verify(languageServer, times(1)).exit(); + await() + .atMost(Duration.ofSeconds(1)) + .untilAsserted( + () -> verify(languageServer, times(1)).exit() + ); } @Test void testParentProcessIsAlive() { // given + var languageServer = mock(LanguageServer.class); + var parentProcessWatcher = new ParentProcessWatcher(languageServer); + var params = new InitializeParams(); params.setProcessId((int) ProcessHandle.current().pid()); var event = new LanguageServerInitializeRequestReceivedEvent(languageServer, params); - parentProcessWatcher.handleEvent(event); // when - parentProcessWatcher.watch(); + parentProcessWatcher.handleEvent(event); // then - verify(languageServer, never()).exit(); + await() + .atLeast(Duration.ofSeconds(1)) + .untilAsserted( + () -> verify(languageServer, never()).exit() + ); } } \ No newline at end of file