From 388cfe6a2d861ba7935b5883790dfefd2566b0f2 Mon Sep 17 00:00:00 2001 From: Tobias Ortmayr Date: Thu, 4 Nov 2021 16:25:29 +0100 Subject: [PATCH] #448 Implement dispatching of actions on next model-update (#141) * #448 Implement dispatching of actions on next model-update and update `WorkflowLayoutEngine` to dispatch a `CenterAction` after the next model update. Fixes https://github.com/eclipse-glsp/glsp/issues/448 * Address review feedback * Update jetty-bundles version Verson 4.14 no longer exists in p2 repository. Update to new 4.44 Version --- .../META-INF/MANIFEST.MF | 14 +++++++------- .../org.eclipse.glsp.server.websocket/pom.xml | 2 +- .../glsp/server/actions/ActionDispatcher.java | 10 ++++++++++ .../glsp/server/actions/SelectAction.java | 9 +++++++-- .../actions/DefaultActionDispatcher.java | 19 +++++++++++++++++++ .../gmodel/CreateNodeOperationHandler.java | 9 ++++++++- targetplatforms/r2021-03.target | 6 +++--- targetplatforms/r2021-03.tpd | 4 ++-- .../modelsourcewatcher/FileWatcherTest.java | 3 +++ 9 files changed, 60 insertions(+), 16 deletions(-) diff --git a/plugins/org.eclipse.glsp.server.websocket/META-INF/MANIFEST.MF b/plugins/org.eclipse.glsp.server.websocket/META-INF/MANIFEST.MF index 68f876cc..4c626eaa 100644 --- a/plugins/org.eclipse.glsp.server.websocket/META-INF/MANIFEST.MF +++ b/plugins/org.eclipse.glsp.server.websocket/META-INF/MANIFEST.MF @@ -7,15 +7,15 @@ Bundle-Vendor: Eclipse GLSP Automatic-Module-Name: com.eclipsesource.glps.server.websocket Bundle-RequiredExecutionEnvironment: JavaSE-11 Require-Bundle: javax.websocket;bundle-version="1.0.0";visibility:=reexport, - org.eclipse.jetty.server;bundle-version="9.4.14";visibility:=reexport, - org.eclipse.jetty.servlet;bundle-version="9.4.14";visibility:=reexport, - org.eclipse.jetty.util;bundle-version="9.4.14";visibility:=reexport, - org.eclipse.jetty.websocket.javax.websocket;bundle-version="9.4.14";visibility:=reexport, - org.eclipse.jetty.websocket.javax.websocket.server;bundle-version="9.4.14";visibility:=reexport, + org.eclipse.jetty.server;bundle-version="9.4.44";visibility:=reexport, + org.eclipse.jetty.servlet;bundle-version="9.4.44";visibility:=reexport, + org.eclipse.jetty.util;bundle-version="9.4.44";visibility:=reexport, + org.eclipse.jetty.websocket.javax.websocket;bundle-version="9.4.44";visibility:=reexport, + org.eclipse.jetty.websocket.javax.websocket.server;bundle-version="9.4.44";visibility:=reexport, org.eclipse.glsp.server;bundle-version="0.9.0", org.eclipse.lsp4j.websocket;bundle-version="0.9.0", - org.eclipse.jetty.webapp;bundle-version="9.4.14";visibility:=reexport, - org.eclipse.jetty.websocket.api;bundle-version="9.4.14";visibility:=reexport, + org.eclipse.jetty.webapp;bundle-version="9.4.44";visibility:=reexport, + org.eclipse.jetty.websocket.api;bundle-version="9.4.44";visibility:=reexport, com.google.gson, org.eclipse.lsp4j, org.eclipse.lsp4j.jsonrpc diff --git a/plugins/org.eclipse.glsp.server.websocket/pom.xml b/plugins/org.eclipse.glsp.server.websocket/pom.xml index c187425f..66c22f25 100644 --- a/plugins/org.eclipse.glsp.server.websocket/pom.xml +++ b/plugins/org.eclipse.glsp.server.websocket/pom.xml @@ -50,7 +50,7 @@ org.eclipse.jetty.websocket javax-websocket-server-impl - 9.4.14.v20181114 + 9.4.44.v20210927 org.eclipse.lsp4j diff --git a/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/actions/ActionDispatcher.java b/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/actions/ActionDispatcher.java index 974174aa..8acd8bd9 100644 --- a/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/actions/ActionDispatcher.java +++ b/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/actions/ActionDispatcher.java @@ -20,6 +20,7 @@ import java.util.stream.Collectors; import org.eclipse.glsp.server.disposable.IDisposable; +import org.eclipse.glsp.server.features.core.model.UpdateModelAction; public interface ActionDispatcher extends IDisposable { @@ -45,4 +46,13 @@ public interface ActionDispatcher extends IDisposable { default List> dispatchAll(final List actions) { return actions.stream().map(action -> dispatch(action)).collect(Collectors.toList()); } + + /** + * Processes all given actions, by dispatching them to the corresponding handlers, after the next model update. + * The given actions are queued until the next model update cycle has been completed i.e. an + * {@link UpdateModelAction} has been dispatched and processed by this action dispatcher. + * + * @param actions The actions that should be dispatched after the next model update + */ + void dispatchAfterNextUpdate(Action... actions); } diff --git a/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/actions/SelectAction.java b/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/actions/SelectAction.java index 70297f10..95ef783f 100644 --- a/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/actions/SelectAction.java +++ b/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/actions/SelectAction.java @@ -15,6 +15,7 @@ ******************************************************************************/ package org.eclipse.glsp.server.actions; +import java.util.ArrayList; import java.util.List; public class SelectAction extends Action { @@ -25,11 +26,15 @@ public class SelectAction extends Action { private List deselectedElementsIDs; public SelectAction() { - super(ID); + this(new ArrayList<>()); + } + + public SelectAction(final List selectedElementsIDs) { + this(selectedElementsIDs, new ArrayList<>()); } public SelectAction(final List selectedElementsIDs, final List deselectedElementsIDs) { - this(); + super(ID); this.selectedElementsIDs = selectedElementsIDs; this.deselectedElementsIDs = deselectedElementsIDs; } diff --git a/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/internal/actions/DefaultActionDispatcher.java b/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/internal/actions/DefaultActionDispatcher.java index 1eb701b9..6e1b8f01 100644 --- a/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/internal/actions/DefaultActionDispatcher.java +++ b/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/internal/actions/DefaultActionDispatcher.java @@ -16,6 +16,7 @@ package org.eclipse.glsp.server.internal.actions; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.List; @@ -35,6 +36,7 @@ import org.eclipse.glsp.server.actions.ResponseAction; import org.eclipse.glsp.server.di.ClientId; import org.eclipse.glsp.server.disposable.Disposable; +import org.eclipse.glsp.server.features.core.model.UpdateModelAction; import org.eclipse.glsp.server.protocol.GLSPClient; import org.eclipse.glsp.server.utils.FutureUtil; @@ -67,6 +69,8 @@ public class DefaultActionDispatcher extends Disposable implements ActionDispatc protected final BlockingQueue actionsQueue = new ArrayBlockingQueue<>(100, true); + protected List postUpdateQueue = new ArrayList<>(); + // Results will be placed in the map when the action dispatcher receives a new action (From arbitrary threads), // and will be removed from the dispatcher's thread. protected final Map> results = Collections.synchronizedMap(new HashMap<>()); @@ -100,6 +104,11 @@ public CompletableFuture dispatch(final Action action) { return result; } + @Override + public void dispatchAfterNextUpdate(final Action... actions) { + postUpdateQueue.addAll(Arrays.asList(actions)); + } + protected void addToQueue(final Action action) { if (Thread.currentThread() == this.thread) { LOG.error("Actions shouldn't be added to the actions queue from the dispatcher thread!"); @@ -183,10 +192,20 @@ protected List> runAction(final Action action) { .map(response -> ResponseAction.respond(action, response)) .collect(Collectors.toList()); results.addAll(dispatchAll(responses)); + if (action instanceof UpdateModelAction) { + results.add(dispatchPostUpdateQueue()); + } } return results; } + protected CompletableFuture dispatchPostUpdateQueue() { + ArrayList toDispatch = new ArrayList<>(postUpdateQueue); + postUpdateQueue.clear(); + dispatchAll(toDispatch); + return CompletableFuture.completedFuture(null); + } + protected final void checkThread() { if (Thread.currentThread() != thread) { throw new IllegalStateException( diff --git a/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/operations/gmodel/CreateNodeOperationHandler.java b/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/operations/gmodel/CreateNodeOperationHandler.java index 452ffb5d..f3e5a637 100644 --- a/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/operations/gmodel/CreateNodeOperationHandler.java +++ b/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/operations/gmodel/CreateNodeOperationHandler.java @@ -15,6 +15,7 @@ ********************************************************************************/ package org.eclipse.glsp.server.operations.gmodel; +import java.util.List; import java.util.Map; import java.util.Optional; @@ -25,9 +26,11 @@ import org.eclipse.glsp.graph.GNode; import org.eclipse.glsp.graph.GPoint; import org.eclipse.glsp.graph.util.GraphUtil; +import org.eclipse.glsp.server.actions.ActionDispatcher; +import org.eclipse.glsp.server.actions.SelectAction; import org.eclipse.glsp.server.model.GModelState; -import org.eclipse.glsp.server.operations.CreateNodeOperation; import org.eclipse.glsp.server.operations.AbstractCreateOperationHandler; +import org.eclipse.glsp.server.operations.CreateNodeOperation; import org.eclipse.glsp.server.utils.GeometryUtil; import com.google.inject.Inject; @@ -37,6 +40,9 @@ public abstract class CreateNodeOperationHandler extends AbstractCreateOperation @Inject protected GModelState modelState; + @Inject + protected ActionDispatcher actionDispatcher; + public CreateNodeOperationHandler(final String elementTypeId) { super(elementTypeId); } @@ -53,6 +59,7 @@ public void executeOperation(final CreateNodeOperation operation) { Optional relativeLocation = getRelativeLocation(operation, absoluteLocation, container); GModelElement element = createNode(relativeLocation, operation.getArgs()); container.get().getChildren().add(element); + actionDispatcher.dispatchAfterNextUpdate(new SelectAction(), new SelectAction(List.of(element.getId()))); } /** diff --git a/targetplatforms/r2021-03.target b/targetplatforms/r2021-03.target index a8dd8cc6..beaccffe 100644 --- a/targetplatforms/r2021-03.target +++ b/targetplatforms/r2021-03.target @@ -1,7 +1,7 @@ - + @@ -22,8 +22,8 @@ - - + + diff --git a/targetplatforms/r2021-03.tpd b/targetplatforms/r2021-03.tpd index 8340912b..626bfe44 100644 --- a/targetplatforms/r2021-03.tpd +++ b/targetplatforms/r2021-03.tpd @@ -18,8 +18,8 @@ location "https://download.eclipse.org/tools/orbit/downloads/drops/R202106020316 org.junit.jupiter.api [5.7.1,5.7.2) } -location "https://download.eclipse.org/jetty/updates/jetty-bundles-9.x/9.4.14.v20181113/" { - org.eclipse.jetty.bundles.f.feature.group +location "https://download.eclipse.org/jetty/updates/jetty-bundles-9.x/9.4.44.v20210927/" { + org.eclipse.jetty.bundles.f.feature.group } location "https://download.eclipse.org/elk/updates/releases/0.7.1/" { diff --git a/tests/org.eclipse.glsp.server.test/src/org/eclipse/glsp/server/features/modelsourcewatcher/FileWatcherTest.java b/tests/org.eclipse.glsp.server.test/src/org/eclipse/glsp/server/features/modelsourcewatcher/FileWatcherTest.java index be68f89f..00fa5810 100644 --- a/tests/org.eclipse.glsp.server.test/src/org/eclipse/glsp/server/features/modelsourcewatcher/FileWatcherTest.java +++ b/tests/org.eclipse.glsp.server.test/src/org/eclipse/glsp/server/features/modelsourcewatcher/FileWatcherTest.java @@ -201,6 +201,9 @@ public CompletableFuture dispatch(final Action action) { dispatchedActions.add(action); return CompletableFuture.completedFuture(null); } + + @Override + public void dispatchAfterNextUpdate(final Action... actions) {} } class MockClientSessionManager implements ClientSessionManager {