From 9969c59e95314f3d1a84ede8c4964b840477e1cd Mon Sep 17 00:00:00 2001 From: "nsingh@pivotal.io" Date: Thu, 14 Nov 2019 13:56:02 -0800 Subject: [PATCH] PT 168776173 - Integrate progress service live hovers v2 Initial integration of progress service into live hovers v2. Added new API to make it cleared when progress for the same taskId can be done, and added progress reporting to SpringProcessConnectorService which can potentially be a long running progress if several retries on refresh are required. --- .../languageserver/ProgressService.java | 18 +++++++++++-- .../util/SimpleLanguageServer.java | 19 ++++++++----- .../BootJavaLanguageServerComponents.java | 2 +- .../v2/SpringProcessConnectorService.java | 27 +++++++++++++++++-- .../DefaultSpringPropertyIndexProvider.java | 3 +-- .../boot/metadata/PropertiesIndexTest.java | 4 +-- 6 files changed, 58 insertions(+), 15 deletions(-) diff --git a/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/ProgressService.java b/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/ProgressService.java index 0d1fd5959..3eaa7ccb8 100644 --- a/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/ProgressService.java +++ b/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/ProgressService.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2016-2017 Pivotal, Inc. + * Copyright (c) 2016-2019 Pivotal, Inc. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -11,9 +11,21 @@ package org.springframework.ide.vscode.commons.languageserver; -@FunctionalInterface public interface ProgressService { + public static ProgressService NO_PROGRESS = new ProgressService() { + + @Override + public void progressEvent(String taskId, String statusMsg) { + + } + + @Override + public void progressDone(String taskId) { + + } + }; + /** * Sends a progress event to the LSP client. A taskId is an arbirary id * that can be chosen by the caller. The purpose of the id is to be a 'unique' @@ -31,5 +43,7 @@ public interface ProgressService { * @param statusMsg */ void progressEvent(String taskId, String statusMsg); + + void progressDone(String taskId); } diff --git a/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/util/SimpleLanguageServer.java b/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/util/SimpleLanguageServer.java index 81acddabc..56fd33a0e 100644 --- a/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/util/SimpleLanguageServer.java +++ b/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/util/SimpleLanguageServer.java @@ -32,7 +32,6 @@ import org.eclipse.lsp4j.ApplyWorkspaceEditParams; import org.eclipse.lsp4j.ApplyWorkspaceEditResponse; import org.eclipse.lsp4j.ClientCapabilities; import org.eclipse.lsp4j.CodeLensOptions; -import org.eclipse.lsp4j.CompletionOptions; import org.eclipse.lsp4j.Diagnostic; import org.eclipse.lsp4j.DiagnosticSeverity; import org.eclipse.lsp4j.ExecuteCommandOptions; @@ -84,7 +83,6 @@ import org.springframework.ide.vscode.commons.util.CollectionUtil; import org.springframework.ide.vscode.commons.util.text.TextDocument; import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableList.Builder; import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonObject; @@ -118,10 +116,19 @@ public final class SimpleLanguageServer implements Sts4LanguageServer, LanguageC private STS4LanguageClient client; private final LanguageServerProperties props; - private ProgressService progressService = (String taskId, String statusMsg) -> { - STS4LanguageClient client = SimpleLanguageServer.this.client; - if (client!=null) { - client.progress(new ProgressParams(taskId, statusMsg)); + private ProgressService progressService = new ProgressService() { + + @Override + public void progressEvent(String taskId, String statusMsg) { + STS4LanguageClient client = SimpleLanguageServer.this.client; + if (client!=null) { + client.progress(new ProgressParams(taskId, statusMsg)); + } + } + + @Override + public void progressDone(String taskId) { + progressEvent(taskId, null); } }; diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/BootJavaLanguageServerComponents.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/BootJavaLanguageServerComponents.java index 547121bb7..e2785cf6f 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/BootJavaLanguageServerComponents.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/BootJavaLanguageServerComponents.java @@ -152,7 +152,7 @@ public class BootJavaLanguageServerComponents implements LanguageServerComponent // // central live data components (to coordinate live data flow) - liveDataService = new SpringProcessConnectorService(liveDataProvider); + liveDataService = new SpringProcessConnectorService(server.getProgressService(), liveDataProvider); // connect the live data provider with the hovers (for data extraction and live updates) hoverProvider = createHoverHandler(projectFinder, sourceLinks, liveDataProvider); diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/livehover/v2/SpringProcessConnectorService.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/livehover/v2/SpringProcessConnectorService.java index 1e8e3125d..fbbddd7da 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/livehover/v2/SpringProcessConnectorService.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/livehover/v2/SpringProcessConnectorService.java @@ -17,6 +17,7 @@ import java.util.concurrent.TimeUnit; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.ide.vscode.commons.languageserver.ProgressService; /** * @author Martin Lippert @@ -35,12 +36,15 @@ public class SpringProcessConnectorService { private final ConcurrentMap connectedSuccess; private final SpringProcessConnectionChangeListener connectorListener; + + private final ProgressService progressService; - public SpringProcessConnectorService(SpringProcessLiveDataProvider liveDataProvider) { + public SpringProcessConnectorService(ProgressService progressService, SpringProcessLiveDataProvider liveDataProvider) { this.liveDataProvider = liveDataProvider; this.scheduler = new ScheduledThreadPoolExecutor(10); this.connectors = new ConcurrentHashMap<>(); this.connectedSuccess = new ConcurrentHashMap<>(); + this.progressService = progressService; this.connectorListener = new SpringProcessConnectionChangeListener() { @Override @@ -140,11 +144,15 @@ public class SpringProcessConnectorService { } private void scheduleRefresh(String processKey, SpringProcessConnector connector, long delay, TimeUnit unit, int retryNo) { - log.info("schedule task to refresh data from process: " + processKey + " - retry no: " + retryNo); + String progressMessage = "Refreshing data from Spring process: " + processKey + " - retry no: " + retryNo; + log.info(progressMessage); this.scheduler.schedule(() -> { + String progressId = "uniqueId"; try { + progress(progressId, progressMessage); SpringProcessLiveData newLiveData = connector.refresh(); + if (newLiveData != null) { if (!this.liveDataProvider.add(processKey, newLiveData)) { this.liveDataProvider.update(processKey, newLiveData); @@ -152,18 +160,33 @@ public class SpringProcessConnectorService { this.connectedSuccess.put(processKey, true); } + progressDone(progressId); } catch (Exception e) { + log.info("problem occured during process live data refresh", e); if (retryNo < RETRY_MAX_NO) { scheduleRefresh(processKey, connector, RETRY_DELAY_IN_SECONDS, TimeUnit.SECONDS, retryNo + 1); } else { + progressDone(progressId); + disconnectProcess(processKey); } } }, delay, unit); } + private void progress(String taskId, String message) { + if (this.progressService != null) { + this.progressService.progressEvent(taskId, message); + } + } + + private void progressDone(String taskId) { + if (this.progressService != null) { + this.progressService.progressDone(taskId); + } + } } diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/metadata/DefaultSpringPropertyIndexProvider.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/metadata/DefaultSpringPropertyIndexProvider.java index f9c62a541..0e2f2defe 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/metadata/DefaultSpringPropertyIndexProvider.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/metadata/DefaultSpringPropertyIndexProvider.java @@ -19,7 +19,6 @@ import org.springframework.ide.vscode.commons.languageserver.ProgressService; import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder; import org.springframework.ide.vscode.commons.languageserver.java.ProjectObserver; import org.springframework.ide.vscode.commons.util.FileObserver; -import org.springframework.ide.vscode.commons.util.FuzzyMap; import org.springframework.ide.vscode.commons.util.text.IDocument; public class DefaultSpringPropertyIndexProvider implements SpringPropertyIndexProvider { @@ -29,7 +28,7 @@ public class DefaultSpringPropertyIndexProvider implements SpringPropertyIndexPr private Runnable changeHandler = null; - private ProgressService progressService = (id, msg) -> { /*ignore*/ }; + private ProgressService progressService = ProgressService.NO_PROGRESS; public DefaultSpringPropertyIndexProvider(JavaProjectFinder javaProjectFinder, ProjectObserver projectObserver, FileObserver fileObserver, ValueProviderRegistry valueProviders) { this.javaProjectFinder = javaProjectFinder; diff --git a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/metadata/PropertiesIndexTest.java b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/metadata/PropertiesIndexTest.java index b6bade0e3..1b499d737 100644 --- a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/metadata/PropertiesIndexTest.java +++ b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/metadata/PropertiesIndexTest.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2016, 2017 Pivotal, Inc. + * Copyright (c) 2016, 2019 Pivotal, Inc. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -31,7 +31,7 @@ public class PropertiesIndexTest { private static final String CUSTOM_PROPERTIES_PROJECT = "custom-properties-boot-project"; private ProjectsHarness projects = ProjectsHarness.INSTANCE; - private ProgressService progressService = (id, msg) -> { /*ignore*/ }; + private ProgressService progressService = ProgressService.NO_PROGRESS; @Test public void springStandardPropertyPresent_Maven() throws Exception {