-
Notifications
You must be signed in to change notification settings - Fork 1.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Feature/extensions] First draft of adding support for dynamically registering actions #4460
Changes from all commits
c1301cd
f2ceada
7aba611
57d6e84
540fa4b
5f6bc96
329ce48
2999239
748a09b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -32,6 +32,7 @@ | |
|
||
package org.opensearch.client.node; | ||
|
||
import org.opensearch.action.ActionModule; | ||
import org.opensearch.action.ActionType; | ||
import org.opensearch.action.ActionListener; | ||
import org.opensearch.action.ActionRequest; | ||
|
@@ -57,6 +58,7 @@ | |
*/ | ||
public class NodeClient extends AbstractClient { | ||
|
||
private ActionModule.ActionRegistry actionsRegistry; | ||
private Map<ActionType, TransportAction> actions; | ||
/** | ||
* The id of the local {@link DiscoveryNode}. Useful for generating task ids from tasks returned by | ||
|
@@ -72,11 +74,13 @@ public NodeClient(Settings settings, ThreadPool threadPool) { | |
|
||
public void initialize( | ||
Map<ActionType, TransportAction> actions, | ||
ActionModule.ActionRegistry actionsRegistry, | ||
Supplier<String> localNodeId, | ||
RemoteClusterService remoteClusterService, | ||
NamedWriteableRegistry namedWriteableRegistry | ||
) { | ||
this.actions = actions; | ||
this.actionsRegistry = actionsRegistry; | ||
this.localNodeId = localNodeId; | ||
this.remoteClusterService = remoteClusterService; | ||
this.namedWriteableRegistry = namedWriteableRegistry; | ||
|
@@ -137,6 +141,7 @@ public String getLocalNodeId() { | |
private <Request extends ActionRequest, Response extends ActionResponse> TransportAction<Request, Response> transportAction( | ||
ActionType<Response> action | ||
) { | ||
/* TODO add support to read actionsRegistry along with actions */ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we have an issue to track this TODO? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Haha I've taken care of this as part of SDK#106. |
||
if (actions == null) { | ||
throw new IllegalStateException("NodeClient has not been initialized"); | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
/* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
* | ||
* The OpenSearch Contributors require contributions made to | ||
* this file be licensed under the Apache-2.0 license or a | ||
* compatible open source license. | ||
*/ | ||
|
||
package org.opensearch.extensions.action; | ||
|
||
import org.opensearch.action.ActionType; | ||
|
||
public class ExtensionsAction extends ActionType<ExtensionsActionResponse> { | ||
public static final String NAME = "cluster:monitor/extension"; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should be keep the action name in the same format as There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sure makes sense. |
||
public static final ExtensionsAction INSTANCE = new ExtensionsAction(); | ||
|
||
public ExtensionsAction() { | ||
super(NAME, ExtensionsActionResponse::new); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
/* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
* | ||
* The OpenSearch Contributors require contributions made to | ||
* this file be licensed under the Apache-2.0 license or a | ||
* compatible open source license. | ||
*/ | ||
|
||
package org.opensearch.extensions.action; | ||
|
||
import org.opensearch.action.ActionRequest; | ||
import org.opensearch.action.ActionRequestValidationException; | ||
import org.opensearch.common.io.stream.StreamInput; | ||
import org.opensearch.common.io.stream.StreamOutput; | ||
|
||
import java.io.IOException; | ||
|
||
public class ExtensionsActionRequest extends ActionRequest { | ||
String firstRequest; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Leftover from draft PR? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Or is this a draft PR? Why is the first request so important to preserve? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. My bad, looks like I missed a commit during the rebase. |
||
|
||
public ExtensionsActionRequest(String firstRequest) { | ||
this.firstRequest = firstRequest; | ||
} | ||
|
||
ExtensionsActionRequest(StreamInput in) throws IOException { | ||
super(in); | ||
firstRequest = in.readString(); | ||
} | ||
|
||
@Override | ||
public void writeTo(StreamOutput out) throws IOException { | ||
super.writeTo(out); | ||
out.writeString(firstRequest); | ||
} | ||
|
||
@Override | ||
public ActionRequestValidationException validate() { | ||
return null; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
/* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
* | ||
* The OpenSearch Contributors require contributions made to | ||
* this file be licensed under the Apache-2.0 license or a | ||
* compatible open source license. | ||
*/ | ||
|
||
package org.opensearch.extensions.action; | ||
|
||
import org.opensearch.action.ActionResponse; | ||
import org.opensearch.common.io.stream.StreamInput; | ||
import org.opensearch.common.io.stream.StreamOutput; | ||
import org.opensearch.common.xcontent.ToXContentObject; | ||
import org.opensearch.common.xcontent.XContentBuilder; | ||
|
||
import java.io.IOException; | ||
|
||
public class ExtensionsActionResponse extends ActionResponse implements ToXContentObject { | ||
String myFirstResponse; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Looks like leftover from draft PR? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In #4519 I merged multiple similar "string response" classes into an I don't think the name I am also thinking we need to figure out a consistent naming convention. I am also seeing that we are very inconsistent in pluralization of |
||
|
||
ExtensionsActionResponse(String myFirstResponse) { | ||
this.myFirstResponse = myFirstResponse; | ||
} | ||
|
||
ExtensionsActionResponse(StreamInput in) throws IOException { | ||
super(in); | ||
myFirstResponse = in.readString(); | ||
} | ||
|
||
@Override | ||
public void writeTo(StreamOutput out) throws IOException { | ||
out.writeString(myFirstResponse); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I haven't dug into the implementation details, but when I see a All that to say, either add a |
||
} | ||
|
||
@Override | ||
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { | ||
return null; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What will eventually go here? I don't like seeing null returns, but a comment suggesting future usage would make me happier. |
||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
/* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
* | ||
* The OpenSearch Contributors require contributions made to | ||
* this file be licensed under the Apache-2.0 license or a | ||
* compatible open source license. | ||
*/ | ||
|
||
package org.opensearch.extensions.action; | ||
|
||
import org.opensearch.action.ActionListener; | ||
import org.opensearch.action.support.ActionFilters; | ||
import org.opensearch.action.support.HandledTransportAction; | ||
import org.opensearch.cluster.service.ClusterService; | ||
import org.opensearch.common.inject.Inject; | ||
import org.opensearch.common.settings.Settings; | ||
import org.opensearch.node.Node; | ||
import org.opensearch.tasks.Task; | ||
import org.opensearch.transport.TransportService; | ||
|
||
public class TransportExtensionsAction extends HandledTransportAction<ExtensionsActionRequest, ExtensionsActionResponse> { | ||
|
||
private final String nodeName; | ||
private final ClusterService clusterService; | ||
|
||
@Inject | ||
public TransportExtensionsAction( | ||
Settings settings, | ||
TransportService transportService, | ||
ActionFilters actionFilters, | ||
ClusterService clusterService | ||
) { | ||
super(ExtensionsAction.NAME, transportService, actionFilters, ExtensionsActionRequest::new); | ||
this.nodeName = Node.NODE_NAME_SETTING.get(settings); | ||
this.clusterService = clusterService; | ||
} | ||
|
||
@Override | ||
protected void doExecute(Task task, ExtensionsActionRequest request, ActionListener<ExtensionsActionResponse> listener) { | ||
listener.onResponse(new ExtensionsActionResponse("HelloWorld")); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -36,8 +36,13 @@ | |
import org.apache.logging.log4j.Logger; | ||
import org.apache.lucene.util.Constants; | ||
import org.apache.lucene.util.SetOnce; | ||
import org.opensearch.action.ActionType; | ||
import org.opensearch.action.support.TransportAction; | ||
import org.opensearch.common.inject.Key; | ||
import org.opensearch.common.util.FeatureFlags; | ||
import org.opensearch.cluster.routing.allocation.AwarenessReplicaBalance; | ||
import org.opensearch.extensions.action.ExtensionsAction; | ||
import org.opensearch.extensions.action.TransportExtensionsAction; | ||
import org.opensearch.index.IndexingPressureService; | ||
import org.opensearch.extensions.ExtensionsOrchestrator; | ||
//import org.opensearch.index.store.RemoteDirectoryFactory; | ||
|
@@ -54,12 +59,11 @@ | |
import org.opensearch.OpenSearchTimeoutException; | ||
import org.opensearch.Version; | ||
import org.opensearch.action.ActionModule; | ||
import org.opensearch.action.ActionType; | ||
import org.opensearch.action.ActionModule.ActionRegistry; | ||
import org.opensearch.action.admin.cluster.snapshots.status.TransportNodesSnapshotsStatus; | ||
import org.opensearch.action.search.SearchExecutionStatsCollector; | ||
import org.opensearch.action.search.SearchPhaseController; | ||
import org.opensearch.action.search.SearchTransportService; | ||
import org.opensearch.action.support.TransportAction; | ||
import org.opensearch.action.update.UpdateHelper; | ||
import org.opensearch.bootstrap.BootstrapCheck; | ||
import org.opensearch.bootstrap.BootstrapContext; | ||
|
@@ -92,7 +96,6 @@ | |
import org.opensearch.common.component.Lifecycle; | ||
import org.opensearch.common.component.LifecycleComponent; | ||
import org.opensearch.common.inject.Injector; | ||
import org.opensearch.common.inject.Key; | ||
import org.opensearch.common.inject.Module; | ||
import org.opensearch.common.inject.ModulesBuilder; | ||
import org.opensearch.common.io.stream.NamedWriteableRegistry; | ||
|
@@ -919,6 +922,7 @@ protected Node( | |
final PersistentTasksService persistentTasksService = new PersistentTasksService(clusterService, threadPool, client); | ||
|
||
modules.add(b -> { | ||
b.bind(ActionModule.class).toInstance(actionModule); | ||
b.bind(Node.class).toInstance(this); | ||
b.bind(NodeService.class).toInstance(nodeService); | ||
b.bind(NamedXContentRegistry.class).toInstance(xContentRegistry); | ||
|
@@ -1018,7 +1022,12 @@ protected Node( | |
resourcesToClose.add(injector.getInstance(PeerRecoverySourceService.class)); | ||
this.pluginLifecycleComponents = Collections.unmodifiableList(pluginLifecycleComponents); | ||
client.initialize(injector.getInstance(new Key<Map<ActionType, TransportAction>>() { | ||
}), () -> clusterService.localNode().getId(), transportService.getRemoteClusterService(), namedWriteableRegistry); | ||
}), | ||
injector.getInstance(ActionRegistry.class), | ||
() -> clusterService.localNode().getId(), | ||
transportService.getRemoteClusterService(), | ||
namedWriteableRegistry | ||
); | ||
this.namedWriteableRegistry = namedWriteableRegistry; | ||
|
||
logger.debug("initializing HTTP handlers ..."); | ||
|
@@ -1101,6 +1110,8 @@ public Node start() throws NodeValidationException { | |
nodeService.getMonitorService().start(); | ||
|
||
final ClusterService clusterService = injector.getInstance(ClusterService.class); | ||
final ActionModule actionModule = injector.getInstance(ActionModule.class); | ||
actionModule.registerAction(ExtensionsAction.INSTANCE, TransportExtensionsAction.class); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we have tests for There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thats a good point. |
||
|
||
final NodeConnectionsService nodeConnectionsService = injector.getInstance(NodeConnectionsService.class); | ||
nodeConnectionsService.start(); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
/* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
* | ||
* The OpenSearch Contributors require contributions made to | ||
* this file be licensed under the Apache-2.0 license or a | ||
* compatible open source license. | ||
*/ | ||
|
||
package org.opensearch.extensions.action; | ||
|
||
import org.opensearch.action.ActionFuture; | ||
import org.opensearch.test.OpenSearchSingleNodeTestCase; | ||
|
||
import java.util.concurrent.ExecutionException; | ||
|
||
public class ExtensionsActionTests extends OpenSearchSingleNodeTestCase { | ||
|
||
public void testExtensionAction() throws ExecutionException, InterruptedException { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. usually tests contain assertions of some sort. :) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yup I just realized I missed a commit :D |
||
ExtensionsActionRequest request = new ExtensionsActionRequest("MyFirstTransportRequest"); | ||
ActionFuture<ExtensionsActionResponse> execute = client().execute(ExtensionsAction.INSTANCE, request); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -96,7 +96,7 @@ protected void doExecute(Task task, ActionRequest request, ActionListener listen | |
final Map<ActionType, TransportAction> actions = new HashMap<>(); | ||
actions.put(ValidateQueryAction.INSTANCE, transportAction); | ||
|
||
client.initialize(actions, () -> "local", null, new NamedWriteableRegistry(Collections.emptyList())); | ||
client.initialize(actions, null, () -> "local", null, new NamedWriteableRegistry(Collections.emptyList())); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we create a dummy obj of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sure. |
||
controller.registerHandler(action); | ||
} | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Everything around this is
final
. Should this also be?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thats a good point. I was debating but it can be a final because the instance would not change.
Will update.