Enable plugins in BATCH mode
Batch mode is defined (for now) as "everything that is not Gerrit Daemon". This includes the "reindex" task, but is not limited to it. Adding plugins to batch mode allows plugins with a direct impact on the changes' index to have a consistent impact: without it, custom prolog predicates and plugin-provided SubmitRule-s are ignored. In BATCH mode, Gerrit will try to find and load Gerrit-BatchModule(s) modules defined by plugins, if any. This module should be compatible with the batch mode injectors: it must not rely on SSH or HTTP classes. This new module is optional, and plugins not defining one will not be loaded in batch mode. As such, this new feature is retro-compatible: no "old" plugins will be loaded. Change-Id: I9be5a2ea0fd841986b940e046d215a820497107b
This commit is contained in:
@@ -109,6 +109,24 @@ will be performed by scanning all classes in the plugin JAR for
|
||||
Gerrit-HttpModule: tld.example.project.HttpModuleClassName
|
||||
----
|
||||
|
||||
=== Batch runtime
|
||||
|
||||
Gerrit can be run as a server, serving HTTP or SSH requests, or as an
|
||||
offline program. Plugins can contribute Guice modules to this batch
|
||||
runtime by binding `Gerrit-BatchModule` to one of their classes.
|
||||
The Guice injector is bound to less classes, and some Gerrit features
|
||||
will be absent - on purpose.
|
||||
|
||||
This feature was originally introduced to support plugins during an
|
||||
offline reindexing task.
|
||||
|
||||
----
|
||||
Gerrit-BatchModule: tld.example.project.CoreModuleClassName
|
||||
----
|
||||
|
||||
In this runtime, only the module designated by `Gerrit-BatchModule` is
|
||||
enabled, not `Gerrit-SysModule`.
|
||||
|
||||
[[plugin_name]]
|
||||
=== Plugin Name
|
||||
|
||||
@@ -2840,6 +2858,9 @@ public class MyPluginModule extends AbstractModule {
|
||||
}
|
||||
----
|
||||
|
||||
Plugin authors should also consider binding their SubmitRule using a `Gerrit-BatchModule`.
|
||||
See link:dev-plugins.html[Batch runtime] for more informations.
|
||||
|
||||
== SEE ALSO
|
||||
|
||||
* link:js-api.html[JavaScript API]
|
||||
|
||||
@@ -34,6 +34,7 @@ import com.google.gerrit.server.index.DummyIndexModule;
|
||||
import com.google.gerrit.server.index.change.ChangeSchemaDefinitions;
|
||||
import com.google.gerrit.server.notedb.rebuild.GcAllUsers;
|
||||
import com.google.gerrit.server.notedb.rebuild.NoteDbMigrator;
|
||||
import com.google.gerrit.server.plugins.PluginGuiceEnvironment;
|
||||
import com.google.gerrit.server.schema.DataSourceType;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Injector;
|
||||
@@ -118,6 +119,9 @@ public class MigrateToNoteDb extends SiteProgram {
|
||||
sysInjector.injectMembers(this);
|
||||
sysManager = new LifecycleManager();
|
||||
sysManager.add(sysInjector);
|
||||
sysInjector
|
||||
.getInstance(PluginGuiceEnvironment.class)
|
||||
.setDbCfgInjector(dbInjector, dbInjector);
|
||||
sysManager.start();
|
||||
|
||||
try (NoteDbMigrator migrator =
|
||||
|
||||
@@ -35,6 +35,7 @@ import com.google.gerrit.server.config.GerritServerConfig;
|
||||
import com.google.gerrit.server.index.IndexModule;
|
||||
import com.google.gerrit.server.index.IndexModule.IndexType;
|
||||
import com.google.gerrit.server.index.change.ChangeSchemaDefinitions;
|
||||
import com.google.gerrit.server.plugins.PluginGuiceEnvironment;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Injector;
|
||||
import com.google.inject.Key;
|
||||
@@ -72,6 +73,7 @@ public class Reindex extends SiteProgram {
|
||||
|
||||
private Injector dbInjector;
|
||||
private Injector sysInjector;
|
||||
private Injector cfgInjector;
|
||||
private Config globalConfig;
|
||||
|
||||
@Inject private Collection<IndexDefinition<?, ?, ?>> indexDefs;
|
||||
@@ -80,6 +82,7 @@ public class Reindex extends SiteProgram {
|
||||
public int run() throws Exception {
|
||||
mustHaveValidSite();
|
||||
dbInjector = createDbInjector(MULTI_USER);
|
||||
cfgInjector = dbInjector.createChildInjector();
|
||||
globalConfig = dbInjector.getInstance(Key.get(Config.class, GerritServerConfig.class));
|
||||
threads = ThreadLimiter.limitThreads(dbInjector, threads);
|
||||
overrideConfig();
|
||||
@@ -88,9 +91,11 @@ public class Reindex extends SiteProgram {
|
||||
dbManager.start();
|
||||
|
||||
sysInjector = createSysInjector();
|
||||
sysInjector.getInstance(PluginGuiceEnvironment.class).setDbCfgInjector(dbInjector, cfgInjector);
|
||||
LifecycleManager sysManager = new LifecycleManager();
|
||||
sysManager.add(sysInjector);
|
||||
sysManager.start();
|
||||
|
||||
sysInjector.injectMembers(this);
|
||||
checkIndicesOption();
|
||||
|
||||
|
||||
@@ -65,6 +65,7 @@ import com.google.gerrit.server.patch.DiffExecutorModule;
|
||||
import com.google.gerrit.server.patch.PatchListCacheImpl;
|
||||
import com.google.gerrit.server.permissions.DefaultPermissionBackendModule;
|
||||
import com.google.gerrit.server.permissions.SectionSortCache;
|
||||
import com.google.gerrit.server.plugins.PluginModule;
|
||||
import com.google.gerrit.server.project.CommentLinkProvider;
|
||||
import com.google.gerrit.server.project.CommitResource;
|
||||
import com.google.gerrit.server.project.ProjectCacheImpl;
|
||||
@@ -111,7 +112,16 @@ public class BatchProgramModule extends FactoryModule {
|
||||
install(BatchUpdate.module());
|
||||
install(PatchListCacheImpl.module());
|
||||
|
||||
// Plugins are not loaded and we're just running through each change
|
||||
// There is the concept of LifecycleModule, in Gerrit's own extension to Guice, which has these:
|
||||
// listener().to(SomeClassImplementingLifecycleListener.class);
|
||||
// and the start() methods of each such listener are executed in the order they are declared.
|
||||
// Makes sure that PluginLoader.start() is executed before the LuceneIndexModule.start() so that
|
||||
// plugins get loaded and the respective Guice modules installed so that the on-line reindexing
|
||||
// will happen with the proper classes (e.g. group backends, custom Prolog predicates) and the
|
||||
// associated rules ready to be evaluated.
|
||||
install(new PluginModule());
|
||||
|
||||
// We're just running through each change
|
||||
// once, so don't worry about cache removal.
|
||||
bind(new TypeLiteral<DynamicSet<CacheRemovalListener>>() {})
|
||||
.toInstance(DynamicSet.<CacheRemovalListener>emptySet());
|
||||
|
||||
@@ -46,6 +46,7 @@ public class ServerPlugin extends Plugin {
|
||||
private final String metricsPrefix;
|
||||
private final GerritRuntime gerritRuntime;
|
||||
protected Class<? extends Module> sysModule;
|
||||
protected Class<? extends Module> batchModule;
|
||||
protected Class<? extends Module> sshModule;
|
||||
protected Class<? extends Module> httpModule;
|
||||
|
||||
@@ -91,6 +92,7 @@ public class ServerPlugin extends Plugin {
|
||||
String sysName = main.getValue("Gerrit-Module");
|
||||
String sshName = main.getValue("Gerrit-SshModule");
|
||||
String httpName = main.getValue("Gerrit-HttpModule");
|
||||
String batchName = main.getValue("Gerrit-BatchModule");
|
||||
|
||||
if (!Strings.isNullOrEmpty(sshName) && getApiType() != Plugin.ApiType.PLUGIN) {
|
||||
throw new InvalidPluginException(
|
||||
@@ -99,6 +101,7 @@ public class ServerPlugin extends Plugin {
|
||||
}
|
||||
|
||||
try {
|
||||
this.batchModule = load(batchName, classLoader);
|
||||
this.sysModule = load(sysName, classLoader);
|
||||
this.sshModule = load(sshName, classLoader);
|
||||
this.httpModule = load(httpName, classLoader);
|
||||
@@ -108,7 +111,7 @@ public class ServerPlugin extends Plugin {
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected static Class<? extends Module> load(String name, ClassLoader pluginLoader)
|
||||
protected static Class<? extends Module> load(@Nullable String name, ClassLoader pluginLoader)
|
||||
throws ClassNotFoundException {
|
||||
if (Strings.isNullOrEmpty(name)) {
|
||||
return null;
|
||||
@@ -180,6 +183,18 @@ public class ServerPlugin extends Plugin {
|
||||
serverManager = new LifecycleManager();
|
||||
serverManager.add(root);
|
||||
|
||||
if (gerritRuntime == GerritRuntime.BATCH) {
|
||||
if (batchModule != null) {
|
||||
sysInjector = root.createChildInjector(root.getInstance(batchModule));
|
||||
serverManager.add(sysInjector);
|
||||
} else {
|
||||
sysInjector = root;
|
||||
}
|
||||
|
||||
serverManager.start();
|
||||
return;
|
||||
}
|
||||
|
||||
AutoRegisterModules auto = null;
|
||||
if (sysModule == null && sshModule == null && httpModule == null) {
|
||||
auto = new AutoRegisterModules(getName(), env, scanner, classLoader);
|
||||
|
||||
Reference in New Issue
Block a user