Trigger GitReferenceUpdated event when account or change sequence is updated
This allows to replicate updates to the refs/sequences/* branches in All-Users and All-Projects. Replicating these refs is not needed for Gerrit slaves (since they do not create new accounts or changes) but replicating these refs may be wanted if the replication target is a Gerrit backup server. Change-Id: Ib1d21a646d89b2e774dc9d50574eb990b8d79ece Signed-off-by: Edwin Kempin <ekempin@google.com>
This commit is contained in:
parent
02e281d9d3
commit
54c04d380d
@ -252,7 +252,8 @@ public class AccountIT extends AbstractDaemonTest {
|
|||||||
Account.Id accountId = create(2); // account creation + external ID creation
|
Account.Id accountId = create(2); // account creation + external ID creation
|
||||||
refUpdateCounter.assertRefUpdateFor(
|
refUpdateCounter.assertRefUpdateFor(
|
||||||
RefUpdateCounter.projectRef(allUsers, RefNames.refsUsers(accountId)),
|
RefUpdateCounter.projectRef(allUsers, RefNames.refsUsers(accountId)),
|
||||||
RefUpdateCounter.projectRef(allUsers, RefNames.REFS_EXTERNAL_IDS));
|
RefUpdateCounter.projectRef(allUsers, RefNames.REFS_EXTERNAL_IDS),
|
||||||
|
RefUpdateCounter.projectRef(allUsers, RefNames.REFS_SEQUENCES + Sequences.NAME_ACCOUNTS));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -264,6 +265,9 @@ public class AccountIT extends AbstractDaemonTest {
|
|||||||
RefUpdateCounter.projectRef(allUsers, RefNames.refsUsers(accountId)),
|
RefUpdateCounter.projectRef(allUsers, RefNames.refsUsers(accountId)),
|
||||||
2,
|
2,
|
||||||
RefUpdateCounter.projectRef(allUsers, RefNames.REFS_EXTERNAL_IDS),
|
RefUpdateCounter.projectRef(allUsers, RefNames.REFS_EXTERNAL_IDS),
|
||||||
|
1,
|
||||||
|
RefUpdateCounter.projectRef(
|
||||||
|
allUsers, RefNames.REFS_SEQUENCES + Sequences.NAME_ACCOUNTS),
|
||||||
1));
|
1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,6 +17,7 @@ package com.google.gerrit.pgm.init.api;
|
|||||||
import com.google.gerrit.reviewdb.client.Project;
|
import com.google.gerrit.reviewdb.client.Project;
|
||||||
import com.google.gerrit.reviewdb.server.ReviewDb;
|
import com.google.gerrit.reviewdb.server.ReviewDb;
|
||||||
import com.google.gerrit.server.Sequences;
|
import com.google.gerrit.server.Sequences;
|
||||||
|
import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
|
||||||
import com.google.gerrit.server.git.GitRepositoryManager;
|
import com.google.gerrit.server.git.GitRepositoryManager;
|
||||||
import com.google.gerrit.server.notedb.RepoSequence;
|
import com.google.gerrit.server.notedb.RepoSequence;
|
||||||
import com.google.gwtorm.server.OrmException;
|
import com.google.gwtorm.server.OrmException;
|
||||||
@ -40,6 +41,7 @@ public class SequencesOnInit {
|
|||||||
RepoSequence accountSeq =
|
RepoSequence accountSeq =
|
||||||
new RepoSequence(
|
new RepoSequence(
|
||||||
repoManager,
|
repoManager,
|
||||||
|
GitReferenceUpdated.DISABLED,
|
||||||
new Project.NameKey(allUsersName.get()),
|
new Project.NameKey(allUsersName.get()),
|
||||||
Sequences.NAME_ACCOUNTS,
|
Sequences.NAME_ACCOUNTS,
|
||||||
accountSeed,
|
accountSeed,
|
||||||
|
@ -27,6 +27,7 @@ import com.google.gerrit.reviewdb.server.ReviewDb;
|
|||||||
import com.google.gerrit.server.config.AllProjectsName;
|
import com.google.gerrit.server.config.AllProjectsName;
|
||||||
import com.google.gerrit.server.config.AllUsersName;
|
import com.google.gerrit.server.config.AllUsersName;
|
||||||
import com.google.gerrit.server.config.GerritServerConfig;
|
import com.google.gerrit.server.config.GerritServerConfig;
|
||||||
|
import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
|
||||||
import com.google.gerrit.server.git.GitRepositoryManager;
|
import com.google.gerrit.server.git.GitRepositoryManager;
|
||||||
import com.google.gerrit.server.notedb.NotesMigration;
|
import com.google.gerrit.server.notedb.NotesMigration;
|
||||||
import com.google.gerrit.server.notedb.RepoSequence;
|
import com.google.gerrit.server.notedb.RepoSequence;
|
||||||
@ -64,6 +65,7 @@ public class Sequences {
|
|||||||
Provider<ReviewDb> db,
|
Provider<ReviewDb> db,
|
||||||
NotesMigration migration,
|
NotesMigration migration,
|
||||||
GitRepositoryManager repoManager,
|
GitRepositoryManager repoManager,
|
||||||
|
GitReferenceUpdated gitRefUpdated,
|
||||||
AllProjectsName allProjects,
|
AllProjectsName allProjects,
|
||||||
AllUsersName allUsers,
|
AllUsersName allUsers,
|
||||||
MetricMaker metrics) {
|
MetricMaker metrics) {
|
||||||
@ -74,6 +76,7 @@ public class Sequences {
|
|||||||
accountSeq =
|
accountSeq =
|
||||||
new RepoSequence(
|
new RepoSequence(
|
||||||
repoManager,
|
repoManager,
|
||||||
|
gitRefUpdated,
|
||||||
allUsers,
|
allUsers,
|
||||||
NAME_ACCOUNTS,
|
NAME_ACCOUNTS,
|
||||||
() -> ReviewDb.FIRST_ACCOUNT_ID,
|
() -> ReviewDb.FIRST_ACCOUNT_ID,
|
||||||
@ -84,7 +87,8 @@ public class Sequences {
|
|||||||
RepoSequence.Seed changeSeed = () -> db.get().nextChangeId() + gap;
|
RepoSequence.Seed changeSeed = () -> db.get().nextChangeId() + gap;
|
||||||
int changeBatchSize = cfg.getInt("noteDb", "changes", "sequenceBatchSize", 20);
|
int changeBatchSize = cfg.getInt("noteDb", "changes", "sequenceBatchSize", 20);
|
||||||
changeSeq =
|
changeSeq =
|
||||||
new RepoSequence(repoManager, allProjects, NAME_CHANGES, changeSeed, changeBatchSize);
|
new RepoSequence(
|
||||||
|
repoManager, gitRefUpdated, allProjects, NAME_CHANGES, changeSeed, changeBatchSize);
|
||||||
|
|
||||||
nextIdLatency =
|
nextIdLatency =
|
||||||
metrics.newTimer(
|
metrics.newTimer(
|
||||||
|
@ -36,6 +36,7 @@ import com.google.common.util.concurrent.Runnables;
|
|||||||
import com.google.gerrit.common.Nullable;
|
import com.google.gerrit.common.Nullable;
|
||||||
import com.google.gerrit.reviewdb.client.Project;
|
import com.google.gerrit.reviewdb.client.Project;
|
||||||
import com.google.gerrit.reviewdb.client.RefNames;
|
import com.google.gerrit.reviewdb.client.RefNames;
|
||||||
|
import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
|
||||||
import com.google.gerrit.server.git.GitRepositoryManager;
|
import com.google.gerrit.server.git.GitRepositoryManager;
|
||||||
import com.google.gwtorm.server.OrmException;
|
import com.google.gwtorm.server.OrmException;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -86,6 +87,7 @@ public class RepoSequence {
|
|||||||
private static final Retryer<RefUpdate.Result> RETRYER = retryerBuilder().build();
|
private static final Retryer<RefUpdate.Result> RETRYER = retryerBuilder().build();
|
||||||
|
|
||||||
private final GitRepositoryManager repoManager;
|
private final GitRepositoryManager repoManager;
|
||||||
|
private final GitReferenceUpdated gitRefUpdated;
|
||||||
private final Project.NameKey projectName;
|
private final Project.NameKey projectName;
|
||||||
private final String refName;
|
private final String refName;
|
||||||
private final Seed seed;
|
private final Seed seed;
|
||||||
@ -103,16 +105,26 @@ public class RepoSequence {
|
|||||||
|
|
||||||
public RepoSequence(
|
public RepoSequence(
|
||||||
GitRepositoryManager repoManager,
|
GitRepositoryManager repoManager,
|
||||||
|
GitReferenceUpdated gitRefUpdated,
|
||||||
Project.NameKey projectName,
|
Project.NameKey projectName,
|
||||||
String name,
|
String name,
|
||||||
Seed seed,
|
Seed seed,
|
||||||
int batchSize) {
|
int batchSize) {
|
||||||
this(repoManager, projectName, name, seed, batchSize, Runnables.doNothing(), RETRYER);
|
this(
|
||||||
|
repoManager,
|
||||||
|
gitRefUpdated,
|
||||||
|
projectName,
|
||||||
|
name,
|
||||||
|
seed,
|
||||||
|
batchSize,
|
||||||
|
Runnables.doNothing(),
|
||||||
|
RETRYER);
|
||||||
}
|
}
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
RepoSequence(
|
RepoSequence(
|
||||||
GitRepositoryManager repoManager,
|
GitRepositoryManager repoManager,
|
||||||
|
GitReferenceUpdated gitRefUpdated,
|
||||||
Project.NameKey projectName,
|
Project.NameKey projectName,
|
||||||
String name,
|
String name,
|
||||||
Seed seed,
|
Seed seed,
|
||||||
@ -120,6 +132,7 @@ public class RepoSequence {
|
|||||||
Runnable afterReadRef,
|
Runnable afterReadRef,
|
||||||
Retryer<RefUpdate.Result> retryer) {
|
Retryer<RefUpdate.Result> retryer) {
|
||||||
this.repoManager = checkNotNull(repoManager, "repoManager");
|
this.repoManager = checkNotNull(repoManager, "repoManager");
|
||||||
|
this.gitRefUpdated = checkNotNull(gitRefUpdated, "gitRefUpdated");
|
||||||
this.projectName = checkNotNull(projectName, "projectName");
|
this.projectName = checkNotNull(projectName, "projectName");
|
||||||
|
|
||||||
checkArgument(
|
checkArgument(
|
||||||
@ -213,11 +226,15 @@ public class RepoSequence {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void checkResult(RefUpdate.Result result) throws OrmException {
|
private void checkResult(RefUpdate.Result result) throws OrmException {
|
||||||
if (result != RefUpdate.Result.NEW && result != RefUpdate.Result.FORCED) {
|
if (!refUpdated(result)) {
|
||||||
throw new OrmException("failed to update " + refName + ": " + result);
|
throw new OrmException("failed to update " + refName + ": " + result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean refUpdated(RefUpdate.Result result) {
|
||||||
|
return result == RefUpdate.Result.NEW || result == RefUpdate.Result.FORCED;
|
||||||
|
}
|
||||||
|
|
||||||
private class TryAcquire implements Callable<RefUpdate.Result> {
|
private class TryAcquire implements Callable<RefUpdate.Result> {
|
||||||
private final Repository repo;
|
private final Repository repo;
|
||||||
private final RevWalk rw;
|
private final RevWalk rw;
|
||||||
@ -275,7 +292,11 @@ public class RepoSequence {
|
|||||||
}
|
}
|
||||||
ru.setNewObjectId(newId);
|
ru.setNewObjectId(newId);
|
||||||
ru.setForceUpdate(true); // Required for non-commitish updates.
|
ru.setForceUpdate(true); // Required for non-commitish updates.
|
||||||
return ru.update(rw);
|
RefUpdate.Result result = ru.update(rw);
|
||||||
|
if (refUpdated(result)) {
|
||||||
|
gitRefUpdated.fire(projectName, ru, null);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ReceiveCommand storeNew(ObjectInserter ins, String name, int val)
|
public static ReceiveCommand storeNew(ObjectInserter ins, String name, int val)
|
||||||
|
@ -51,6 +51,7 @@ import com.google.gerrit.server.Sequences;
|
|||||||
import com.google.gerrit.server.config.AllProjectsName;
|
import com.google.gerrit.server.config.AllProjectsName;
|
||||||
import com.google.gerrit.server.config.GerritServerConfigProvider;
|
import com.google.gerrit.server.config.GerritServerConfigProvider;
|
||||||
import com.google.gerrit.server.config.SitePaths;
|
import com.google.gerrit.server.config.SitePaths;
|
||||||
|
import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
|
||||||
import com.google.gerrit.server.git.GitRepositoryManager;
|
import com.google.gerrit.server.git.GitRepositoryManager;
|
||||||
import com.google.gerrit.server.git.LockFailureException;
|
import com.google.gerrit.server.git.LockFailureException;
|
||||||
import com.google.gerrit.server.git.WorkQueue;
|
import com.google.gerrit.server.git.WorkQueue;
|
||||||
@ -505,6 +506,7 @@ public class NoteDbMigrator implements AutoCloseable {
|
|||||||
RepoSequence seq =
|
RepoSequence seq =
|
||||||
new RepoSequence(
|
new RepoSequence(
|
||||||
repoManager,
|
repoManager,
|
||||||
|
GitReferenceUpdated.DISABLED,
|
||||||
allProjects,
|
allProjects,
|
||||||
Sequences.NAME_CHANGES,
|
Sequences.NAME_CHANGES,
|
||||||
// If sequenceGap is 0, this writes into the sequence ref the same ID that is returned
|
// If sequenceGap is 0, this writes into the sequence ref the same ID that is returned
|
||||||
|
@ -17,6 +17,7 @@ package com.google.gerrit.server.schema;
|
|||||||
import com.google.gerrit.reviewdb.server.ReviewDb;
|
import com.google.gerrit.reviewdb.server.ReviewDb;
|
||||||
import com.google.gerrit.server.Sequences;
|
import com.google.gerrit.server.Sequences;
|
||||||
import com.google.gerrit.server.config.AllUsersName;
|
import com.google.gerrit.server.config.AllUsersName;
|
||||||
|
import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
|
||||||
import com.google.gerrit.server.git.GitRepositoryManager;
|
import com.google.gerrit.server.git.GitRepositoryManager;
|
||||||
import com.google.gerrit.server.notedb.RepoSequence;
|
import com.google.gerrit.server.notedb.RepoSequence;
|
||||||
import com.google.gwtorm.server.OrmException;
|
import com.google.gwtorm.server.OrmException;
|
||||||
@ -42,7 +43,13 @@ public class Schema_155 extends SchemaVersion {
|
|||||||
@SuppressWarnings("deprecation")
|
@SuppressWarnings("deprecation")
|
||||||
RepoSequence.Seed accountSeed = () -> db.nextAccountId();
|
RepoSequence.Seed accountSeed = () -> db.nextAccountId();
|
||||||
RepoSequence accountSeq =
|
RepoSequence accountSeq =
|
||||||
new RepoSequence(repoManager, allUsersName, Sequences.NAME_ACCOUNTS, accountSeed, 1);
|
new RepoSequence(
|
||||||
|
repoManager,
|
||||||
|
GitReferenceUpdated.DISABLED,
|
||||||
|
allUsersName,
|
||||||
|
Sequences.NAME_ACCOUNTS,
|
||||||
|
accountSeed,
|
||||||
|
1);
|
||||||
|
|
||||||
// consume one account ID to ensure that the account sequence is initialized in NoteDb
|
// consume one account ID to ensure that the account sequence is initialized in NoteDb
|
||||||
accountSeq.next();
|
accountSeq.next();
|
||||||
|
@ -25,6 +25,7 @@ import com.github.rholder.retry.StopStrategies;
|
|||||||
import com.google.common.util.concurrent.Runnables;
|
import com.google.common.util.concurrent.Runnables;
|
||||||
import com.google.gerrit.reviewdb.client.Project;
|
import com.google.gerrit.reviewdb.client.Project;
|
||||||
import com.google.gerrit.reviewdb.client.RefNames;
|
import com.google.gerrit.reviewdb.client.RefNames;
|
||||||
|
import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
|
||||||
import com.google.gerrit.testutil.InMemoryRepositoryManager;
|
import com.google.gerrit.testutil.InMemoryRepositoryManager;
|
||||||
import com.google.gwtorm.server.OrmException;
|
import com.google.gwtorm.server.OrmException;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -264,7 +265,14 @@ public class RepoSequenceTest {
|
|||||||
Runnable afterReadRef,
|
Runnable afterReadRef,
|
||||||
Retryer<RefUpdate.Result> retryer) {
|
Retryer<RefUpdate.Result> retryer) {
|
||||||
return new RepoSequence(
|
return new RepoSequence(
|
||||||
repoManager, project, name, () -> start, batchSize, afterReadRef, retryer);
|
repoManager,
|
||||||
|
GitReferenceUpdated.DISABLED,
|
||||||
|
project,
|
||||||
|
name,
|
||||||
|
() -> start,
|
||||||
|
batchSize,
|
||||||
|
afterReadRef,
|
||||||
|
retryer);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ObjectId writeBlob(String sequenceName, String value) {
|
private ObjectId writeBlob(String sequenceName, String value) {
|
||||||
|
Loading…
Reference in New Issue
Block a user