Lazily open database connections in ChangeIndexer tasks
These connections are only needed in the request scope environment
when continuing work in a different thread. Most indexing operations
(e.g. from new-style REST APIs) don't happen in a request scope, so
don't need to tie up a database connection on the off chance that
RequestContext.getReviewDbProvider() is called.
Change-Id: Ide04ffc61dc73b2c816ed29ee018c83e948f6f1d
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/index/ChangeIndexerImpl.java b/gerrit-server/src/main/java/com/google/gerrit/server/index/ChangeIndexerImpl.java
index ef89a54..e79622c 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/index/ChangeIndexerImpl.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/index/ChangeIndexerImpl.java
@@ -14,15 +14,18 @@
package com.google.gerrit.server.index;
+import com.google.common.util.concurrent.Atomics;
import com.google.common.util.concurrent.ListeningScheduledExecutorService;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.query.change.ChangeData;
import com.google.gerrit.server.util.RequestContext;
import com.google.gerrit.server.util.ThreadLocalRequestContext;
+import com.google.gwtorm.server.OrmException;
import com.google.gwtorm.server.SchemaFactory;
import com.google.inject.OutOfScopeException;
import com.google.inject.Provider;
+import com.google.inject.ProvisionException;
import com.google.inject.assistedinject.Assisted;
import com.google.inject.assistedinject.AssistedInject;
import com.google.inject.util.Providers;
@@ -32,6 +35,7 @@
import java.io.IOException;
import java.util.concurrent.Callable;
+import java.util.concurrent.atomic.AtomicReference;
/**
* Helper for (re)indexing a change document.
@@ -94,12 +98,25 @@
@Override
public Void call() throws Exception {
try {
- final ReviewDb db = schemaFactory.open();
+ final AtomicReference<Provider<ReviewDb>> dbRef =
+ Atomics.newReference();
try {
context.setContext(new RequestContext() {
@Override
public Provider<ReviewDb> getReviewDbProvider() {
- return Providers.of(db);
+ Provider<ReviewDb> db = dbRef.get();
+ if (db == null) {
+ try {
+ db = Providers.of(schemaFactory.open());
+ } catch (OrmException e) {
+ ProvisionException pe =
+ new ProvisionException("error opening ReviewDb");
+ pe.initCause(e);
+ throw pe;
+ }
+ dbRef.set(db);
+ }
+ return db;
}
@Override
@@ -117,7 +134,10 @@
return null;
} finally {
context.setContext(null);
- db.close();
+ Provider<ReviewDb> db = dbRef.get();
+ if (db != null) {
+ db.get().close();
+ }
}
} catch (Exception e) {
log.error(String.format(