Read reviewedBy set from secondary index

We now no longer read the database when rendering search results even
with the REVIEWED option used on the account dashboard screen.

Tweak query tests to allow assertions over specific fields set in the
result, to ensure that the value is being set correctly from the
stored field.

Change-Id: I21c43496d2a5b6a1533c45a24e027257f5e4944e
This commit is contained in:
Dave Borowitz
2015-05-27 15:47:20 -07:00
parent 97c7803b7a
commit a7df7ca122
4 changed files with 60 additions and 24 deletions

View File

@@ -463,9 +463,10 @@ public class ChangeIT extends AbstractDaemonTest {
assertThat(gApi.changes().query() assertThat(gApi.changes().query()
.withQuery( .withQuery(
"project:{" + project.get() + "} (status:open OR status:closed)") "project:{" + project.get() + "} (status:open OR status:closed)")
// Options should match defaults in ChangeTable. // Options should match defaults in AccountDashboardScreen.
.withOption(ListChangesOption.LABELS) .withOption(ListChangesOption.LABELS)
.withOption(ListChangesOption.DETAILED_ACCOUNTS) .withOption(ListChangesOption.DETAILED_ACCOUNTS)
.withOption(ListChangesOption.REVIEWED)
.get()) .get())
.hasSize(2); .hasSize(2);
} }

View File

@@ -33,6 +33,8 @@ import java.util.EnumSet;
import java.util.Set; import java.util.Set;
public class AccountDashboardScreen extends Screen implements ChangeListScreen { public class AccountDashboardScreen extends Screen implements ChangeListScreen {
// If changing default options, also update in
// ChangeIT#defaultSearchDoesNotTouchDatabase().
private static final Set<ListChangesOption> MY_DASHBOARD_OPTIONS; private static final Set<ListChangesOption> MY_DASHBOARD_OPTIONS;
static { static {
EnumSet<ListChangesOption> options = EnumSet.copyOf(ChangeTable.OPTIONS); EnumSet<ListChangesOption> options = EnumSet.copyOf(ChangeTable.OPTIONS);

View File

@@ -30,6 +30,7 @@ import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService; import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.gerrit.common.Nullable; import com.google.gerrit.common.Nullable;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.Change; import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.PatchSet; import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gerrit.reviewdb.server.ReviewDb; import com.google.gerrit.reviewdb.server.ReviewDb;
@@ -132,12 +133,14 @@ public class LuceneChangeIndex implements ChangeIndex {
sortFieldName(ChangeField.LEGACY_ID); sortFieldName(ChangeField.LEGACY_ID);
private static final String MERGEABLE_FIELD = ChangeField.MERGEABLE.getName(); private static final String MERGEABLE_FIELD = ChangeField.MERGEABLE.getName();
private static final String PATCH_SET_FIELD = ChangeField.PATCH_SET.getName(); private static final String PATCH_SET_FIELD = ChangeField.PATCH_SET.getName();
private static final String REVIEWEDBY_FIELD =
ChangeField.REVIEWEDBY.getName();
private static final String UPDATED_SORT_FIELD = private static final String UPDATED_SORT_FIELD =
sortFieldName(ChangeField.UPDATED); sortFieldName(ChangeField.UPDATED);
private static final ImmutableSet<String> FIELDS = ImmutableSet.of( private static final ImmutableSet<String> FIELDS = ImmutableSet.of(
ADDED_FIELD, APPROVAL_FIELD, CHANGE_FIELD, DELETED_FIELD, ID_FIELD, ADDED_FIELD, APPROVAL_FIELD, CHANGE_FIELD, DELETED_FIELD, ID_FIELD,
MERGEABLE_FIELD, PATCH_SET_FIELD); MERGEABLE_FIELD, PATCH_SET_FIELD, REVIEWEDBY_FIELD);
private static final Map<String, String> CUSTOM_CHAR_MAPPING = ImmutableMap.of( private static final Map<String, String> CUSTOM_CHAR_MAPPING = ImmutableMap.of(
"_", " ", ".", " "); "_", " ", ".", " ");
@@ -506,6 +509,21 @@ public class LuceneChangeIndex implements ChangeIndex {
cd.setMergeable(false); cd.setMergeable(false);
} }
// Reviewed-by.
IndexableField[] reviewedBy = doc.getFields(REVIEWEDBY_FIELD);
if (reviewedBy.length > 0) {
Set<Account.Id> accounts =
Sets.newHashSetWithExpectedSize(reviewedBy.length);
for (IndexableField r : reviewedBy) {
int id = r.numericValue().intValue();
if (reviewedBy.length == 1 && id == ChangeField.NOT_REVIEWED) {
break;
}
accounts.add(new Account.Id(id));
}
cd.setReviewedBy(accounts);
}
return cd; return cd;
} }

View File

@@ -16,6 +16,7 @@ package com.google.gerrit.server.query.change;
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.TruthJUnit.assume; import static com.google.common.truth.TruthJUnit.assume;
import static com.google.gerrit.extensions.client.ListChangesOption.REVIEWED;
import static java.nio.charset.StandardCharsets.UTF_8; import static java.nio.charset.StandardCharsets.UTF_8;
import static java.util.concurrent.TimeUnit.HOURS; import static java.util.concurrent.TimeUnit.HOURS;
import static java.util.concurrent.TimeUnit.MILLISECONDS; import static java.util.concurrent.TimeUnit.MILLISECONDS;
@@ -1101,10 +1102,25 @@ public abstract class AbstractQueryChangesTest {
.revision(ps3_1.get()) .revision(ps3_1.get())
.review(new ReviewInput().message("comment")); .review(new ReviewInput().message("comment"));
assertQuery("is:reviewed", change3, change2); List<ChangeInfo> actual;
assertQuery("-is:reviewed", change1); actual = assertQuery(
assertQuery("reviewedby:" + userId.get()); newQuery("is:reviewed").withOption(REVIEWED),
assertQuery("reviewedby:" + user2.get(), change3, change2); change3, change2);
assertThat(actual.get(0).reviewed).isTrue();
assertThat(actual.get(1).reviewed).isTrue();
actual = assertQuery(
newQuery("-is:reviewed").withOption(REVIEWED),
change1);
assertThat(actual.get(0).reviewed).isNull();
actual = assertQuery("reviewedby:" + userId.get());
actual = assertQuery(
newQuery("reviewedby:" + user2.get()).withOption(REVIEWED),
change3, change2);
assertThat(actual.get(0).reviewed).isTrue();
assertThat(actual.get(1).reviewed).isTrue();
} }
protected ChangeInserter newChange( protected ChangeInserter newChange(
@@ -1181,29 +1197,18 @@ public abstract class AbstractQueryChangesTest {
return gApi.changes().query(query.toString()); return gApi.changes().query(query.toString());
} }
protected void assertQuery(Object query, Change... changes) protected List<ChangeInfo> assertQuery(Object query, Change... changes)
throws Exception { throws Exception {
assertQuery(newQuery(query), changes); return assertQuery(newQuery(query), changes);
} }
protected void assertQuery(QueryRequest query, Change... changes) protected List<ChangeInfo> assertQuery(QueryRequest query, Change... changes)
throws Exception { throws Exception {
assertThat(query(query)).named(query.toString()) List<ChangeInfo> result = query.get();
Iterable<Integer> ids = ids(result);
assertThat(ids).named(ids.toString())
.containsExactlyElementsIn(ids(changes)).inOrder(); .containsExactlyElementsIn(ids(changes)).inOrder();
} return result;
protected List<Integer> query(Object query) throws Exception {
return query(newQuery(query));
}
protected static List<Integer> query(QueryRequest query) throws Exception {
return FluentIterable.from(query.get())
.transform(new Function<ChangeInfo, Integer>() {
@Override
public Integer apply(ChangeInfo in) {
return in._number;
}
}).toList();
} }
protected static Iterable<Integer> ids(Change... changes) { protected static Iterable<Integer> ids(Change... changes) {
@@ -1216,6 +1221,16 @@ public abstract class AbstractQueryChangesTest {
}); });
} }
protected static Iterable<Integer> ids(Iterable<ChangeInfo> changes) {
return FluentIterable.from(changes).transform(
new Function<ChangeInfo, Integer>() {
@Override
public Integer apply(ChangeInfo in) {
return in._number;
}
});
}
protected static long lastUpdatedMs(Change c) { protected static long lastUpdatedMs(Change c) {
return c.getLastUpdatedOn().getTime(); return c.getLastUpdatedOn().getTime();
} }