Plugins: Add components creator as bridge between guice and new plugin init world
This change adds a createComponents() method to Plugin implementations which they can use to return already constructed componenents/services. Eventually this should be just services ("components" don't really do anything), but for now it allows any object so that preconstructed instances by plugins can still be bound to guice. Over time we should add basic services as arguments to this method, but for now I have left it empty so as to not presume what is a necessary service.
This commit is contained in:
parent
47bd2f9ca5
commit
99ac65931a
|
@ -21,6 +21,8 @@ package org.elasticsearch.client.transport;
|
|||
|
||||
import java.io.Closeable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
|
@ -154,11 +156,13 @@ public class TransportClient extends AbstractClient {
|
|||
resourcesToClose.add(circuitBreakerService);
|
||||
BigArrays bigArrays = new BigArrays(settings, circuitBreakerService);
|
||||
resourcesToClose.add(bigArrays);
|
||||
Collection<Object> pluginComponents = pluginsService.createComponenents();
|
||||
modules.add(settingsModule);
|
||||
modules.add((b -> {
|
||||
b.bind(BigArrays.class).toInstance(bigArrays);
|
||||
b.bind(PluginsService.class).toInstance(pluginsService);
|
||||
b.bind(CircuitBreakerService.class).toInstance(circuitBreakerService);
|
||||
pluginComponents.stream().forEach(p -> b.bind((Class)p.getClass()).toInstance(p));
|
||||
}));
|
||||
|
||||
Injector injector = modules.createInjector();
|
||||
|
@ -168,9 +172,17 @@ public class TransportClient extends AbstractClient {
|
|||
final TransportProxyClient proxy = new TransportProxyClient(settings, transportService, nodesService,
|
||||
actionModule.getActions().values().stream().map(x -> x.getAction()).collect(Collectors.toList()));
|
||||
|
||||
List<LifecycleComponent> pluginLifecycles = pluginComponents.stream()
|
||||
.filter(p -> p instanceof LifecycleComponent)
|
||||
.map(p -> (LifecycleComponent)p).collect(Collectors.toList());
|
||||
pluginLifecycles.addAll(pluginsService.getGuiceServiceClasses().stream()
|
||||
.map(injector::getInstance).collect(Collectors.toList()));
|
||||
resourcesToClose.addAll(pluginLifecycles);
|
||||
|
||||
transportService.start();
|
||||
transportService.acceptIncomingRequests();
|
||||
TransportClient transportClient = new TransportClient(injector, nodesService, proxy);
|
||||
|
||||
TransportClient transportClient = new TransportClient(injector, pluginLifecycles, nodesService, proxy);
|
||||
resourcesToClose.clear();
|
||||
return transportClient;
|
||||
} finally {
|
||||
|
@ -183,12 +195,15 @@ public class TransportClient extends AbstractClient {
|
|||
|
||||
final Injector injector;
|
||||
|
||||
private final List<LifecycleComponent> pluginLifecycleComponents;
|
||||
private final TransportClientNodesService nodesService;
|
||||
private final TransportProxyClient proxy;
|
||||
|
||||
private TransportClient(Injector injector, TransportClientNodesService nodesService, TransportProxyClient proxy) {
|
||||
private TransportClient(Injector injector, List<LifecycleComponent> pluginLifecycleComponents,
|
||||
TransportClientNodesService nodesService, TransportProxyClient proxy) {
|
||||
super(injector.getInstance(Settings.class), injector.getInstance(ThreadPool.class));
|
||||
this.injector = injector;
|
||||
this.pluginLifecycleComponents = Collections.unmodifiableList(pluginLifecycleComponents);
|
||||
this.nodesService = nodesService;
|
||||
this.proxy = proxy;
|
||||
}
|
||||
|
@ -269,8 +284,8 @@ public class TransportClient extends AbstractClient {
|
|||
closeables.add(nodesService);
|
||||
closeables.add(injector.getInstance(TransportService.class));
|
||||
|
||||
for (Class<? extends LifecycleComponent> plugin : injector.getInstance(PluginsService.class).nodeServices()) {
|
||||
closeables.add(injector.getInstance(plugin));
|
||||
for (LifecycleComponent plugin : pluginLifecycleComponents) {
|
||||
closeables.add(plugin);
|
||||
}
|
||||
closeables.add(() -> ThreadPool.terminate(injector.getInstance(ThreadPool.class), 10, TimeUnit.SECONDS));
|
||||
closeables.add(injector.getInstance(BigArrays.class));
|
||||
|
|
|
@ -132,6 +132,8 @@ import java.util.Map;
|
|||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* A node represent a node within a cluster (<tt>cluster.name</tt>). The {@link #client()} can be used
|
||||
|
@ -182,6 +184,7 @@ public class Node implements Closeable {
|
|||
private final NodeEnvironment nodeEnvironment;
|
||||
private final PluginsService pluginsService;
|
||||
private final NodeClient client;
|
||||
private final Collection<LifecycleComponent> pluginLifecycleComponents;
|
||||
|
||||
/**
|
||||
* Constructs a node with the given settings.
|
||||
|
@ -192,6 +195,7 @@ public class Node implements Closeable {
|
|||
this(InternalSettingsPreparer.prepareEnvironment(preparedSettings, null), Collections.<Class<? extends Plugin>>emptyList());
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected Node(Environment tmpEnv, Collection<Class<? extends Plugin>> classpathPlugins) {
|
||||
Settings tmpSettings = Settings.builder().put(tmpEnv.settings())
|
||||
.put(Client.CLIENT_TYPE_SETTING_S.getKey(), CLIENT_TYPE).build();
|
||||
|
@ -300,6 +304,7 @@ public class Node implements Closeable {
|
|||
resourcesToClose.add(bigArrays);
|
||||
modules.add(settingsModule);
|
||||
client = new NodeClient(settings, threadPool);
|
||||
Collection<Object> pluginComponents = pluginsService.createComponenents();
|
||||
modules.add(b -> {
|
||||
b.bind(PluginsService.class).toInstance(pluginsService);
|
||||
b.bind(Client.class).toInstance(client);
|
||||
|
@ -314,10 +319,19 @@ public class Node implements Closeable {
|
|||
b.bind(ScriptService.class).toInstance(scriptModule.getScriptService());
|
||||
b.bind(AnalysisRegistry.class).toInstance(analysisModule.getAnalysisRegistry());
|
||||
b.bind(IngestService.class).toInstance(ingestService);
|
||||
pluginComponents.stream().forEach(p -> b.bind((Class)p.getClass()).toInstance(p));
|
||||
}
|
||||
);
|
||||
injector = modules.createInjector();
|
||||
|
||||
List<LifecycleComponent> pluginLifecycles = pluginComponents.stream()
|
||||
.filter(p -> p instanceof LifecycleComponent)
|
||||
.map(p -> (LifecycleComponent)p).collect(Collectors.toList());
|
||||
pluginLifecycles.addAll(pluginsService.getGuiceServiceClasses().stream()
|
||||
.map(injector::getInstance).collect(Collectors.toList()));
|
||||
resourcesToClose.addAll(pluginLifecycles);
|
||||
pluginLifecycleComponents = Collections.unmodifiableList(pluginLifecycles);
|
||||
|
||||
client.intialize(injector.getInstance(new Key<Map<GenericAction, TransportAction>>() {}));
|
||||
|
||||
success = true;
|
||||
|
@ -373,9 +387,7 @@ public class Node implements Closeable {
|
|||
logger.info("starting ...");
|
||||
// hack around dependency injection problem (for now...)
|
||||
injector.getInstance(Discovery.class).setAllocationService(injector.getInstance(AllocationService.class));
|
||||
for (Class<? extends LifecycleComponent> plugin : pluginsService.nodeServices()) {
|
||||
injector.getInstance(plugin).start();
|
||||
}
|
||||
pluginLifecycleComponents.forEach(LifecycleComponent::start);
|
||||
|
||||
injector.getInstance(MappingUpdatedAction.class).setClient(client);
|
||||
injector.getInstance(IndicesService.class).start();
|
||||
|
@ -511,9 +523,7 @@ public class Node implements Closeable {
|
|||
injector.getInstance(RestController.class).stop();
|
||||
injector.getInstance(TransportService.class).stop();
|
||||
|
||||
for (Class<? extends LifecycleComponent> plugin : pluginsService.nodeServices()) {
|
||||
injector.getInstance(plugin).stop();
|
||||
}
|
||||
pluginLifecycleComponents.forEach(LifecycleComponent::stop);
|
||||
// we should stop this last since it waits for resources to get released
|
||||
// if we had scroll searchers etc or recovery going on we wait for to finish.
|
||||
injector.getInstance(IndicesService.class).stop();
|
||||
|
@ -577,9 +587,9 @@ public class Node implements Closeable {
|
|||
toClose.add(() -> stopWatch.stop().start("transport"));
|
||||
toClose.add(injector.getInstance(TransportService.class));
|
||||
|
||||
for (Class<? extends LifecycleComponent> plugin : pluginsService.nodeServices()) {
|
||||
toClose.add(() -> stopWatch.stop().start("plugin(" + plugin.getName() + ")"));
|
||||
toClose.add(injector.getInstance(plugin));
|
||||
for (LifecycleComponent plugin : pluginLifecycleComponents) {
|
||||
toClose.add(() -> stopWatch.stop().start("plugin(" + plugin.getClass().getName() + ")"));
|
||||
toClose.add(plugin);
|
||||
}
|
||||
toClose.addAll(pluginsService.filterPlugins(Closeable.class));
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
package org.elasticsearch.plugins;
|
||||
|
||||
import org.elasticsearch.action.ActionModule;
|
||||
import org.elasticsearch.common.component.AbstractComponent;
|
||||
import org.elasticsearch.common.component.LifecycleComponent;
|
||||
import org.elasticsearch.common.inject.Module;
|
||||
import org.elasticsearch.common.settings.Setting;
|
||||
|
@ -43,16 +44,28 @@ import java.util.List;
|
|||
public abstract class Plugin {
|
||||
|
||||
/**
|
||||
* Node level modules.
|
||||
* Node level guice modules.
|
||||
*/
|
||||
public Collection<Module> nodeModules() {
|
||||
public Collection<Module> createGuiceModules() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
/**
|
||||
* Node level services that will be automatically started/stopped/closed.
|
||||
* Node level services that will be automatically started/stopped/closed. This classes must be constructed
|
||||
* by injection with guice.
|
||||
*/
|
||||
public Collection<Class<? extends LifecycleComponent>> nodeServices() {
|
||||
public Collection<Class<? extends LifecycleComponent>> getGuiceServiceClasses() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns components maintained by this plugin.
|
||||
*
|
||||
* Any components returned that implement {@link LifecycleComponent} will have their lifecycle managed.
|
||||
* Note: To aid in the migration away from guice, all objects returned as components will be bound in guice
|
||||
* to themselves.
|
||||
*/
|
||||
public Collection<Object> createComponents() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
|
|
|
@ -39,13 +39,7 @@ import org.elasticsearch.common.logging.Loggers;
|
|||
import org.elasticsearch.common.settings.Setting;
|
||||
import org.elasticsearch.common.settings.Setting.Property;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.settings.SettingsModule;
|
||||
import org.elasticsearch.index.IndexModule;
|
||||
import org.elasticsearch.indices.analysis.AnalysisModule;
|
||||
import org.elasticsearch.script.NativeScriptFactory;
|
||||
import org.elasticsearch.script.ScriptContext;
|
||||
import org.elasticsearch.script.ScriptEngineService;
|
||||
import org.elasticsearch.script.ScriptModule;
|
||||
import org.elasticsearch.threadpool.ExecutorBuilder;
|
||||
|
||||
import java.io.IOException;
|
||||
|
@ -274,10 +268,16 @@ public class PluginsService extends AbstractComponent {
|
|||
return builder.put(this.settings).build();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public Collection<Module> nodeModules() {
|
||||
List<Module> modules = new ArrayList<>();
|
||||
for (Tuple<PluginInfo, Plugin> plugin : plugins) {
|
||||
modules.addAll(plugin.v2().nodeModules());
|
||||
modules.addAll(plugin.v2().createGuiceModules());
|
||||
modules.add(b -> {
|
||||
for (Object c : plugin.v2().createComponents()) {
|
||||
b.bind((Class)c.getClass()).toInstance(c);
|
||||
}
|
||||
});
|
||||
}
|
||||
return modules;
|
||||
}
|
||||
|
@ -290,14 +290,20 @@ public class PluginsService extends AbstractComponent {
|
|||
return builders;
|
||||
}
|
||||
|
||||
public Collection<Class<? extends LifecycleComponent>> nodeServices() {
|
||||
/** Returns all classes injected into guice by plugins which extend {@link LifecycleComponent}. */
|
||||
public Collection<Class<? extends LifecycleComponent>> getGuiceServiceClasses() {
|
||||
List<Class<? extends LifecycleComponent>> services = new ArrayList<>();
|
||||
for (Tuple<PluginInfo, Plugin> plugin : plugins) {
|
||||
services.addAll(plugin.v2().nodeServices());
|
||||
services.addAll(plugin.v2().getGuiceServiceClasses());
|
||||
}
|
||||
return services;
|
||||
}
|
||||
|
||||
/** Gets components from each plugin. This method should be called exactly once. */
|
||||
public Collection<Object> createComponenents() {
|
||||
return plugins.stream().flatMap(p -> p.v2().createComponents().stream()).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public void onIndexModule(IndexModule indexModule) {
|
||||
for (Tuple<PluginInfo, Plugin> plugin : plugins) {
|
||||
plugin.v2().onIndexModule(indexModule);
|
||||
|
|
|
@ -579,7 +579,7 @@ public class ClusterServiceIT extends ESIntegTestCase {
|
|||
public static class TestPlugin extends Plugin {
|
||||
|
||||
@Override
|
||||
public Collection<Class<? extends LifecycleComponent>> nodeServices() {
|
||||
public Collection<Class<? extends LifecycleComponent>> getGuiceServiceClasses() {
|
||||
List<Class<? extends LifecycleComponent>> services = new ArrayList<>(1);
|
||||
services.add(MasterAwareService.class);
|
||||
return services;
|
||||
|
|
|
@ -60,7 +60,7 @@ public class SettingsListenerIT extends ESIntegTestCase {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Collection<Module> nodeModules() {
|
||||
public Collection<Module> createGuiceModules() {
|
||||
return Collections.<Module>singletonList(new SettingsListenerModule(service));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -51,7 +51,7 @@ public class AzureDiscoveryPlugin extends Plugin {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Collection<Module> nodeModules() {
|
||||
public Collection<Module> createGuiceModules() {
|
||||
return Collections.singletonList((Module) new AzureDiscoveryModule(settings));
|
||||
}
|
||||
|
||||
|
|
|
@ -86,7 +86,7 @@ public class Ec2DiscoveryPlugin extends Plugin {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Collection<Module> nodeModules() {
|
||||
public Collection<Module> createGuiceModules() {
|
||||
Collection<Module> modules = new ArrayList<>();
|
||||
modules.add(new Ec2Module());
|
||||
return modules;
|
||||
|
@ -94,7 +94,7 @@ public class Ec2DiscoveryPlugin extends Plugin {
|
|||
|
||||
@Override
|
||||
@SuppressWarnings("rawtypes") // Supertype uses rawtype
|
||||
public Collection<Class<? extends LifecycleComponent>> nodeServices() {
|
||||
public Collection<Class<? extends LifecycleComponent>> getGuiceServiceClasses() {
|
||||
Collection<Class<? extends LifecycleComponent>> services = new ArrayList<>();
|
||||
services.add(AwsEc2ServiceImpl.class);
|
||||
return services;
|
||||
|
|
|
@ -70,13 +70,13 @@ public class GceDiscoveryPlugin extends Plugin {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Collection<Module> nodeModules() {
|
||||
public Collection<Module> createGuiceModules() {
|
||||
return Collections.singletonList(new GceModule());
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("rawtypes") // Supertype uses raw type
|
||||
public Collection<Class<? extends LifecycleComponent>> nodeServices() {
|
||||
public Collection<Class<? extends LifecycleComponent>> getGuiceServiceClasses() {
|
||||
return Collections.singletonList(GceModule.getComputeServiceImpl());
|
||||
}
|
||||
|
||||
|
|
|
@ -44,13 +44,13 @@ public class JvmExamplePlugin extends Plugin {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Collection<Module> nodeModules() {
|
||||
public Collection<Module> createGuiceModules() {
|
||||
return Collections.<Module>singletonList(new ConfiguredExampleModule());
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("rawtypes") // Plugin use a rawtype
|
||||
public Collection<Class<? extends LifecycleComponent>> nodeServices() {
|
||||
public Collection<Class<? extends LifecycleComponent>> getGuiceServiceClasses() {
|
||||
Collection<Class<? extends LifecycleComponent>> services = new ArrayList<>();
|
||||
return services;
|
||||
}
|
||||
|
|
|
@ -292,7 +292,7 @@ public class ContextAndHeaderTransportIT extends ESIntegTestCase {
|
|||
public static class ActionLoggingPlugin extends Plugin implements ActionPlugin {
|
||||
|
||||
@Override
|
||||
public Collection<Module> nodeModules() {
|
||||
public Collection<Module> createGuiceModules() {
|
||||
return Collections.<Module>singletonList(new ActionLoggingModule());
|
||||
}
|
||||
|
||||
|
|
|
@ -49,7 +49,7 @@ public class MockEngineFactoryPlugin extends Plugin {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Collection<Module> nodeModules() {
|
||||
public Collection<Module> createGuiceModules() {
|
||||
return Collections.singleton(new MockEngineReaderModule());
|
||||
}
|
||||
|
||||
|
|
|
@ -70,7 +70,7 @@ public final class MockIndexEventListener {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Collection<Module> nodeModules() {
|
||||
public Collection<Module> createGuiceModules() {
|
||||
return Collections.singleton(binder -> binder.bind(TestEventListener.class).toInstance(listener));
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue