Merge branch 'stable-3.1'
* stable-3.1:
Use a global version number instead of the commit timestamp
Update project version on global ref-db only when more recent
Add missing prometheus configuration
Change-Id: Iaf3846dc0a8210762c80b19c9bc6b87293ce54b1
diff --git a/setup_local_env/prometheus-config/prometheus.yml b/setup_local_env/prometheus-config/prometheus.yml
new file mode 100644
index 0000000..e6d3ea1
--- /dev/null
+++ b/setup_local_env/prometheus-config/prometheus.yml
@@ -0,0 +1,14 @@
+# my global config
+global:
+ scrape_interval: 10s
+ evaluation_interval: 10s
+
+scrape_configs:
+ - job_name: gerrit
+ static_configs:
+ - targets: ['localhost:18080','localhost:18081']
+ metrics_path: '/plugins/metrics-reporter-prometheus/metrics'
+ params:
+ format: ['prometheus']
+ bearer_token: token
+
diff --git a/src/main/java/com/googlesource/gerrit/plugins/multisite/index/ChangeCheckerImpl.java b/src/main/java/com/googlesource/gerrit/plugins/multisite/index/ChangeCheckerImpl.java
index 32b8af3..15b1e09 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/multisite/index/ChangeCheckerImpl.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/multisite/index/ChangeCheckerImpl.java
@@ -79,7 +79,7 @@
@Override
public Optional<ChangeNotes> getChangeNotes() {
try (ManualRequestContext ctx = oneOffReqCtx.open()) {
- this.changeNotes = Optional.ofNullable(changeFinder.findOne(changeId));
+ this.changeNotes = changeFinder.findOne(changeId);
return changeNotes;
}
}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/multisite/validation/ProjectVersionRefUpdate.java b/src/main/java/com/googlesource/gerrit/plugins/multisite/validation/ProjectVersionRefUpdate.java
index bd910ad..73bab49 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/multisite/validation/ProjectVersionRefUpdate.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/multisite/validation/ProjectVersionRefUpdate.java
@@ -18,10 +18,8 @@
import static org.eclipse.jgit.lib.Constants.OBJ_BLOB;
import com.gerritforge.gerrit.globalrefdb.GlobalRefDbSystemError;
-import com.google.common.base.CharMatcher;
import com.google.common.collect.ImmutableSet;
import com.google.common.flogger.FluentLogger;
-import com.google.common.primitives.Ints;
import com.google.gerrit.entities.Project;
import com.google.gerrit.entities.RefNames;
import com.google.gerrit.server.events.Event;
@@ -42,13 +40,9 @@
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectIdRef;
import org.eclipse.jgit.lib.ObjectInserter;
-import org.eclipse.jgit.lib.ObjectLoader;
-import org.eclipse.jgit.lib.ObjectReader;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.RefUpdate;
import org.eclipse.jgit.lib.Repository;
-import org.eclipse.jgit.revwalk.RevCommit;
-import org.eclipse.jgit.revwalk.RevWalk;
@Singleton
public class ProjectVersionRefUpdate implements EventListener {
@@ -105,23 +99,18 @@
}
try {
Project.NameKey projectNameKey = refUpdatedEvent.getProjectNameKey();
- Ref currentProjectVersionRef = getLocalProjectVersionRef(refUpdatedEvent.getProjectNameKey());
- Optional<Long> currentProjectVersionValue =
- getLongFromObjectId(projectNameKey.get(), currentProjectVersionRef.getObjectId());
+ long newVersion = getCurrentGlobalVersionNumber();
- Optional<Long> lastRefUpdatedTimestamp = getLastRefUpdatedTimestamp(projectNameKey, refName);
- Optional<ObjectId> newProjectVersionObjectId =
- updateLocalProjectVersion(projectNameKey, lastRefUpdatedTimestamp);
+ Optional<RefUpdate> newProjectVersionRefUpdate =
+ updateLocalProjectVersion(projectNameKey, newVersion);
- if (newProjectVersionObjectId.isPresent()) {
- verLogger.log(projectNameKey, lastRefUpdatedTimestamp.get(), 0L);
+ if (newProjectVersionRefUpdate.isPresent()) {
+ verLogger.log(projectNameKey, newVersion, 0L);
- updateSharedProjectVersion(
- projectNameKey,
- currentProjectVersionRef,
- newProjectVersionObjectId.get(),
- currentProjectVersionValue,
- lastRefUpdatedTimestamp);
+ if (updateSharedProjectVersion(
+ projectNameKey, newProjectVersionRefUpdate.get().getNewObjectId(), newVersion)) {
+ gitReferenceUpdated.fire(projectNameKey, newProjectVersionRefUpdate.get(), null);
+ }
} else {
logger.atWarning().log(
"Ref %s not found on projet %s: skipping project version update",
@@ -149,71 +138,49 @@
return newId;
}
- private Ref getLocalProjectVersionRef(Project.NameKey projectNameKey)
- throws LocalProjectVersionUpdateException {
- try (Repository repository = gitRepositoryManager.openRepository(projectNameKey)) {
- Ref ref = repository.findRef(MULTI_SITE_VERSIONING_REF);
- return ref != null ? ref : NULL_PROJECT_VERSION_REF;
- } catch (IOException e) {
- String message =
- String.format("Error while getting current version ref for %s", projectNameKey.get());
- logger.atSevere().withCause(e).log(message);
- throw new LocalProjectVersionUpdateException(message);
- }
- }
-
- private Optional<Long> getLastRefUpdatedTimestamp(Project.NameKey projectNameKey, String refName)
- throws LocalProjectVersionUpdateException {
- logger.atFine().log(
- String.format(
- "Getting last ref updated time for project %s, ref %s", projectNameKey.get(), refName));
- try (Repository repository = gitRepositoryManager.openRepository(projectNameKey)) {
- Ref ref = repository.findRef(refName);
- if (ref == null) {
- logger.atWarning().log("Unable to find ref " + refName + " in project " + projectNameKey);
- return Optional.empty();
- }
- try (RevWalk walk = new RevWalk(repository)) {
- RevCommit commit = walk.parseCommit(ref.getObjectId());
- return Optional.of(Integer.toUnsignedLong(commit.getCommitTime()));
- }
- } catch (IOException ioe) {
- String message =
- String.format(
- "Error while getting last ref updated time for project %s, ref %s",
- projectNameKey.get(), refName);
- logger.atSevere().withCause(ioe).log(message);
- throw new LocalProjectVersionUpdateException(message);
- }
- }
-
- private void updateSharedProjectVersion(
- Project.NameKey projectNameKey,
- Ref currentRef,
- ObjectId newObjectId,
- Optional<Long> currentVersion,
- Optional<Long> newVersion)
+ private boolean updateSharedProjectVersion(
+ Project.NameKey projectNameKey, ObjectId newObjectId, Long newVersion)
throws SharedProjectVersionUpdateException {
- logger.atFine().log(
- String.format(
- "Updating shared project version for %s. Current value %s, new value: %s",
- projectNameKey.get(), currentRef.getObjectId(), newObjectId));
+ Ref sharedRef =
+ sharedRefDb
+ .get(projectNameKey, MULTI_SITE_VERSIONING_REF, String.class)
+ .map(
+ (String objectId) ->
+ new ObjectIdRef.Unpeeled(
+ Ref.Storage.NEW, MULTI_SITE_VERSIONING_REF, ObjectId.fromString(objectId)))
+ .orElse(
+ new ObjectIdRef.Unpeeled(
+ Ref.Storage.NEW, MULTI_SITE_VERSIONING_REF, ObjectId.zeroId()));
+ Optional<Long> sharedVersion =
+ sharedRefDb
+ .get(projectNameKey, MULTI_SITE_VERSIONING_VALUE_REF, String.class)
+ .map(Long::parseLong);
+
try {
- if (!sharedRefDb.exists(projectNameKey, MULTI_SITE_VERSIONING_REF)) {
- currentRef =
- new ObjectIdRef.Unpeeled(Ref.Storage.NEW, MULTI_SITE_VERSIONING_REF, ObjectId.zeroId());
- }
- if (!sharedRefDb.exists(projectNameKey, MULTI_SITE_VERSIONING_VALUE_REF)) {
- currentVersion = Optional.empty();
+ if (sharedVersion.isPresent() && sharedVersion.get() >= newVersion) {
+ logger.atWarning().log(
+ String.format(
+ "NOT Updating project %s version %s (value=%d) in shared ref-db because is more recent than the local one %s (value=%d) ",
+ projectNameKey.get(),
+ newObjectId,
+ newVersion,
+ sharedRef.getObjectId().getName(),
+ sharedVersion.get()));
+ return false;
}
- boolean success = sharedRefDb.compareAndPut(projectNameKey, currentRef, newObjectId);
+ logger.atFine().log(
+ String.format(
+ "Updating shared project %s version to %s (value=%d)",
+ projectNameKey.get(), newObjectId, newVersion));
+
+ boolean success = sharedRefDb.compareAndPut(projectNameKey, sharedRef, newObjectId);
if (!success) {
String message =
String.format(
"Project version blob update failed for %s. Current value %s, new value: %s",
- projectNameKey.get(), safeGetObjectId(currentRef), newObjectId);
+ projectNameKey.get(), safeGetObjectId(sharedRef), newObjectId);
logger.atSevere().log(message);
throw new SharedProjectVersionUpdateException(message);
}
@@ -222,22 +189,24 @@
sharedRefDb.compareAndPut(
projectNameKey,
MULTI_SITE_VERSIONING_VALUE_REF,
- currentVersion.map(Object::toString).orElse(null),
- newVersion.map(Object::toString).orElse(null));
+ sharedVersion.map(Object::toString).orElse(null),
+ newVersion.toString());
if (!success) {
String message =
String.format(
"Project version update failed for %s. Current value %s, new value: %s",
- projectNameKey.get(), safeGetObjectId(currentRef), newObjectId);
+ projectNameKey.get(), safeGetObjectId(sharedRef), newObjectId);
logger.atSevere().log(message);
throw new SharedProjectVersionUpdateException(message);
}
+
+ return true;
} catch (GlobalRefDbSystemError refDbSystemError) {
String message =
String.format(
"Error while updating shared project version for %s. Current value %s, new value: %s. Error: %s",
projectNameKey.get(),
- currentRef.getObjectId(),
+ sharedRef.getObjectId(),
newObjectId,
refDbSystemError.getMessage());
logger.atSevere().withCause(refDbSystemError).log(message);
@@ -283,54 +252,25 @@
}
}
- private Optional<Long> getLongFromObjectId(String projectName, ObjectId objectId) {
- if (objectId.equals(ObjectId.zeroId())) {
- return Optional.empty();
- }
- try (Repository repository =
- gitRepositoryManager.openRepository(Project.NameKey.parse(projectName))) {
- ObjectReader or = repository.newObjectReader();
- ObjectLoader ol = or.open(objectId, OBJ_BLOB);
- if (ol.getType() != OBJ_BLOB) {
- // In theory this should be thrown by open but not all implementations may do it properly
- // (certainly InMemoryRepository doesn't).
- logger.atSevere().log("Incorrect object type loaded for objectId %s", objectId.toString());
- return Optional.empty();
- }
- String str = CharMatcher.whitespace().trimFrom(new String(ol.getCachedBytes(), UTF_8));
- Integer value = Ints.tryParse(str);
- logger.atInfo().log(
- "Found remote version for project %s, value: %s - %d",
- projectName, objectId.toString(), value);
- return Optional.of(Integer.toUnsignedLong(value));
- } catch (IOException e) {
- logger.atSevere().withCause(e).log("Cannot parse objectId %s", objectId.toString());
- return Optional.empty();
- }
- }
-
- private Optional<ObjectId> updateLocalProjectVersion(
- Project.NameKey projectNameKey, Optional<Long> lastRefUpdatedTimestamp)
+ private Optional<RefUpdate> updateLocalProjectVersion(
+ Project.NameKey projectNameKey, long newVersionNumber)
throws LocalProjectVersionUpdateException {
- if (!lastRefUpdatedTimestamp.isPresent()) {
- return Optional.empty();
- }
-
- logger.atFine().log("Updating local version for project " + projectNameKey.get());
+ logger.atFine().log(
+ "Updating local version for project %s with version %d",
+ projectNameKey.get(), newVersionNumber);
try (Repository repository = gitRepositoryManager.openRepository(projectNameKey)) {
- RefUpdate refUpdate = getProjectVersionRefUpdate(repository, lastRefUpdatedTimestamp.get());
+ RefUpdate refUpdate = getProjectVersionRefUpdate(repository, newVersionNumber);
RefUpdate.Result result = refUpdate.update();
if (!isSuccessful(result)) {
String message =
String.format(
"RefUpdate failed with result %s for: project=%s, version=%d",
- result.name(), projectNameKey.get(), lastRefUpdatedTimestamp.get());
+ result.name(), projectNameKey.get(), newVersionNumber);
logger.atSevere().log(message);
throw new LocalProjectVersionUpdateException(message);
}
- gitReferenceUpdated.fire(projectNameKey, refUpdate, null);
- return Optional.of(refUpdate.getNewObjectId());
+ return Optional.of(refUpdate);
} catch (IOException e) {
String message = "Cannot create versioning command for " + projectNameKey.get();
logger.atSevere().withCause(e).log(message);
@@ -338,6 +278,10 @@
}
}
+ private long getCurrentGlobalVersionNumber() {
+ return System.currentTimeMillis() / 1000;
+ }
+
private Boolean isSuccessful(RefUpdate.Result result) {
return SUCCESSFUL_RESULTS.contains(result);
}
diff --git a/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/ProjectVersionRefUpdateTest.java b/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/ProjectVersionRefUpdateTest.java
index 20b49c1..2eefb5a 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/ProjectVersionRefUpdateTest.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/ProjectVersionRefUpdateTest.java
@@ -88,12 +88,16 @@
@Test
public void producerShouldUpdateProjectVersionUponRefUpdatedEvent() throws IOException {
Context.setForwardedEvent(false);
- when(sharedRefDb.exists(
- A_TEST_PROJECT_NAME_KEY, ProjectVersionRefUpdate.MULTI_SITE_VERSIONING_REF))
- .thenReturn(true);
- when(sharedRefDb.exists(
- A_TEST_PROJECT_NAME_KEY, ProjectVersionRefUpdate.MULTI_SITE_VERSIONING_VALUE_REF))
- .thenReturn(true);
+ when(sharedRefDb.get(
+ A_TEST_PROJECT_NAME_KEY,
+ ProjectVersionRefUpdate.MULTI_SITE_VERSIONING_REF,
+ String.class))
+ .thenReturn(Optional.of("26f7ee61bf0e470e8393c884526eec8a9b943a63"));
+ when(sharedRefDb.get(
+ A_TEST_PROJECT_NAME_KEY,
+ ProjectVersionRefUpdate.MULTI_SITE_VERSIONING_VALUE_REF,
+ String.class))
+ .thenReturn(Optional.of("" + (masterCommit.getCommitTime() - 1)));
when(sharedRefDb.compareAndPut(any(Project.NameKey.class), any(Ref.class), any(ObjectId.class)))
.thenReturn(true);
when(sharedRefDb.compareAndPut(any(Project.NameKey.class), any(String.class), any(), any()))
@@ -112,22 +116,72 @@
assertThat(ref).isNotNull();
ObjectLoader loader = repo.getRepository().open(ref.getObjectId());
- String storedVersion = IOUtils.toString(loader.openStream(), StandardCharsets.UTF_8.name());
- assertThat(Long.parseLong(storedVersion)).isEqualTo(masterCommit.getCommitTime());
+ long storedVersion =
+ Long.parseLong(IOUtils.toString(loader.openStream(), StandardCharsets.UTF_8.name()));
+ assertThat(storedVersion).isGreaterThan((long) masterCommit.getCommitTime());
- verify(verLogger).log(A_TEST_PROJECT_NAME_KEY, masterCommit.getCommitTime(), 0);
+ verify(verLogger).log(A_TEST_PROJECT_NAME_KEY, storedVersion, 0);
+ }
+
+ @Test
+ public void producerShouldUpdateProjectVersionUponForcedPushRefUpdatedEvent() throws Exception {
+ Context.setForwardedEvent(false);
+
+ Thread.sleep(1000L);
+ RevCommit masterPlusOneCommit = repo.branch("master").commit().create();
+
+ Thread.sleep(1000L);
+ repo.branch("master").update(masterCommit);
+
+ when(sharedRefDb.get(
+ A_TEST_PROJECT_NAME_KEY,
+ ProjectVersionRefUpdate.MULTI_SITE_VERSIONING_REF,
+ String.class))
+ .thenReturn(Optional.of("26f7ee61bf0e470e8393c884526eec8a9b943a63"));
+ when(sharedRefDb.get(
+ A_TEST_PROJECT_NAME_KEY,
+ ProjectVersionRefUpdate.MULTI_SITE_VERSIONING_VALUE_REF,
+ String.class))
+ .thenReturn(Optional.of("" + (masterCommit.getCommitTime() - 1)));
+ when(sharedRefDb.compareAndPut(any(Project.NameKey.class), any(Ref.class), any(ObjectId.class)))
+ .thenReturn(true);
+ when(sharedRefDb.compareAndPut(any(Project.NameKey.class), any(String.class), any(), any()))
+ .thenReturn(true);
+ when(refUpdatedEvent.getProjectNameKey()).thenReturn(A_TEST_PROJECT_NAME_KEY);
+ when(refUpdatedEvent.getRefName()).thenReturn(A_TEST_REF_NAME);
+
+ new ProjectVersionRefUpdate(repoManager, sharedRefDb, gitReferenceUpdated, verLogger)
+ .onEvent(refUpdatedEvent);
+
+ Ref ref = repo.getRepository().findRef(MULTI_SITE_VERSIONING_REF);
+
+ verify(sharedRefDb, atMost(1))
+ .compareAndPut(any(Project.NameKey.class), any(Ref.class), any(ObjectId.class));
+
+ assertThat(ref).isNotNull();
+
+ ObjectLoader loader = repo.getRepository().open(ref.getObjectId());
+ long storedVersion =
+ Long.parseLong(IOUtils.toString(loader.openStream(), StandardCharsets.UTF_8.name()));
+ assertThat(storedVersion).isGreaterThan((long) masterPlusOneCommit.getCommitTime());
+
+ verify(verLogger).log(A_TEST_PROJECT_NAME_KEY, storedVersion, 0);
}
@Test
public void producerShouldCreateNewProjectVersionWhenMissingUponRefUpdatedEvent()
throws IOException {
Context.setForwardedEvent(false);
- when(sharedRefDb.exists(
- A_TEST_PROJECT_NAME_KEY, ProjectVersionRefUpdate.MULTI_SITE_VERSIONING_REF))
- .thenReturn(false);
- when(sharedRefDb.exists(
- A_TEST_PROJECT_NAME_KEY, ProjectVersionRefUpdate.MULTI_SITE_VERSIONING_VALUE_REF))
- .thenReturn(false);
+ when(sharedRefDb.get(
+ A_TEST_PROJECT_NAME_KEY,
+ ProjectVersionRefUpdate.MULTI_SITE_VERSIONING_REF,
+ String.class))
+ .thenReturn(Optional.empty());
+ when(sharedRefDb.get(
+ A_TEST_PROJECT_NAME_KEY,
+ ProjectVersionRefUpdate.MULTI_SITE_VERSIONING_VALUE_REF,
+ String.class))
+ .thenReturn(Optional.empty());
when(sharedRefDb.compareAndPut(any(Project.NameKey.class), any(Ref.class), any(ObjectId.class)))
.thenReturn(true);
@@ -147,10 +201,11 @@
assertThat(ref).isNotNull();
ObjectLoader loader = repo.getRepository().open(ref.getObjectId());
- String storedVersion = IOUtils.toString(loader.openStream(), StandardCharsets.UTF_8.name());
- assertThat(Long.parseLong(storedVersion)).isEqualTo(masterCommit.getCommitTime());
+ long storedVersion =
+ Long.parseLong(IOUtils.toString(loader.openStream(), StandardCharsets.UTF_8.name()));
+ assertThat(storedVersion).isGreaterThan((long) masterCommit.getCommitTime());
- verify(verLogger).log(A_TEST_PROJECT_NAME_KEY, masterCommit.getCommitTime(), 0);
+ verify(verLogger).log(A_TEST_PROJECT_NAME_KEY, storedVersion, 0);
}
@Test