Make ReviewDb available in the server on a per-thread basis
Allow types bound in the system injector to access the per-thread ReviewDb if they are invoked from within a request context, without caring about which entry they were invoked from. This allows email sending and some other change update action code to be bound at the global level and work in both SSH and HTTP invocations. Change-Id: I411ded5196ae6920573233fb0cde48f35ce7ad01
This commit is contained in:
@@ -14,9 +14,12 @@
|
||||
|
||||
package com.google.gerrit.server.util;
|
||||
|
||||
import com.google.gerrit.reviewdb.server.ReviewDb;
|
||||
import com.google.gerrit.server.AnonymousUser;
|
||||
import com.google.gerrit.server.CurrentUser;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Provider;
|
||||
import com.google.inject.ProvisionException;
|
||||
import com.google.inject.Singleton;
|
||||
|
||||
/**
|
||||
@@ -37,4 +40,15 @@ public class FallbackRequestContext implements RequestContext {
|
||||
public CurrentUser getCurrentUser() {
|
||||
return user;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Provider<ReviewDb> getReviewDbProvider() {
|
||||
return new Provider<ReviewDb>() {
|
||||
@Override
|
||||
public ReviewDb get() {
|
||||
throw new ProvisionException(
|
||||
"Automatic ReviewDb only available in request scope");
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ package com.google.gerrit.server.util;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.gerrit.server.RemotePeer;
|
||||
import com.google.gerrit.server.config.CanonicalWebUrl;
|
||||
import com.google.gerrit.server.config.RequestScopedReviewDbProvider;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Key;
|
||||
import com.google.inject.Provider;
|
||||
@@ -42,8 +43,9 @@ public class GuiceRequestScopePropagator extends RequestScopePropagator {
|
||||
GuiceRequestScopePropagator(
|
||||
@CanonicalWebUrl @Nullable Provider<String> urlProvider,
|
||||
@RemotePeer Provider<SocketAddress> remotePeerProvider,
|
||||
ThreadLocalRequestContext local) {
|
||||
super(ServletScopes.REQUEST, local);
|
||||
ThreadLocalRequestContext local,
|
||||
Provider<RequestScopedReviewDbProvider> dbProviderProvider) {
|
||||
super(ServletScopes.REQUEST, local, dbProviderProvider);
|
||||
this.url = urlProvider != null ? urlProvider.get() : null;
|
||||
this.peer = remotePeerProvider.get();
|
||||
}
|
||||
|
||||
@@ -14,13 +14,15 @@
|
||||
|
||||
package com.google.gerrit.server.util;
|
||||
|
||||
import com.google.gerrit.reviewdb.server.ReviewDb;
|
||||
import com.google.gerrit.server.CurrentUser;
|
||||
import com.google.inject.Provider;
|
||||
|
||||
/**
|
||||
* The RequestContext is an interface exposing the fields that are needed
|
||||
* by the GerritGlobalModule scope.
|
||||
*/
|
||||
public interface RequestContext {
|
||||
|
||||
CurrentUser getCurrentUser();
|
||||
Provider<ReviewDb> getReviewDbProvider();
|
||||
}
|
||||
|
||||
@@ -14,8 +14,12 @@
|
||||
|
||||
package com.google.gerrit.server.util;
|
||||
|
||||
import com.google.gerrit.reviewdb.client.Project.NameKey;
|
||||
import com.google.common.base.Throwables;
|
||||
import com.google.gerrit.reviewdb.client.Project;
|
||||
import com.google.gerrit.reviewdb.server.ReviewDb;
|
||||
import com.google.gerrit.server.CurrentUser;
|
||||
import com.google.gerrit.server.RequestCleanup;
|
||||
import com.google.gerrit.server.config.RequestScopedReviewDbProvider;
|
||||
import com.google.gerrit.server.git.ProjectRunnable;
|
||||
import com.google.inject.Key;
|
||||
import com.google.inject.Provider;
|
||||
@@ -43,11 +47,14 @@ public abstract class RequestScopePropagator {
|
||||
|
||||
private final Scope scope;
|
||||
private final ThreadLocalRequestContext local;
|
||||
private final Provider<RequestScopedReviewDbProvider> dbProviderProvider;
|
||||
|
||||
protected RequestScopePropagator(Scope scope,
|
||||
ThreadLocalRequestContext local) {
|
||||
ThreadLocalRequestContext local,
|
||||
Provider<RequestScopedReviewDbProvider> dbProviderProvider) {
|
||||
this.scope = scope;
|
||||
this.local = local;
|
||||
this.dbProviderProvider = dbProviderProvider;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -111,15 +118,14 @@ public abstract class RequestScopePropagator {
|
||||
public void run() {
|
||||
try {
|
||||
wrapped.call();
|
||||
} catch (RuntimeException e) {
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
Throwables.propagateIfPossible(e);
|
||||
throw new RuntimeException(e); // Not possible.
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public NameKey getProjectNameKey() {
|
||||
public Project.NameKey getProjectNameKey() {
|
||||
return ((ProjectRunnable) runnable).getProjectNameKey();
|
||||
}
|
||||
|
||||
@@ -164,12 +170,23 @@ public abstract class RequestScopePropagator {
|
||||
*/
|
||||
protected abstract <T> Callable<T> wrapImpl(final Callable<T> callable);
|
||||
|
||||
protected <T> Callable<T> context(final RequestContext context,
|
||||
protected <T> Callable<T> context(RequestContext context,
|
||||
final Callable<T> callable) {
|
||||
final CurrentUser user = context.getCurrentUser();
|
||||
return new Callable<T>() {
|
||||
@Override
|
||||
public T call() throws Exception {
|
||||
RequestContext old = local.setContext(context);
|
||||
RequestContext old = local.setContext(new RequestContext() {
|
||||
@Override
|
||||
public CurrentUser getCurrentUser() {
|
||||
return user;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Provider<ReviewDb> getReviewDbProvider() {
|
||||
return dbProviderProvider.get();
|
||||
}
|
||||
});
|
||||
try {
|
||||
return callable.call();
|
||||
} finally {
|
||||
@@ -191,7 +208,6 @@ public abstract class RequestScopePropagator {
|
||||
return new RequestCleanup();
|
||||
}
|
||||
}).get();
|
||||
|
||||
try {
|
||||
return callable.call();
|
||||
} finally {
|
||||
|
||||
@@ -16,6 +16,7 @@ package com.google.gerrit.server.util;
|
||||
|
||||
import com.google.common.base.Objects;
|
||||
import com.google.gerrit.common.errors.NotSignedInException;
|
||||
import com.google.gerrit.reviewdb.server.ReviewDb;
|
||||
import com.google.gerrit.server.CurrentUser;
|
||||
import com.google.gerrit.server.IdentifiedUser;
|
||||
import com.google.inject.AbstractModule;
|
||||
@@ -64,6 +65,11 @@ public class ThreadLocalRequestContext {
|
||||
throw new ProvisionException(NotSignedInException.MESSAGE,
|
||||
new NotSignedInException());
|
||||
}
|
||||
|
||||
@Provides
|
||||
ReviewDb provideReviewDb(RequestContext ctx) {
|
||||
return ctx.getReviewDbProvider().get();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -14,7 +14,9 @@
|
||||
|
||||
package com.google.gerrit.server.util;
|
||||
|
||||
import com.google.gerrit.server.config.RequestScopedReviewDbProvider;
|
||||
import com.google.inject.OutOfScopeException;
|
||||
import com.google.inject.Provider;
|
||||
import com.google.inject.Scope;
|
||||
|
||||
import java.util.concurrent.Callable;
|
||||
@@ -31,8 +33,10 @@ public abstract class ThreadLocalRequestScopePropagator<C>
|
||||
private final ThreadLocal<C> threadLocal;
|
||||
|
||||
protected ThreadLocalRequestScopePropagator(Scope scope,
|
||||
ThreadLocal<C> threadLocal, ThreadLocalRequestContext local) {
|
||||
super(scope, local);
|
||||
ThreadLocal<C> threadLocal,
|
||||
ThreadLocalRequestContext local,
|
||||
Provider<RequestScopedReviewDbProvider> dbProviderProvider) {
|
||||
super(scope, local, dbProviderProvider);
|
||||
this.threadLocal = threadLocal;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user