From 17760fdceb6ba2e76911587d8e1776d283f54502 Mon Sep 17 00:00:00 2001 From: aboyko Date: Wed, 25 Jan 2023 22:58:23 -0500 Subject: [PATCH] Kick off ProjectReconcileSchedulers from within the bean --- .../boot/app/BootLanguageServerBootApp.java | 7 ++-- .../app/BootLanguageServerInitializer.java | 34 ++++++--------- .../common/ProjectReconcileScheduler.java | 41 ++++++++----------- .../BootJavaProjectReconcilerScheduler.java | 21 ++++------ 4 files changed, 42 insertions(+), 61 deletions(-) diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/app/BootLanguageServerBootApp.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/app/BootLanguageServerBootApp.java index eb0d59a51..cfea0156e 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/app/BootLanguageServerBootApp.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/app/BootLanguageServerBootApp.java @@ -360,16 +360,15 @@ public class BootLanguageServerBootApp { BootJavaProjectReconcilerScheduler bootJavaProjectReconcilerScheduler(SimpleLanguageServer server, BootJavaReconcileEngine bootJavaReconciler, ProjectObserver projectObserver, BootJavaConfig config, Optional recipeRepoOpt, JavaProjectFinder projectFinder) { - return new BootJavaProjectReconcilerScheduler(bootJavaReconciler, - server.getWorkspaceService().getFileObserver(), projectObserver, config, recipeRepoOpt.orElse(null), - server.getTextDocumentService(), projectFinder); + return new BootJavaProjectReconcilerScheduler(bootJavaReconciler, projectObserver, config, + recipeRepoOpt.orElse(null), projectFinder, server); } @ConditionalOnMissingClass("org.springframework.ide.vscode.languageserver.testharness.LanguageServerHarness") @ConditionalOnProperty(prefix = "languageserver", name = "reconcile-only-opened-docs", havingValue = "false", matchIfMissing = true) @Bean ProjectReconcileScheduler bootVersionValidationScheduler(SimpleLanguageServer server, JavaProjectFinder projectFinder, BootJavaConfig config, ProjectObserver projectObserver) { - return new ProjectReconcileScheduler(new BootVersionValidationEngine(server, config, projectObserver, projectFinder), projectFinder) { + return new ProjectReconcileScheduler(server, new BootVersionValidationEngine(server, config, projectObserver, projectFinder), projectFinder) { @Override protected void init() { diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/app/BootLanguageServerInitializer.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/app/BootLanguageServerInitializer.java index 70c760c83..3750a97a2 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/app/BootLanguageServerInitializer.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/app/BootLanguageServerInitializer.java @@ -19,7 +19,6 @@ import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.context.ApplicationContext; -import org.springframework.ide.vscode.boot.common.ProjectReconcileScheduler; import org.springframework.ide.vscode.boot.factories.SpringFactoriesLanguageServerComponents; import org.springframework.ide.vscode.boot.java.BootJavaLanguageServerComponents; import org.springframework.ide.vscode.boot.java.links.JavaElementLocationProvider; @@ -68,7 +67,6 @@ public class BootLanguageServerInitializer implements InitializingBean { @Autowired(required = false) List completionEngines; @Autowired private JavaProjectFinder projectFinder; @Autowired(required = false) private RewriteRecipeRepository recipesRepo; - @Autowired(required = false) private ProjectReconcileScheduler[] reconcileSchedulers; @Qualifier("adHocProperties") @Autowired ProjectBasedPropertyIndexProvider adHocProperties; @@ -124,14 +122,6 @@ public class BootLanguageServerInitializer implements InitializingBean { builder.add(c); } - if (reconcileSchedulers != null) { - // Kick off project reconcile schedulers - for (ProjectReconcileScheduler scheduler : reconcileSchedulers) { - scheduler.start(); - server.onShutdown(() -> scheduler.stop()); - } - } - components = builder.build(server); final SimpleTextDocumentService documents = server.getTextDocumentService(); @@ -152,18 +142,20 @@ public class BootLanguageServerInitializer implements InitializingBean { components.getDocumentSymbolProvider().ifPresent(documents::onDocumentSymbol); - - if (recipesRepo != null) { - recipesRepo.onRecipesLoaded(v -> { - // Recipes will start loading only after config has been received. Therefore safe to start listening to config changes now - // and launch initial project reconcile since both config and recipes are present - startListeningToPerformReconcile(); + server.doOnInitialized(() -> { + if (recipesRepo != null) { + recipesRepo.onRecipesLoaded(v -> { + // Recipes will start loading only after config has been received. Therefore safe to start listening to config changes now + // and launch initial project reconcile since both config and recipes are present + startListeningToPerformReconcile(); + reconcile(); + }); + } else { + // Reconcile would occur as listeners will be receiving events + startListeningToPerformReconcile(); reconcile(); - }); - } else { - // Reconcile would occur as listeners will be receiving events - startListeningToPerformReconcile(); - } + } + }); server.onShutdown(() -> { for (TextDocument d : documents.getAll()) { diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/common/ProjectReconcileScheduler.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/common/ProjectReconcileScheduler.java index fafe58e32..1d4c9441f 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/common/ProjectReconcileScheduler.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/common/ProjectReconcileScheduler.java @@ -18,6 +18,7 @@ import java.util.concurrent.ConcurrentHashMap; import org.eclipse.lsp4j.TextDocumentIdentifier; import org.springframework.ide.vscode.commons.java.IJavaProject; import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder; +import org.springframework.ide.vscode.commons.languageserver.util.SimpleLanguageServer; import reactor.core.Disposable; import reactor.core.publisher.Mono; @@ -26,40 +27,30 @@ import reactor.core.scheduler.Schedulers; public abstract class ProjectReconcileScheduler { - private IJavaProjectReconcileEngine reconciler; - private JavaProjectFinder projectFinder; - private long debounce; + private final SimpleLanguageServer server; + private final IJavaProjectReconcileEngine reconciler; + private final JavaProjectFinder projectFinder; + private final long debounce; - private Scheduler projectReconcileScheduler; - private Map projectReconcileRequests = new ConcurrentHashMap<>(); - private boolean started; + private final Scheduler projectReconcileScheduler; + private final Map projectReconcileRequests = new ConcurrentHashMap<>(); - public ProjectReconcileScheduler(IJavaProjectReconcileEngine reconciler, JavaProjectFinder projectFinder, long debounce, int numberOFthreads) { + public ProjectReconcileScheduler(SimpleLanguageServer server, IJavaProjectReconcileEngine reconciler, JavaProjectFinder projectFinder, long debounce, int numberOFthreads) { + this.server = server; this.reconciler = reconciler; this.debounce = debounce; this.projectFinder = projectFinder; projectReconcileScheduler = Schedulers.newBoundedElastic(numberOFthreads, Integer.MAX_VALUE, "Project-Reconciler", 10); + + server.doOnInitialized(this::init); + server.onShutdown(this::dispose); } - public ProjectReconcileScheduler(IJavaProjectReconcileEngine reconciler, JavaProjectFinder projectFinder) { - this(reconciler, projectFinder, 500, 1); + public ProjectReconcileScheduler(SimpleLanguageServer server, IJavaProjectReconcileEngine reconciler, JavaProjectFinder projectFinder) { + this(server, reconciler, projectFinder, 500, 1); } - public final synchronized void start() { - if (!started) { - init(); - started = true; - } - } - - public final synchronized void stop() { - if (started) { - dispose(); - started = false; - } - } - protected void init() { } @@ -124,4 +115,8 @@ public abstract class ProjectReconcileScheduler { return projectFinder; } + public SimpleLanguageServer getServer() { + return server; + } + } diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/handlers/BootJavaProjectReconcilerScheduler.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/handlers/BootJavaProjectReconcilerScheduler.java index 2ac756840..023bcdc05 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/handlers/BootJavaProjectReconcilerScheduler.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/handlers/BootJavaProjectReconcilerScheduler.java @@ -24,28 +24,23 @@ import org.springframework.ide.vscode.commons.java.IClasspathUtil; import org.springframework.ide.vscode.commons.java.IJavaProject; import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder; import org.springframework.ide.vscode.commons.languageserver.java.ProjectObserver; -import org.springframework.ide.vscode.commons.languageserver.util.SimpleTextDocumentService; -import org.springframework.ide.vscode.commons.util.FileObserver; +import org.springframework.ide.vscode.commons.languageserver.util.SimpleLanguageServer; import org.springframework.ide.vscode.commons.util.text.TextDocument; public class BootJavaProjectReconcilerScheduler extends ProjectReconcileScheduler { - + private static final List FILES_TO_WATCH_GLOB = List.of("**/*.java"); private ProjectObserver projectObserver; private BootJavaConfig config; private RewriteRecipeRepository recipesRepo; - private FileObserver fileObserver; - private SimpleTextDocumentService documents; - public BootJavaProjectReconcilerScheduler(IJavaProjectReconcileEngine reconciler, FileObserver fileObserver, ProjectObserver projectObserver, - BootJavaConfig config, RewriteRecipeRepository recipesRepo, SimpleTextDocumentService documents, JavaProjectFinder projectFinder) { - super(reconciler, projectFinder); - this.fileObserver = fileObserver; + public BootJavaProjectReconcilerScheduler(IJavaProjectReconcileEngine reconciler, ProjectObserver projectObserver, + BootJavaConfig config, RewriteRecipeRepository recipesRepo, JavaProjectFinder projectFinder, SimpleLanguageServer server) { + super(server, reconciler, projectFinder); this.projectObserver = projectObserver; this.config = config; this.recipesRepo = recipesRepo; - this.documents = documents; } @Override @@ -86,8 +81,8 @@ public class BootJavaProjectReconcilerScheduler extends ProjectReconcileSchedule } }); - fileObserver.onFilesChanged(FILES_TO_WATCH_GLOB, this::handleFiles); - fileObserver.onFilesCreated(FILES_TO_WATCH_GLOB, this::handleFiles); + getServer().getWorkspaceService().getFileObserver().onFilesChanged(FILES_TO_WATCH_GLOB, this::handleFiles); + getServer().getWorkspaceService().getFileObserver().onFilesCreated(FILES_TO_WATCH_GLOB, this::handleFiles); // TODO: index update even happens on every file save. Very expensive to blindly reconcile all projects. // Need to figure out a check if spring index has any changes @@ -98,7 +93,7 @@ public class BootJavaProjectReconcilerScheduler extends ProjectReconcileSchedule for (String f : files) { URI uri = URI.create(f); TextDocumentIdentifier docId = new TextDocumentIdentifier(uri.toASCIIString()); - TextDocument doc = documents.getLatestSnapshot(docId.getUri()); + TextDocument doc = getServer().getTextDocumentService().getLatestSnapshot(docId.getUri()); if (doc == null) { getProjectFinder().find(docId).ifPresent(project -> { Path p = Paths.get(uri);