Do not use QueryProcessor multiple times
The QueryProcessor object is non-threadsafe and it should not be reused.
This is been enforced with runtime state checks from stable-2.15 onwards.
Rather than using the same object through multiple requests, the
QueryChanges healthcheck now will be instantiated with a _provider_ of
QueryChanges, so that a new QueryProcessor is used each time the
healthcheck is executed.
Change-Id: Ifa4e621eaf87a409c428a618e2a7f2dcd0bb2ca7
diff --git a/src/main/java/com/googlesource/gerrit/plugins/healthcheck/check/QueryChangesHealthCheck.java b/src/main/java/com/googlesource/gerrit/plugins/healthcheck/check/QueryChangesHealthCheck.java
index ce6b168..a8e4d2e 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/healthcheck/check/QueryChangesHealthCheck.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/healthcheck/check/QueryChangesHealthCheck.java
@@ -21,6 +21,7 @@
import com.google.gerrit.server.util.ManualRequestContext;
import com.google.gerrit.server.util.OneOffRequestContext;
import com.google.inject.Inject;
+import com.google.inject.Provider;
import com.google.inject.Singleton;
import com.googlesource.gerrit.plugins.healthcheck.HealthCheckConfig;
import java.util.List;
@@ -30,7 +31,8 @@
@Singleton
public class QueryChangesHealthCheck extends AbstractHealthCheck {
private static final Logger log = LoggerFactory.getLogger(QueryChangesHealthCheck.class);
- private final QueryChanges queryChanges;
+ private final Provider<QueryChanges> queryChangesProvider;
+ private final HealthCheckConfig config;
private final int limit;
private final OneOffRequestContext oneOffCtx;
@@ -38,20 +40,25 @@
public QueryChangesHealthCheck(
ListeningExecutorService executor,
HealthCheckConfig config,
- QueryChanges queryChanges,
+ Provider<QueryChanges> queryChangesProvider,
OneOffRequestContext oneOffCtx) {
super(executor, config, QUERYCHANGES);
- this.queryChanges = queryChanges;
+ this.queryChangesProvider = queryChangesProvider;
+ this.config = config;
this.limit = config.getLimit(QUERYCHANGES);
- queryChanges.setLimit(limit);
- queryChanges.addQuery(config.getQuery(QUERYCHANGES));
- queryChanges.setStart(0);
+
this.oneOffCtx = oneOffCtx;
}
@Override
protected Result doCheck() throws Exception {
try (ManualRequestContext ctx = oneOffCtx.open()) {
+
+ QueryChanges queryChanges = this.queryChangesProvider.get();
+ queryChanges.setLimit(limit);
+ queryChanges.addQuery(config.getQuery(QUERYCHANGES));
+ queryChanges.setStart(0);
+
List<?> changes = queryChanges.apply(null);
if (changes == null) {
log.warn("Cannot query changes: received a null list of results");
diff --git a/src/test/java/com/googlesource/gerrit/plugins/healthcheck/HealthCheckIT.java b/src/test/java/com/googlesource/gerrit/plugins/healthcheck/HealthCheckIT.java
index 38f807e..2c63ed7 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/healthcheck/HealthCheckIT.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/healthcheck/HealthCheckIT.java
@@ -102,6 +102,18 @@
assertCheckResult(respPayload, QUERYCHANGES, "passed");
}
+ @Test
+ public void shouldReturnQueryChangesMultipleTimesCheck() throws Exception {
+ createChange("refs/for/master");
+ getHealthCheckStatus();
+ RestResponse resp = getHealthCheckStatus();
+ resp.assertOK();
+
+ JsonObject respPayload = gson.fromJson(resp.getReader(), JsonObject.class);
+
+ assertCheckResult(respPayload, QUERYCHANGES, "passed");
+ }
+
private RestResponse getHealthCheckStatus() throws IOException {
return adminRestSession.get("/config/server/healthcheck~status");
}