NoteDb: Avoid writing partial change graphs
If we naively turn on notedb.writeChanges without previously running RebuildNoteDb to backfill existing changes, a single ChangeUpdate may end up writing a partial note graph, for example containing a single commit with only a "Topic" field and no other information. Such a partial graph will almost certainly fail to parse; better to avoid writing them out in the first place. Teach NoteDbUpdateManager to skip writing updates unless the first update in the list has a special allowWriteToNewRef. This means writing a change will automatically "turn on" on a per-change basis as soon as a backfill is completed, whether in a running server or in between restarts. There are three cases where we want to allow writing updates to new refs: - Any ChangeDraftUpdate, since having a "partial" draft notes ref doesn't cause parsing to fail, and executing the same update multiple times is idempotent with respect to the note data. - A ChangeUpdate that creates a change for the first time, which is by definition not a partial graph. This is handled in BatchUpdate, which already knows which ChangeUpdates correspond to new changes. - In ChangeRebuilder, which again is guaranteed to write a complete graph. Change-Id: Ic8c6c28e68aef22be7569d2b0cb409eae22e3034
This commit is contained in:
@@ -204,7 +204,9 @@ public abstract class AbstractChangeNotesTest extends GerritBaseTests {
|
||||
|
||||
protected ChangeUpdate newUpdate(Change c, CurrentUser user)
|
||||
throws Exception {
|
||||
return TestChanges.newUpdate(injector, c, user);
|
||||
ChangeUpdate update = TestChanges.newUpdate(injector, c, user);
|
||||
update.setAllowWriteToNewRef(true);
|
||||
return update;
|
||||
}
|
||||
|
||||
protected ChangeNotes newNotes(Change c) throws OrmException {
|
||||
|
||||
@@ -14,13 +14,18 @@
|
||||
|
||||
package com.google.gerrit.testutil;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import com.google.common.base.Joiner;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.gerrit.reviewdb.client.Change;
|
||||
import com.google.gerrit.reviewdb.client.Project;
|
||||
import com.google.gerrit.reviewdb.server.ReviewDb;
|
||||
import com.google.gerrit.reviewdb.server.ReviewDbUtil;
|
||||
import com.google.gerrit.server.PatchLineCommentsUtil;
|
||||
import com.google.gerrit.server.git.GitRepositoryManager;
|
||||
import com.google.gerrit.server.notedb.ChangeBundle;
|
||||
import com.google.gerrit.server.notedb.ChangeNoteUtil;
|
||||
import com.google.gerrit.server.notedb.ChangeNotes;
|
||||
import com.google.gerrit.server.notedb.ChangeRebuilder;
|
||||
import com.google.gerrit.server.schema.DisabledChangesReviewDbWrapper;
|
||||
@@ -29,6 +34,7 @@ import com.google.inject.Provider;
|
||||
import com.google.inject.Singleton;
|
||||
|
||||
import org.eclipse.jgit.errors.RepositoryNotFoundException;
|
||||
import org.eclipse.jgit.lib.Repository;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -41,6 +47,7 @@ public class NoteDbChecker {
|
||||
static final Logger log = LoggerFactory.getLogger(NoteDbChecker.class);
|
||||
|
||||
private final Provider<ReviewDb> dbProvider;
|
||||
private final GitRepositoryManager repoManager;
|
||||
private final TestNotesMigration notesMigration;
|
||||
private final ChangeNotes.Factory notesFactory;
|
||||
private final ChangeRebuilder changeRebuilder;
|
||||
@@ -48,11 +55,13 @@ public class NoteDbChecker {
|
||||
|
||||
@Inject
|
||||
NoteDbChecker(Provider<ReviewDb> dbProvider,
|
||||
GitRepositoryManager repoManager,
|
||||
TestNotesMigration notesMigration,
|
||||
ChangeNotes.Factory notesFactory,
|
||||
ChangeRebuilder changeRebuilder,
|
||||
PatchLineCommentsUtil plcUtil) {
|
||||
this.dbProvider = dbProvider;
|
||||
this.repoManager = repoManager;
|
||||
this.notesMigration = notesMigration;
|
||||
this.notesFactory = notesFactory;
|
||||
this.changeRebuilder = changeRebuilder;
|
||||
@@ -106,6 +115,14 @@ public class NoteDbChecker {
|
||||
checkActual(readExpected(changeIds), new ArrayList<String>());
|
||||
}
|
||||
|
||||
public void assertNoChangeRef(Project.NameKey project, Change.Id changeId)
|
||||
throws Exception {
|
||||
try (Repository repo = repoManager.openMetadataRepository(project)) {
|
||||
assertThat(repo.exactRef(ChangeNoteUtil.changeRefName(changeId)))
|
||||
.isNull();
|
||||
}
|
||||
}
|
||||
|
||||
private List<ChangeBundle> readExpected(Iterable<Change.Id> changeIds)
|
||||
throws Exception {
|
||||
ReviewDb db = unwrapDb();
|
||||
|
||||
Reference in New Issue
Block a user