Move lazy initialization classes from Watcher to XPack
This commit moves the InitializingModule and InitializingService classes in the common XPack package so that it can be used by any plugin. It also renames the module and service from Initializing* to LazyInitializing* and add a ClientProxy class. Original commit: elastic/x-pack-elasticsearch@fbdf9d1614
This commit is contained in:
parent
0f905e9b00
commit
62ad9f4f0d
|
@ -22,6 +22,8 @@ import org.elasticsearch.plugins.Plugin;
|
|||
import org.elasticsearch.script.ScriptModule;
|
||||
import org.elasticsearch.shield.Shield;
|
||||
import org.elasticsearch.watcher.Watcher;
|
||||
import org.elasticsearch.xpack.common.init.LazyInitializationModule;
|
||||
import org.elasticsearch.xpack.common.init.LazyInitializationService;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.security.AccessController;
|
||||
|
@ -89,6 +91,7 @@ public class XPackPlugin extends Plugin {
|
|||
@Override
|
||||
public Collection<Module> nodeModules() {
|
||||
ArrayList<Module> modules = new ArrayList<>();
|
||||
modules.add(new LazyInitializationModule());
|
||||
modules.addAll(licensing.nodeModules());
|
||||
modules.addAll(shield.nodeModules());
|
||||
modules.addAll(watcher.nodeModules());
|
||||
|
@ -99,6 +102,10 @@ public class XPackPlugin extends Plugin {
|
|||
@Override
|
||||
public Collection<Class<? extends LifecycleComponent>> nodeServices() {
|
||||
ArrayList<Class<? extends LifecycleComponent>> services = new ArrayList<>();
|
||||
// the initialization service must be first in the list
|
||||
// as other services may depend on one of the initialized
|
||||
// constructs
|
||||
services.add(LazyInitializationService.class);
|
||||
services.addAll(licensing.nodeServices());
|
||||
services.addAll(shield.nodeServices());
|
||||
services.addAll(watcher.nodeServices());
|
||||
|
@ -145,6 +152,10 @@ public class XPackPlugin extends Plugin {
|
|||
shield.onIndexModule(module);
|
||||
}
|
||||
|
||||
public void onModule(LazyInitializationModule module) {
|
||||
watcher.onModule(module);
|
||||
}
|
||||
|
||||
public static boolean transportClientMode(Settings settings) {
|
||||
return !"node".equals(settings.get(Client.CLIENT_TYPE_SETTING_S.getKey()));
|
||||
}
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
package org.elasticsearch.xpack.common.init;
|
||||
|
||||
import org.elasticsearch.common.inject.Injector;
|
||||
|
||||
public interface LazyInitializable {
|
||||
|
||||
/**
|
||||
* This method is called once all objects have been constructed and
|
||||
* the @{link LazyInitializationService} has been started.
|
||||
*/
|
||||
void init(Injector injector);
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
package org.elasticsearch.xpack.common.init;
|
||||
|
||||
import org.elasticsearch.common.inject.AbstractModule;
|
||||
import org.elasticsearch.common.inject.multibindings.Multibinder;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* A module to lazy initialize objects and avoid circular dependency injection issues.
|
||||
*
|
||||
* Objects that use the {@link org.elasticsearch.client.ElasticsearchClient} and that are also injected in transport actions provoke
|
||||
* a circular dependency injection issues with Guice. Using proxies with lazy initialization is a way to solve this issue.
|
||||
*
|
||||
* The proxies are initialized by {@link LazyInitializationService}.
|
||||
*/
|
||||
public class LazyInitializationModule extends AbstractModule {
|
||||
|
||||
private final Set<Class<? extends LazyInitializable>> initializables = new HashSet<>();
|
||||
|
||||
@Override
|
||||
protected void configure() {
|
||||
Multibinder<LazyInitializable> mbinder = Multibinder.newSetBinder(binder(), LazyInitializable.class);
|
||||
for (Class<? extends LazyInitializable> initializable : initializables) {
|
||||
bind(initializable).asEagerSingleton();
|
||||
mbinder.addBinding().to(initializable);
|
||||
}
|
||||
bind(LazyInitializationService.class).asEagerSingleton();
|
||||
}
|
||||
|
||||
public void registerLazyInitializable(Class<? extends LazyInitializable> lazyTypeClass) {
|
||||
initializables.add(lazyTypeClass);
|
||||
}
|
||||
}
|
|
@ -3,7 +3,7 @@
|
|||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
package org.elasticsearch.watcher.support.init;
|
||||
package org.elasticsearch.xpack.common.init;
|
||||
|
||||
import org.elasticsearch.ElasticsearchException;
|
||||
import org.elasticsearch.common.component.AbstractLifecycleComponent;
|
||||
|
@ -14,15 +14,15 @@ import org.elasticsearch.common.settings.Settings;
|
|||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* A service to lazy initialize {@link InitializingService.Initializable} constructs.
|
||||
* A service to lazy initialize {@link LazyInitializable} constructs.
|
||||
*/
|
||||
public class InitializingService extends AbstractLifecycleComponent {
|
||||
public class LazyInitializationService extends AbstractLifecycleComponent {
|
||||
|
||||
private final Injector injector;
|
||||
private final Set<Initializable> initializables;
|
||||
private final Set<LazyInitializable> initializables;
|
||||
|
||||
@Inject
|
||||
public InitializingService(Settings settings, Injector injector, Set<Initializable> initializables) {
|
||||
public LazyInitializationService(Settings settings, Injector injector, Set<LazyInitializable> initializables) {
|
||||
super(settings);
|
||||
this.injector = injector;
|
||||
this.initializables = initializables;
|
||||
|
@ -30,7 +30,8 @@ public class InitializingService extends AbstractLifecycleComponent {
|
|||
|
||||
@Override
|
||||
protected void doStart() throws ElasticsearchException {
|
||||
for (Initializable initializable : initializables) {
|
||||
for (LazyInitializable initializable : initializables) {
|
||||
logger.trace("lazy initialization of [{}]", initializable);
|
||||
initializable.init(injector);
|
||||
}
|
||||
}
|
||||
|
@ -42,9 +43,4 @@ public class InitializingService extends AbstractLifecycleComponent {
|
|||
@Override
|
||||
protected void doClose() throws ElasticsearchException {
|
||||
}
|
||||
|
||||
public interface Initializable {
|
||||
|
||||
void init(Injector injector);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
package org.elasticsearch.xpack.common.init.proxy;
|
||||
|
||||
import org.elasticsearch.action.ActionListener;
|
||||
import org.elasticsearch.action.bulk.BulkRequest;
|
||||
import org.elasticsearch.action.bulk.BulkResponse;
|
||||
import org.elasticsearch.client.AdminClient;
|
||||
import org.elasticsearch.client.Client;
|
||||
import org.elasticsearch.common.inject.Injector;
|
||||
import org.elasticsearch.shield.InternalClient;
|
||||
import org.elasticsearch.transport.TransportMessage;
|
||||
import org.elasticsearch.xpack.common.init.LazyInitializable;
|
||||
|
||||
/**
|
||||
* A lazily initialized proxy to an elasticsearch {@link Client}. Inject this proxy whenever a client
|
||||
* needs to injected to be avoid circular dependencies issues.
|
||||
*/
|
||||
public class ClientProxy implements LazyInitializable {
|
||||
|
||||
protected InternalClient client;
|
||||
|
||||
@Override
|
||||
public void init(Injector injector) {
|
||||
this.client = injector.getInstance(InternalClient.class);
|
||||
}
|
||||
|
||||
public AdminClient admin() {
|
||||
return client.admin();
|
||||
}
|
||||
|
||||
public void bulk(BulkRequest request, ActionListener<BulkResponse> listener) {
|
||||
client.bulk(preProcess(request), listener);
|
||||
}
|
||||
|
||||
protected <M extends TransportMessage> M preProcess(M message) {
|
||||
return message;
|
||||
}
|
||||
}
|
|
@ -38,6 +38,7 @@ import org.elasticsearch.watcher.execution.ExecutionModule;
|
|||
import org.elasticsearch.watcher.history.HistoryModule;
|
||||
import org.elasticsearch.watcher.history.HistoryStore;
|
||||
import org.elasticsearch.watcher.input.InputModule;
|
||||
import org.elasticsearch.watcher.input.chain.ChainInputFactory;
|
||||
import org.elasticsearch.watcher.license.LicenseModule;
|
||||
import org.elasticsearch.watcher.license.WatcherLicensee;
|
||||
import org.elasticsearch.watcher.rest.action.RestAckWatchAction;
|
||||
|
@ -54,14 +55,14 @@ import org.elasticsearch.watcher.support.WatcherIndexTemplateRegistry.TemplateCo
|
|||
import org.elasticsearch.watcher.support.clock.ClockModule;
|
||||
import org.elasticsearch.watcher.support.http.HttpClient;
|
||||
import org.elasticsearch.watcher.support.http.HttpClientModule;
|
||||
import org.elasticsearch.watcher.support.init.InitializingModule;
|
||||
import org.elasticsearch.watcher.support.init.InitializingService;
|
||||
import org.elasticsearch.watcher.support.init.proxy.ScriptServiceProxy;
|
||||
import org.elasticsearch.watcher.support.init.proxy.WatcherClientProxy;
|
||||
import org.elasticsearch.watcher.support.secret.SecretModule;
|
||||
import org.elasticsearch.watcher.support.secret.SecretService;
|
||||
import org.elasticsearch.watcher.support.text.TextTemplateModule;
|
||||
import org.elasticsearch.watcher.support.validation.WatcherSettingsValidation;
|
||||
import org.elasticsearch.watcher.transform.TransformModule;
|
||||
import org.elasticsearch.watcher.transform.chain.ChainTransformFactory;
|
||||
import org.elasticsearch.watcher.transport.actions.ack.AckWatchAction;
|
||||
import org.elasticsearch.watcher.transport.actions.ack.TransportAckWatchAction;
|
||||
import org.elasticsearch.watcher.transport.actions.activate.ActivateWatchAction;
|
||||
|
@ -82,6 +83,7 @@ import org.elasticsearch.watcher.trigger.TriggerModule;
|
|||
import org.elasticsearch.watcher.trigger.schedule.ScheduleModule;
|
||||
import org.elasticsearch.watcher.watch.WatchModule;
|
||||
import org.elasticsearch.xpack.XPackPlugin;
|
||||
import org.elasticsearch.xpack.common.init.LazyInitializationModule;
|
||||
import org.joda.time.DateTime;
|
||||
import org.joda.time.DateTimeZone;
|
||||
|
||||
|
@ -133,7 +135,6 @@ public class Watcher {
|
|||
}
|
||||
return Arrays.<Module>asList(
|
||||
new WatcherModule(settings),
|
||||
new InitializingModule(),
|
||||
new LicenseModule(),
|
||||
new WatchModule(),
|
||||
new TextTemplateModule(),
|
||||
|
@ -156,10 +157,6 @@ public class Watcher {
|
|||
return Collections.emptyList();
|
||||
}
|
||||
return Arrays.<Class<? extends LifecycleComponent>>asList(
|
||||
// the initialization service must be first in the list
|
||||
// as other services may depend on one of the initialized
|
||||
// constructs
|
||||
InitializingService.class,
|
||||
WatcherLicensee.class,
|
||||
EmailService.class,
|
||||
HipChatService.class,
|
||||
|
@ -254,6 +251,15 @@ public class Watcher {
|
|||
}
|
||||
}
|
||||
|
||||
public void onModule(LazyInitializationModule module) {
|
||||
if (enabled) {
|
||||
module.registerLazyInitializable(WatcherClientProxy.class);
|
||||
module.registerLazyInitializable(ScriptServiceProxy.class);
|
||||
module.registerLazyInitializable(ChainTransformFactory.class);
|
||||
module.registerLazyInitializable(ChainInputFactory.class);
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean enabled(Settings settings) {
|
||||
return XPackPlugin.featureEnabled(settings, NAME, true);
|
||||
}
|
||||
|
|
|
@ -48,7 +48,7 @@ public class InputModule extends AbstractModule {
|
|||
bind(NoneInputFactory.class).asEagerSingleton();
|
||||
parsersBinder.addBinding(NoneInput.TYPE).to(NoneInputFactory.class);
|
||||
|
||||
// no bind() needed, done in InitializingModule
|
||||
// no bind() needed, done using the LazyInitializationModule
|
||||
parsersBinder.addBinding(ChainInput.TYPE).to(ChainInputFactory.class);
|
||||
|
||||
for (Map.Entry<String, Class<? extends InputFactory>> entry : parsers.entrySet()) {
|
||||
|
|
|
@ -15,14 +15,14 @@ import org.elasticsearch.watcher.input.ExecutableInput;
|
|||
import org.elasticsearch.watcher.input.Input;
|
||||
import org.elasticsearch.watcher.input.InputFactory;
|
||||
import org.elasticsearch.watcher.input.InputRegistry;
|
||||
import org.elasticsearch.watcher.support.init.InitializingService;
|
||||
import org.elasticsearch.xpack.common.init.LazyInitializable;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class ChainInputFactory extends InputFactory<ChainInput, ChainInput.Result, ExecutableChainInput>
|
||||
implements InitializingService.Initializable {
|
||||
implements LazyInitializable {
|
||||
|
||||
private InputRegistry inputRegistry;
|
||||
|
||||
|
|
|
@ -1,35 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
package org.elasticsearch.watcher.support.init;
|
||||
|
||||
import org.elasticsearch.common.inject.AbstractModule;
|
||||
import org.elasticsearch.common.inject.multibindings.Multibinder;
|
||||
import org.elasticsearch.watcher.input.chain.ChainInputFactory;
|
||||
import org.elasticsearch.watcher.support.init.proxy.WatcherClientProxy;
|
||||
import org.elasticsearch.watcher.support.init.proxy.ScriptServiceProxy;
|
||||
import org.elasticsearch.watcher.transform.chain.ChainTransformFactory;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class InitializingModule extends AbstractModule {
|
||||
|
||||
@Override
|
||||
protected void configure() {
|
||||
|
||||
bind(WatcherClientProxy.class).asEagerSingleton();
|
||||
bind(ScriptServiceProxy.class).asEagerSingleton();
|
||||
bind(ChainInputFactory.class).asEagerSingleton();
|
||||
|
||||
Multibinder<InitializingService.Initializable> mbinder = Multibinder.newSetBinder(binder(),
|
||||
InitializingService.Initializable.class);
|
||||
mbinder.addBinding().to(WatcherClientProxy.class);
|
||||
mbinder.addBinding().to(ScriptServiceProxy.class);
|
||||
mbinder.addBinding().to(ChainTransformFactory.class);
|
||||
mbinder.addBinding().to(ChainInputFactory.class);
|
||||
bind(InitializingService.class).asEagerSingleton();
|
||||
}
|
||||
}
|
|
@ -13,7 +13,7 @@ import org.elasticsearch.script.ScriptService;
|
|||
import org.elasticsearch.shield.SecurityContext;
|
||||
import org.elasticsearch.shield.XPackUser;
|
||||
import org.elasticsearch.watcher.support.Script;
|
||||
import org.elasticsearch.watcher.support.init.InitializingService;
|
||||
import org.elasticsearch.xpack.common.init.LazyInitializable;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
|
@ -23,7 +23,7 @@ import static java.util.Collections.emptyMap;
|
|||
*A lazily initialized proxy to the elasticsearch {@link ScriptService}. Inject this proxy whenever the script
|
||||
* service needs to be injected to avoid circular dependencies issues.
|
||||
*/
|
||||
public class ScriptServiceProxy implements InitializingService.Initializable {
|
||||
public class ScriptServiceProxy implements LazyInitializable {
|
||||
|
||||
private ScriptService service;
|
||||
private SecurityContext securityContext;
|
||||
|
|
|
@ -23,26 +23,22 @@ import org.elasticsearch.action.search.SearchResponse;
|
|||
import org.elasticsearch.action.search.SearchScrollRequest;
|
||||
import org.elasticsearch.action.update.UpdateRequest;
|
||||
import org.elasticsearch.action.update.UpdateResponse;
|
||||
import org.elasticsearch.client.AdminClient;
|
||||
import org.elasticsearch.client.Client;
|
||||
import org.elasticsearch.common.inject.Inject;
|
||||
import org.elasticsearch.common.inject.Injector;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.unit.TimeValue;
|
||||
import org.elasticsearch.shield.InternalClient;
|
||||
import org.elasticsearch.transport.TransportMessage;
|
||||
import org.elasticsearch.watcher.support.init.InitializingService;
|
||||
import org.elasticsearch.xpack.common.init.proxy.ClientProxy;
|
||||
|
||||
/**
|
||||
* A lazily initialized proxy to an elasticsearch {@link Client}. Inject this proxy whenever a client
|
||||
* needs to injected to be avoid circular dependencies issues.
|
||||
*/
|
||||
public class WatcherClientProxy implements InitializingService.Initializable {
|
||||
public class WatcherClientProxy extends ClientProxy {
|
||||
|
||||
private final TimeValue defaultSearchTimeout;
|
||||
private final TimeValue defaultIndexTimeout;
|
||||
private final TimeValue defaultBulkTimeout;
|
||||
private InternalClient client;
|
||||
|
||||
@Inject
|
||||
public WatcherClientProxy(Settings settings) {
|
||||
|
@ -60,15 +56,6 @@ public class WatcherClientProxy implements InitializingService.Initializable {
|
|||
return proxy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(Injector injector) {
|
||||
this.client = injector.getInstance(InternalClient.class);
|
||||
}
|
||||
|
||||
public AdminClient admin() {
|
||||
return client.admin();
|
||||
}
|
||||
|
||||
public IndexResponse index(IndexRequest request, TimeValue timeout) {
|
||||
if (timeout == null) {
|
||||
timeout = defaultIndexTimeout;
|
||||
|
@ -125,8 +112,4 @@ public class WatcherClientProxy implements InitializingService.Initializable {
|
|||
preProcess(request);
|
||||
return client.admin().indices().putTemplate(request).actionGet(defaultIndexTimeout);
|
||||
}
|
||||
|
||||
<M extends TransportMessage> M preProcess(M message) {
|
||||
return message;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,7 +38,7 @@ public class TransformModule extends AbstractModule {
|
|||
bind(ScriptTransformFactory.class).asEagerSingleton();
|
||||
mbinder.addBinding(ScriptTransform.TYPE).to(ScriptTransformFactory.class);
|
||||
|
||||
bind(ChainTransformFactory.class).asEagerSingleton();
|
||||
// no bind() needed, done using the LazyInitializationModule
|
||||
mbinder.addBinding(ChainTransform.TYPE).to(ChainTransformFactory.class);
|
||||
|
||||
for (Map.Entry<String, Class<? extends TransformFactory>> entry : factories.entrySet()) {
|
||||
|
|
|
@ -9,11 +9,11 @@ import org.elasticsearch.common.inject.Injector;
|
|||
import org.elasticsearch.common.logging.Loggers;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.watcher.support.init.InitializingService;
|
||||
import org.elasticsearch.watcher.transform.ExecutableTransform;
|
||||
import org.elasticsearch.watcher.transform.Transform;
|
||||
import org.elasticsearch.watcher.transform.TransformFactory;
|
||||
import org.elasticsearch.watcher.transform.TransformRegistry;
|
||||
import org.elasticsearch.xpack.common.init.LazyInitializable;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
|
@ -22,7 +22,7 @@ import java.util.ArrayList;
|
|||
*
|
||||
*/
|
||||
public class ChainTransformFactory extends TransformFactory<ChainTransform, ChainTransform.Result, ExecutableChainTransform> implements
|
||||
InitializingService.Initializable {
|
||||
LazyInitializable {
|
||||
|
||||
private TransformRegistry registry;
|
||||
|
||||
|
|
Loading…
Reference in New Issue