diff options
author | Luca Milanesio <luca.milanesio@gmail.com> | 2023-11-28 15:03:17 +0000 |
---|---|---|
committer | Luca Milanesio <luca.milanesio@gmail.com> | 2023-11-28 15:13:32 +0000 |
commit | 07d8d99b20eedf99f15dbf1289b661792e1bfda0 (patch) | |
tree | 7bbb2498ab34f828e74f12dbd2d770cc341e99ea | |
parent | d0ef111b9b0d8e64326fc198154d4f23b99a5f54 (diff) |
Revert "Remove old change index schema versions and clean up the code"
This reverts commit 714371d91b51e686e7c3caca0c5d7eab9e24bce2.
Forward-Compatible: checked
Release-Notes: skip
Change-Id: Icd74be21ab64a7fd50aa788fec831907f9f2acf0
5 files changed, 232 insertions, 13 deletions
diff --git a/java/com/google/gerrit/server/DraftCommentsReader.java b/java/com/google/gerrit/server/DraftCommentsReader.java index 11b72635db..1eea228ccc 100644 --- a/java/com/google/gerrit/server/DraftCommentsReader.java +++ b/java/com/google/gerrit/server/DraftCommentsReader.java @@ -59,6 +59,9 @@ public interface DraftCommentsReader { */ List<HumanComment> getDraftsByChangeForAllAuthors(ChangeNotes notes); + /** Returns all users that have any draft comments on the provided change. */ + Set<Account.Id> getUsersWithDrafts(ChangeNotes changeNotes); + /** Returns all changes that contain draft comments of {@code author}. */ Set<Change.Id> getChangesWithDrafts(Account.Id author); } diff --git a/java/com/google/gerrit/server/index/change/ChangeField.java b/java/com/google/gerrit/server/index/change/ChangeField.java index 43bfe39310..38c2e9fdeb 100644 --- a/java/com/google/gerrit/server/index/change/ChangeField.java +++ b/java/com/google/gerrit/server/index/change/ChangeField.java @@ -23,6 +23,7 @@ import static java.util.stream.Collectors.joining; import static java.util.stream.Collectors.toList; import static java.util.stream.Collectors.toSet; +import com.google.auto.value.AutoValue; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Splitter; import com.google.common.collect.HashBasedTable; @@ -30,10 +31,12 @@ import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableTable; +import com.google.common.collect.Iterables; import com.google.common.collect.Lists; import com.google.common.collect.Table; import com.google.common.flogger.FluentLogger; import com.google.common.io.Files; +import com.google.common.primitives.Ints; import com.google.common.primitives.Longs; import com.google.common.reflect.TypeToken; import com.google.gerrit.common.Nullable; @@ -62,6 +65,7 @@ import com.google.gerrit.proto.Entities; import com.google.gerrit.server.ReviewerByEmailSet; import com.google.gerrit.server.ReviewerSet; import com.google.gerrit.server.cache.proto.Cache; +import com.google.gerrit.server.config.AllUsersName; import com.google.gerrit.server.index.change.StalenessChecker.RefStatePattern; import com.google.gerrit.server.notedb.ReviewerStateInternal; import com.google.gerrit.server.notedb.SubmitRequirementProtoConverter; @@ -107,6 +111,8 @@ import org.eclipse.jgit.lib.PersonIdent; public class ChangeField { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); + public static final int NO_ASSIGNEE = -1; + private static final Gson GSON = OutputFormat.JSON_COMPACT.newGson(); /** @@ -498,6 +504,16 @@ public class ChangeField { ATTENTION_SET_FULL_SPEC = ATTENTION_SET_FULL_FIELD.storedOnly(ChangeQueryBuilder.FIELD_ATTENTION_SET_FULL); + /** The user assigned to the change. */ + // The getter always returns NO_ASSIGNEE, since assignee field is deprecated. + @Deprecated + public static final IndexedField<ChangeData, Integer> ASSIGNEE_FIELD = + IndexedField.<ChangeData>integerBuilder("Assignee").build(changeGetter(c -> NO_ASSIGNEE)); + + @Deprecated + public static final IndexedField<ChangeData, Integer>.SearchSpec ASSIGNEE_SPEC = + ASSIGNEE_FIELD.integer(ChangeQueryBuilder.FIELD_ASSIGNEE); + /** Reviewer(s) associated with the change. */ public static final IndexedField<ChangeData, Iterable<String>> REVIEWER_FIELD = IndexedField.<ChangeData>iterableStringBuilder("Reviewer") @@ -1252,6 +1268,31 @@ public class ChangeField { public static final IndexedField<ChangeData, Iterable<Integer>>.SearchSpec COMMENTBY_SPEC = COMMENTBY_FIELD.integer(ChangeQueryBuilder.FIELD_COMMENTBY); + /** Star labels on this change in the format: <account-id> */ + public static final IndexedField<ChangeData, Iterable<String>> STAR_FIELD = + IndexedField.<ChangeData>iterableStringBuilder("Star") + .stored() + .build( + cd -> + Iterables.transform( + cd.stars(), accountId -> StarField.create(accountId).toString()), + (cd, field) -> + cd.setStars( + StreamSupport.stream(field.spliterator(), false) + .map(f -> StarField.parse(f).accountId()) + .collect(toImmutableList()))); + + public static final IndexedField<ChangeData, Iterable<String>>.SearchSpec STAR_SPEC = + STAR_FIELD.exact(ChangeQueryBuilder.FIELD_STAR); + + /** Users that have starred the change with any label. */ + public static final IndexedField<ChangeData, Iterable<Integer>> STARBY_FIELD = + IndexedField.<ChangeData>iterableIntegerBuilder("StarBy") + .build(cd -> Iterables.transform(cd.stars(), Account.Id::get)); + + public static final IndexedField<ChangeData, Iterable<Integer>>.SearchSpec STARBY_SPEC = + STARBY_FIELD.integer(ChangeQueryBuilder.FIELD_STARBY); + /** Opaque group identifiers for this change's patch sets. */ public static final IndexedField<ChangeData, Iterable<String>> GROUP_FIELD = IndexedField.<ChangeData>iterableStringBuilder("Group") @@ -1289,6 +1330,14 @@ public class ChangeField { public static final IndexedField<ChangeData, Iterable<Integer>>.SearchSpec EDITBY_SPEC = EDITBY_FIELD.integer(ChangeQueryBuilder.FIELD_EDITBY); + /** Users who have draft comments on this change. */ + public static final IndexedField<ChangeData, Iterable<Integer>> DRAFTBY_FIELD = + IndexedField.<ChangeData>iterableIntegerBuilder("DraftBy") + .build(cd -> cd.draftsByUser().stream().map(Account.Id::get).collect(toSet())); + + public static final IndexedField<ChangeData, Iterable<Integer>>.SearchSpec DRAFTBY_SPEC = + DRAFTBY_FIELD.integer(ChangeQueryBuilder.FIELD_DRAFTBY); + public static final Integer NOT_REVIEWED = -1; /** @@ -1647,6 +1696,12 @@ public class ChangeField { RefStatePattern.create( RefNames.REFS_USERS + "*/" + RefNames.EDIT_PREFIX + id + "/*") .toByteArray(project)); + result.add( + RefStatePattern.create(RefNames.refsStarredChangesPrefix(id) + "*") + .toByteArray(allUsers(cd))); + result.add( + RefStatePattern.create(RefNames.refsDraftCommentsPrefix(id) + "*") + .toByteArray(allUsers(cd))); return result; }, (cd, field) -> cd.setRefStatePatterns(field)); @@ -1715,6 +1770,10 @@ public class ChangeField { return in -> in.change() != null ? func.apply(in.change()) : null; } + private static AllUsersName allUsers(ChangeData cd) { + return cd.getAllUsersNameForIndexing(); + } + private static String truncateStringValueToMaxTermLength(String str) { return truncateStringValue(str, MAX_TERM_LENGTH); } @@ -1756,4 +1815,45 @@ public class ChangeField { } return str; } + + @AutoValue + abstract static class StarField { + private static final String SEPARATOR = ":"; + + @Nullable + static StarField parse(String s) { + Integer id; + int p = s.indexOf(SEPARATOR); + if (p >= 0) { + id = Ints.tryParse(s.substring(0, p)); + } else { + // NOTE: This code branch should not be removed. This code is used internally by Google and + // must not be changed without approval from a Google contributor. In + // 992877d06d3492f78a3b189eb5579ddb86b9f0da we accidentally changed index writing to write + // <account_id> instead of <account_id>:star. As some servers have picked that up and wrote + // index entries with the short format, we should keep support its parsing. + id = Ints.tryParse(s); + } + if (id == null) { + return null; + } + return create(Account.id(id)); + } + + static StarField create(Account.Id accountId) { + return new AutoValue_ChangeField_StarField(accountId); + } + + public abstract Account.Id accountId(); + + @Override + public final String toString() { + // NOTE: The ":star" addition is used internally by Google and must not be removed without + // approval from a Google contributor. This method is used for writing change index data. + // Historically, we supported different kinds of labels, which were stored in this + // format, with "star" being the only label in use. This label addition stayed in order to + // keep the index format consistent while removing the star-label support. + return accountId() + SEPARATOR + "star"; + } + } } diff --git a/java/com/google/gerrit/server/index/change/ChangeSchemaDefinitions.java b/java/com/google/gerrit/server/index/change/ChangeSchemaDefinitions.java index 86c8986a2c..3d48907702 100644 --- a/java/com/google/gerrit/server/index/change/ChangeSchemaDefinitions.java +++ b/java/com/google/gerrit/server/index/change/ChangeSchemaDefinitions.java @@ -29,13 +29,15 @@ import com.google.gerrit.server.query.change.ChangeData; * com.google.gerrit.index.IndexUpgradeValidator}. */ public class ChangeSchemaDefinitions extends SchemaDefinitions<ChangeData> { + /** Added new field {@link ChangeField#IS_SUBMITTABLE_SPEC} based on submit requirements. */ @Deprecated - static final Schema<ChangeData> V84 = + static final Schema<ChangeData> V74 = schema( - /* version= */ 84, + /* version= */ 74, ImmutableList.<IndexedField<ChangeData, ?>>of( ChangeField.ADDED_LINES_FIELD, ChangeField.APPROVAL_FIELD, + ChangeField.ASSIGNEE_FIELD, ChangeField.ATTENTION_SET_FULL_FIELD, ChangeField.ATTENTION_SET_USERS_COUNT_FIELD, ChangeField.ATTENTION_SET_USERS_FIELD, @@ -50,17 +52,15 @@ public class ChangeSchemaDefinitions extends SchemaDefinitions<ChangeData> { ChangeField.COMMITTER_PARTS_FIELD, ChangeField.COMMIT_FIELD, ChangeField.COMMIT_MESSAGE_FIELD, - ChangeField.COMMIT_MESSAGE_EXACT_FIELD, - ChangeField.CUSTOM_KEYED_VALUES_FIELD, ChangeField.DELETED_LINES_FIELD, ChangeField.DELTA_LINES_FIELD, ChangeField.DIRECTORY_FIELD, + ChangeField.DRAFTBY_FIELD, ChangeField.EDITBY_FIELD, ChangeField.EXACT_AUTHOR_FIELD, ChangeField.EXACT_COMMITTER_FIELD, ChangeField.EXTENSION_FIELD, ChangeField.FILE_PART_FIELD, - ChangeField.FOOTER_NAME_FIELD, ChangeField.FOOTER_FIELD, ChangeField.GROUP_FIELD, ChangeField.HASHTAG_CASE_AWARE_FIELD, @@ -87,12 +87,13 @@ public class ChangeSchemaDefinitions extends SchemaDefinitions<ChangeData> { ChangeField.REVIEWEDBY_FIELD, ChangeField.REVIEWER_BY_EMAIL_FIELD, ChangeField.REVIEWER_FIELD, + ChangeField.STARBY_FIELD, ChangeField.STARTED_FIELD, + ChangeField.STAR_FIELD, ChangeField.STATUS_FIELD, ChangeField.STORED_SUBMIT_RECORD_LENIENT_FIELD, ChangeField.STORED_SUBMIT_RECORD_STRICT_FIELD, ChangeField.STORED_SUBMIT_REQUIREMENTS_FIELD, - ChangeField.SUBJECT_FIELD, ChangeField.SUBMISSIONID_FIELD, ChangeField.SUBMIT_RECORD_FIELD, ChangeField.SUBMIT_RULE_RESULT_FIELD, @@ -106,6 +107,7 @@ public class ChangeSchemaDefinitions extends SchemaDefinitions<ChangeData> { ImmutableList.<IndexedField<ChangeData, ?>.SearchSpec>of( ChangeField.ADDED_LINES_SPEC, ChangeField.APPROVAL_SPEC, + ChangeField.ASSIGNEE_SPEC, ChangeField.ATTENTION_SET_FULL_SPEC, ChangeField.ATTENTION_SET_USERS, ChangeField.ATTENTION_SET_USERS_COUNT, @@ -119,12 +121,11 @@ public class ChangeSchemaDefinitions extends SchemaDefinitions<ChangeData> { ChangeField.COMMENT_SPEC, ChangeField.COMMITTER_PARTS_SPEC, ChangeField.COMMIT_MESSAGE, - ChangeField.COMMIT_MESSAGE_EXACT, ChangeField.COMMIT_SPEC, - ChangeField.CUSTOM_KEYED_VALUES_SPEC, ChangeField.DELETED_LINES_SPEC, ChangeField.DELTA_LINES_SPEC, ChangeField.DIRECTORY_SPEC, + ChangeField.DRAFTBY_SPEC, ChangeField.EDITBY_SPEC, ChangeField.EXACT_AUTHOR_SPEC, ChangeField.EXACT_COMMITTER_SPEC, @@ -132,7 +133,6 @@ public class ChangeSchemaDefinitions extends SchemaDefinitions<ChangeData> { ChangeField.EXACT_TOPIC, ChangeField.EXTENSION_SPEC, ChangeField.FILE_PART_SPEC, - ChangeField.FOOTER_NAME, ChangeField.FOOTER_SPEC, ChangeField.FUZZY_HASHTAG, ChangeField.FUZZY_TOPIC, @@ -152,9 +152,6 @@ public class ChangeSchemaDefinitions extends SchemaDefinitions<ChangeData> { ChangeField.PATH_SPEC, ChangeField.PENDING_REVIEWER_BY_EMAIL, ChangeField.PENDING_REVIEWER_SPEC, - ChangeField.PREFIX_HASHTAG, - ChangeField.PREFIX_TOPIC, - ChangeField.PREFIX_SUBJECT_SPEC, ChangeField.PRIVATE_SPEC, ChangeField.PROJECTS_SPEC, ChangeField.PROJECT_SPEC, @@ -165,12 +162,13 @@ public class ChangeSchemaDefinitions extends SchemaDefinitions<ChangeData> { ChangeField.REVIEWEDBY_SPEC, ChangeField.REVIEWER_BY_EMAIL, ChangeField.REVIEWER_SPEC, + ChangeField.STARBY_SPEC, ChangeField.STARTED_SPEC, + ChangeField.STAR_SPEC, ChangeField.STATUS_SPEC, ChangeField.STORED_SUBMIT_RECORD_LENIENT_SPEC, ChangeField.STORED_SUBMIT_RECORD_STRICT_SPEC, ChangeField.STORED_SUBMIT_REQUIREMENTS_SPEC, - ChangeField.SUBJECT_SPEC, ChangeField.SUBMISSIONID_SPEC, ChangeField.SUBMIT_RECORD_SPEC, ChangeField.SUBMIT_RULE_RESULT_SPEC, @@ -181,7 +179,87 @@ public class ChangeSchemaDefinitions extends SchemaDefinitions<ChangeData> { ChangeField.UPLOADER_SPEC, ChangeField.WIP_SPEC)); + /** + * Added new field {@link ChangeField#PREFIX_HASHTAG} and {@link ChangeField#PREFIX_TOPIC} to + * allow easier search for topics. + */ + @Deprecated + static final Schema<ChangeData> V75 = + new Schema.Builder<ChangeData>() + .add(V74) + .addSearchSpecs(ChangeField.PREFIX_HASHTAG) + .addSearchSpecs(ChangeField.PREFIX_TOPIC) + .build(); + + /** Added new field {@link ChangeField#FOOTER_NAME}. */ + @Deprecated + static final Schema<ChangeData> V76 = + new Schema.Builder<ChangeData>() + .add(V75) + .addIndexedFields(ChangeField.FOOTER_NAME_FIELD) + .addSearchSpecs(ChangeField.FOOTER_NAME) + .build(); + + /** Added new field {@link ChangeField#COMMIT_MESSAGE_EXACT}. */ + @Deprecated + static final Schema<ChangeData> V77 = + new Schema.Builder<ChangeData>() + .add(V76) + .addIndexedFields(ChangeField.COMMIT_MESSAGE_EXACT_FIELD) + .addSearchSpecs(ChangeField.COMMIT_MESSAGE_EXACT) + .build(); + + // Upgrade Lucene to 7.x requires reindexing. + @Deprecated static final Schema<ChangeData> V78 = schema(V77); + + /** Remove draft and star fields. */ + @Deprecated + static final Schema<ChangeData> V79 = + new Schema.Builder<ChangeData>() + .add(V78) + .remove(ChangeField.STAR_SPEC, ChangeField.STARBY_SPEC, ChangeField.DRAFTBY_SPEC) + .remove(ChangeField.STAR_FIELD, ChangeField.STARBY_FIELD, ChangeField.DRAFTBY_FIELD) + .build(); + + /** Add subject field. */ + @Deprecated + static final Schema<ChangeData> V80 = + new Schema.Builder<ChangeData>() + .add(V79) + .addIndexedFields(ChangeField.SUBJECT_FIELD) + .addSearchSpecs(ChangeField.SUBJECT_SPEC) + .build(); + + /** Add prefixsubject field. */ + @Deprecated + static final Schema<ChangeData> V81 = + new Schema.Builder<ChangeData>() + .add(V80) + .addSearchSpecs(ChangeField.PREFIX_SUBJECT_SPEC) + .build(); + + /** Remove assignee field. */ + @Deprecated + static final Schema<ChangeData> V82 = + new Schema.Builder<ChangeData>() + .add(V81) + .remove(ChangeField.ASSIGNEE_SPEC) + .remove(ChangeField.ASSIGNEE_FIELD) + .build(); + + /** Upgrade Lucene to 8.x requires reindexing. */ + @Deprecated static final Schema<ChangeData> V83 = schema(V82); + + @Deprecated + static final Schema<ChangeData> V84 = + new Schema.Builder<ChangeData>() + .add(V83) + .addIndexedFields(ChangeField.CUSTOM_KEYED_VALUES_FIELD) + .addSearchSpecs(ChangeField.CUSTOM_KEYED_VALUES_SPEC) + .build(); + /** Upgrade Lucene to 9.x requires reindexing. */ + @SuppressWarnings("deprecation") static final Schema<ChangeData> V85 = schema(V84); /** diff --git a/java/com/google/gerrit/server/notedb/DraftCommentsNotesReader.java b/java/com/google/gerrit/server/notedb/DraftCommentsNotesReader.java index 8563ec3b41..27c59f968f 100644 --- a/java/com/google/gerrit/server/notedb/DraftCommentsNotesReader.java +++ b/java/com/google/gerrit/server/notedb/DraftCommentsNotesReader.java @@ -95,6 +95,25 @@ public class DraftCommentsNotesReader implements DraftCommentsReader { } @Override + public Set<Account.Id> getUsersWithDrafts(ChangeNotes changeNotes) { + Set<Account.Id> res = new HashSet<>(); + for (Ref ref : getDraftRefs(changeNotes)) { + Account.Id account = Account.Id.fromRefSuffix(ref.getName()); + if (account != null + // Double-check that any drafts exist for this user after + // filtering out zombies. If some but not all drafts in the ref + // were zombies, the returned Ref still includes those zombies; + // this is suboptimal, but is ok for the purposes of + // draftsByUser(), and easier than trying to rebuild the change at + // this point. + && !changeNotes.getDraftComments(account, ref).isEmpty()) { + res.add(account); + } + } + return res; + } + + @Override public Set<Change.Id> getChangesWithDrafts(Account.Id author) { Set<Change.Id> changes = new HashSet<>(); try (Repository repo = repoManager.openRepository(allUsers)) { diff --git a/java/com/google/gerrit/server/query/change/ChangeData.java b/java/com/google/gerrit/server/query/change/ChangeData.java index 3c774131b3..0c02920cb0 100644 --- a/java/com/google/gerrit/server/query/change/ChangeData.java +++ b/java/com/google/gerrit/server/query/change/ChangeData.java @@ -64,6 +64,7 @@ import com.google.gerrit.index.RefState; import com.google.gerrit.server.ChangeMessagesUtil; import com.google.gerrit.server.CommentsUtil; import com.google.gerrit.server.CurrentUser; +import com.google.gerrit.server.DraftCommentsReader; import com.google.gerrit.server.PatchSetUtil; import com.google.gerrit.server.ReviewerByEmailSet; import com.google.gerrit.server.ReviewerSet; @@ -334,6 +335,7 @@ public class ChangeData { null, null, null, + null, serverId, virtualIdAlgo, false, @@ -360,6 +362,7 @@ public class ChangeData { private final ChangeNotes.Factory notesFactory; private final CommentsUtil commentsUtil; + private final DraftCommentsReader draftCommentsReader; private final GitRepositoryManager repoManager; private final MergeUtilFactory mergeUtilFactory; private final MergeabilityCache mergeabilityCache; @@ -455,6 +458,7 @@ public class ChangeData { ChangeMessagesUtil cmUtil, ChangeNotes.Factory notesFactory, CommentsUtil commentsUtil, + DraftCommentsReader draftCommentsReader, GitRepositoryManager repoManager, MergeUtilFactory mergeUtilFactory, MergeabilityCache mergeabilityCache, @@ -479,6 +483,7 @@ public class ChangeData { this.cmUtil = cmUtil; this.notesFactory = notesFactory; this.commentsUtil = commentsUtil; + this.draftCommentsReader = draftCommentsReader; this.repoManager = repoManager; this.mergeUtilFactory = mergeUtilFactory; this.mergeabilityCache = mergeabilityCache; @@ -1317,6 +1322,20 @@ public class ChangeData { return editRefsByUser; } + public Set<Account.Id> draftsByUser() { + if (usersWithDrafts == null) { + if (!lazyload()) { + return Collections.emptySet(); + } + Change c = change(); + if (c == null) { + return Collections.emptySet(); + } + usersWithDrafts = draftCommentsReader.getUsersWithDrafts(notes()); + } + return usersWithDrafts; + } + public boolean isReviewedBy(Account.Id accountId) { return reviewedBy().contains(accountId); } |