summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniele Sassoli <danielesassoli@gmail.com>2024-03-04 17:10:48 +0100
committerDaniele Sassoli <danielesassoli@gmail.com>2024-03-07 22:23:29 +0000
commit848a3d8e42902e025251a3a96d2efe7caa0d036e (patch)
treefd3c342c1ae4af64cd9101358debc4c6ae75812d
parentd3d973b5c1d23364d16e497527cf354d65337b46 (diff)
Introduce `notedb.changes.metaRefStreamEventsInTrial` setting
When running in trial, mode Gerrit stores reviews and change metadata in both ReviewDB (DBMS) and NoteDB (Git). Writing to the NoteDB layer implies creating, and updating, meta refs for changes (`/refs/changes/xx/xx/meta`). Whilst the creation of such meta refs is notified via stream events when Gerrit runs fully on NoteDB, Gerrit does not emit ref-updated stream events for those trial updates because they are not part of the batch update of the Git repository This is by design: trial mode is, as the name suggests, a temporary trial state and it might be unwanted to expose an internal, possibly temporary state to the external environment. Introduce the new `notedb.changes.metaRefStreamEventsInTrial` setting to enable notification of /meta ref-updates in trial mode, as any other refs on the stream events channel. IMPORTANT NOTE: The ref-updates in trial mode can be used for logging or tracing purposes, but should not be relied upon for data replication, because of the inherent danger of inconsistency. E.g. when uploading a new patch-set, the ref-update of the patch may fail but not the associated /meta update. Forward-Compatible: checked Release-Notes: Introduce `notedb.changes.metaRefStreamEventsInTrial` setting Bug: Issue 328298006 Change-Id: I691f9908b7c455343aaab1a387a23b8e06fd1a5c
-rw-r--r--Documentation/note-db.txt10
-rw-r--r--java/com/google/gerrit/server/notedb/rebuild/NoteDbMigrator.java6
-rw-r--r--java/com/google/gerrit/server/update/ReviewDbBatchUpdate.java13
-rw-r--r--javatests/com/google/gerrit/acceptance/server/notedb/OnlineNoteDbMigrationIT.java41
4 files changed, 68 insertions, 2 deletions
diff --git a/Documentation/note-db.txt b/Documentation/note-db.txt
index a9b71c1357..b31911fa64 100644
--- a/Documentation/note-db.txt
+++ b/Documentation/note-db.txt
@@ -153,6 +153,16 @@ There are several use cases for trial mode:
link:rest-api-changes.html#get-hashtags[hashtags] without running the full
migration.
+Note that notedb migration and trial mode do not generate ref-updated stream
+events for /meta ref. To enable ref-updates in trial mode for post-migration
+modifications of changes metadata, set
+`noteDb.changes.metaRefStreamEventsInTrial=true`.
+
+Note however that, replication of /meta refs should be disabled until the
+notedb migration has finished its final mode, because, during trial mode,
+change meta refs are not persisted transactionally with the ReviewDB update,
+nor with the patch-set ref update.
+
To continue with the full migration after running the trial migration, use
either the online or offline migration steps as normal. To revert to
ReviewDb-only, remove `noteDb.changes.read` and `noteDb.changes.write` from
diff --git a/java/com/google/gerrit/server/notedb/rebuild/NoteDbMigrator.java b/java/com/google/gerrit/server/notedb/rebuild/NoteDbMigrator.java
index 0781105448..c7fd6af247 100644
--- a/java/com/google/gerrit/server/notedb/rebuild/NoteDbMigrator.java
+++ b/java/com/google/gerrit/server/notedb/rebuild/NoteDbMigrator.java
@@ -124,6 +124,7 @@ public class NoteDbMigrator implements AutoCloseable {
private static final String AUTO_MIGRATE = "autoMigrate";
private static final String TRIAL = "trial";
+ private static final String META_REF_STREAM_EVENTS_IN_TRIAL = "metaRefStreamEventsInTrial";
private static final String SECTION_DATABASE = "database";
private static final String POSTGRESQL = "postgresql";
private static final String URL = "url";
@@ -144,6 +145,11 @@ public class NoteDbMigrator implements AutoCloseable {
return cfg.getBoolean(SECTION_NOTE_DB, NoteDbTable.CHANGES.key(), TRIAL, false);
}
+ public static boolean getEnableMetaRefStreamEventsInTrial(Config cfg) {
+ return cfg.getBoolean(
+ SECTION_NOTE_DB, NoteDbTable.CHANGES.key(), META_REF_STREAM_EVENTS_IN_TRIAL, false);
+ }
+
public static void setTrialMode(Config cfg, boolean trial) {
cfg.setBoolean(SECTION_NOTE_DB, NoteDbTable.CHANGES.key(), TRIAL, trial);
}
diff --git a/java/com/google/gerrit/server/update/ReviewDbBatchUpdate.java b/java/com/google/gerrit/server/update/ReviewDbBatchUpdate.java
index 14307e2889..1218aaea45 100644
--- a/java/com/google/gerrit/server/update/ReviewDbBatchUpdate.java
+++ b/java/com/google/gerrit/server/update/ReviewDbBatchUpdate.java
@@ -59,6 +59,7 @@ import com.google.gerrit.server.notedb.NoteDbUpdateManager;
import com.google.gerrit.server.notedb.NoteDbUpdateManager.MismatchedStateException;
import com.google.gerrit.server.notedb.NotesMigration;
import com.google.gerrit.server.notedb.OnlineProjectsMigrationChecker;
+import com.google.gerrit.server.notedb.rebuild.NoteDbMigrator;
import com.google.gwtorm.server.OrmException;
import com.google.gwtorm.server.SchemaFactory;
import com.google.inject.Inject;
@@ -286,9 +287,10 @@ public class ReviewDbBatchUpdate extends BatchUpdate {
// patch set ref being created means the change was created, or a branch advancing meaning
// some changes were closed.
updates.stream()
- .filter(u -> u.batchRefUpdate != null)
.forEach(
- u -> u.gitRefUpdated.fire(u.project, u.batchRefUpdate, u.getAccount().orElse(null)));
+ u ->
+ u.batchRefUpdatesToFire.forEach(
+ bru -> u.gitRefUpdated.fire(u.project, bru, u.getAccount().orElse(null))));
if (!dryrun) {
for (ReviewDbBatchUpdate u : updates) {
@@ -311,8 +313,10 @@ public class ReviewDbBatchUpdate extends BatchUpdate {
private final NotesMigration notesMigration;
private final OnlineProjectsMigrationChecker onlineProjectsMigrationChecker;
private final ReviewDb db;
+ private final boolean getMetaEventsInTrial;
private final SchemaFactory<ReviewDb> schemaFactory;
private final long skewMs;
+ private final List<BatchRefUpdate> batchRefUpdatesToFire = new ArrayList<>();
@SuppressWarnings("deprecation")
private final List<com.google.common.util.concurrent.CheckedFuture<?, IOException>> indexFutures =
@@ -351,6 +355,7 @@ public class ReviewDbBatchUpdate extends BatchUpdate {
this.db = db;
skewMs = NoteDbChangeState.getReadOnlySkew(cfg);
this.onlineProjectsMigrationChecker = onlineProjectsMigrationChecker;
+ this.getMetaEventsInTrial = NoteDbMigrator.getEnableMetaRefStreamEventsInTrial(cfg);
}
@Override
@@ -433,6 +438,7 @@ public class ReviewDbBatchUpdate extends BatchUpdate {
if (!ok) {
throw new RestApiException("BatchRefUpdate failed: " + batchRefUpdate);
}
+ batchRefUpdatesToFire.add(batchRefUpdate);
}
private List<ChangeTask> executeChangeOps(boolean parallel, boolean dryrun)
@@ -543,6 +549,9 @@ public class ReviewDbBatchUpdate extends BatchUpdate {
"Collected %d objects and %d ref updates to change repo",
objs, changeRefUpdate.getCommands().size());
executeNoteDbUpdate(getRevWalk(), ins, changeRefUpdate);
+ if (getMetaEventsInTrial) {
+ batchRefUpdatesToFire.add(changeRefUpdate);
+ }
}
if (hasAllUsersCommands) {
diff --git a/javatests/com/google/gerrit/acceptance/server/notedb/OnlineNoteDbMigrationIT.java b/javatests/com/google/gerrit/acceptance/server/notedb/OnlineNoteDbMigrationIT.java
index 74fffbddaf..6c2e1acd5d 100644
--- a/javatests/com/google/gerrit/acceptance/server/notedb/OnlineNoteDbMigrationIT.java
+++ b/javatests/com/google/gerrit/acceptance/server/notedb/OnlineNoteDbMigrationIT.java
@@ -44,6 +44,7 @@ import com.google.gerrit.acceptance.PushOneCommit;
import com.google.gerrit.acceptance.Sandboxed;
import com.google.gerrit.acceptance.UseLocalDisk;
import com.google.gerrit.extensions.api.projects.ProjectInput;
+import com.google.gerrit.extensions.events.GitReferenceUpdatedListener;
import com.google.gerrit.extensions.registration.DynamicSet;
import com.google.gerrit.extensions.registration.RegistrationHandle;
import com.google.gerrit.reviewdb.client.Change;
@@ -80,6 +81,7 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.function.Consumer;
+import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.eclipse.jgit.internal.storage.file.FileRepository;
import org.eclipse.jgit.junit.TestRepository;
@@ -122,6 +124,7 @@ public class OnlineNoteDbMigrationIT extends AbstractDaemonTest {
@Inject private Provider<NoteDbMigrator.Builder> migratorBuilderProvider;
@Inject private Sequences sequences;
@Inject private SitePaths sitePaths;
+ @Inject private DynamicSet<GitReferenceUpdatedListener> refUpdateListeners;
private FileBasedConfig noteDbConfig;
private List<RegistrationHandle> addedListeners;
@@ -252,6 +255,26 @@ public class OnlineNoteDbMigrationIT extends AbstractDaemonTest {
}
@Test
+ @GerritConfig(name = "noteDb.changes.metaRefStreamEventsInTrial", value = "true")
+ public void noteDbMetaRefUpdateIsEmittedWhenTrialMode() throws Exception {
+ migrate(b -> b.setTrialMode(true));
+ List<GitReferenceUpdatedListener.Event> eventsForProject = generateStreamEventsForProject();
+
+ assertThat(eventsForProject).hasSize(2);
+ assertThat(eventsForProject.get(0).getRefName()).doesNotContain("meta");
+ assertThat(eventsForProject.get(1).getRefName()).endsWith("meta");
+ }
+
+ @Test
+ public void noteDbMetaRefUpdateIsNotEmittedByDefaultWhenTrialMode() throws Exception {
+ migrate(b -> b.setTrialMode(true));
+ List<GitReferenceUpdatedListener.Event> eventsForProject = generateStreamEventsForProject();
+
+ assertThat(eventsForProject).hasSize(1);
+ assertThat(eventsForProject.get(0).getRefName()).doesNotContain("meta");
+ }
+
+ @Test
public void autoMigrateTrialMode() throws Exception {
PushOneCommit.Result r = createChange();
Change.Id id = r.getChange().getId();
@@ -817,4 +840,22 @@ public class OnlineNoteDbMigrationIT extends AbstractDaemonTest {
}
}
}
+
+ private List<GitReferenceUpdatedListener.Event> generateStreamEventsForProject()
+ throws Exception {
+ RegistrationHandle testListenerHandler = null;
+ try {
+ List<GitReferenceUpdatedListener.Event> emittedEvents = new ArrayList<>();
+ testListenerHandler = refUpdateListeners.add("gerrit", emittedEvents::add);
+ PushOneCommit.Result r = createChange();
+ Change.Id changeId = r.getChange().getId();
+ return emittedEvents.stream()
+ .filter(e -> project.get().equals(e.getProjectName()))
+ .collect(Collectors.toList());
+ } finally {
+ if (testListenerHandler != null) {
+ testListenerHandler.remove();
+ }
+ }
+ }
}