Merge pull request #19371 from rjernst/plugin_components

Add components getter as bridge between guice and new plugin init world
This commit is contained in:
Ryan Ernst 2016-07-11 14:23:45 -07:00 committed by GitHub
commit 535b60cb2b
13 changed files with 81 additions and 38 deletions

View File

@ -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> pluginLifecycleComponents = pluginComponents.stream()
.filter(p -> p instanceof LifecycleComponent)
.map(p -> (LifecycleComponent)p).collect(Collectors.toList());
pluginLifecycleComponents.addAll(pluginsService.getGuiceServiceClasses().stream()
.map(injector::getInstance).collect(Collectors.toList()));
resourcesToClose.addAll(pluginLifecycleComponents);
transportService.start();
transportService.acceptIncomingRequests();
TransportClient transportClient = new TransportClient(injector, nodesService, proxy);
TransportClient transportClient = new TransportClient(injector, pluginLifecycleComponents, 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));

View File

@ -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.
@ -300,6 +303,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 +318,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> pluginLifecycleComponents = pluginComponents.stream()
.filter(p -> p instanceof LifecycleComponent)
.map(p -> (LifecycleComponent)p).collect(Collectors.toList());
pluginLifecycleComponents.addAll(pluginsService.getGuiceServiceClasses().stream()
.map(injector::getInstance).collect(Collectors.toList()));
resourcesToClose.addAll(pluginLifecycleComponents);
this.pluginLifecycleComponents = Collections.unmodifiableList(pluginLifecycleComponents);
client.intialize(injector.getInstance(new Key<Map<GenericAction, TransportAction>>() {}));
success = true;
@ -373,9 +386,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 +522,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 +586,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));

View File

@ -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();
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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());
}

View File

@ -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;
}

View File

@ -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());
}

View File

@ -49,7 +49,7 @@ public class MockEngineFactoryPlugin extends Plugin {
}
@Override
public Collection<Module> nodeModules() {
public Collection<Module> createGuiceModules() {
return Collections.singleton(new MockEngineReaderModule());
}

View File

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