Kick off ProjectReconcileSchedulers from within the bean

This commit is contained in:
aboyko
2023-01-25 22:58:23 -05:00
parent 8874e9c979
commit 17760fdceb
4 changed files with 42 additions and 61 deletions

View File

@@ -360,16 +360,15 @@ public class BootLanguageServerBootApp {
BootJavaProjectReconcilerScheduler bootJavaProjectReconcilerScheduler(SimpleLanguageServer server,
BootJavaReconcileEngine bootJavaReconciler, ProjectObserver projectObserver, BootJavaConfig config,
Optional<RewriteRecipeRepository> 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() {

View File

@@ -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<ICompletionEngine> 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()) {

View File

@@ -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<URI, Disposable> projectReconcileRequests = new ConcurrentHashMap<>();
private boolean started;
private final Scheduler projectReconcileScheduler;
private final Map<URI, Disposable> 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;
}
}

View File

@@ -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<String> 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);