Add method that retrieve links for specific EiffelEvent key
Solves: Jira GER-1545
Change-Id: Ia2cc9f065773a49bed01158334bd16f96a037d73
diff --git a/src/main/java/com/googlesource/gerrit/plugins/eventseiffel/EiffelEventHub.java b/src/main/java/com/googlesource/gerrit/plugins/eventseiffel/EiffelEventHub.java
index 8d6cab9..8e58fbb 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/eventseiffel/EiffelEventHub.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/eventseiffel/EiffelEventHub.java
@@ -91,6 +91,20 @@
*/
public Optional<UUID> getScsForCommit(String repo, String commit, List<String> branches)
throws EiffelEventIdLookupException;
+
+ /**
+ * If an event exists, already published or awaiting publish in this EiffelEventHub, such that:
+ *
+ * <p>{@code EventKey.fromEvent(this).equals(EventKey.fromEvent(existing)}
+ *
+ * <p>is true, links.target for all links of type PREVIOUS_VERSION of this event is returned,
+ * otherwise Optional.empty()
+ *
+ * @param key EventKey
+ * @return Optional<List<UUID>> event.links[].target
+ * @throws EiffelEventIdLookupException when failing to lookup event from Eiffel.
+ */
+ public Optional<List<UUID>> getParentLinks(EventKey key) throws EiffelEventIdLookupException;
/** Start publishing events to Eiffel. */
public void startPublishing();
/** Stop publishing events to Eiffel. */
diff --git a/src/main/java/com/googlesource/gerrit/plugins/eventseiffel/EiffelEventHubImpl.java b/src/main/java/com/googlesource/gerrit/plugins/eventseiffel/EiffelEventHubImpl.java
index 841aa4f..2138164 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/eventseiffel/EiffelEventHubImpl.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/eventseiffel/EiffelEventHubImpl.java
@@ -15,6 +15,7 @@
package com.googlesource.gerrit.plugins.eventseiffel;
import static com.google.common.base.Preconditions.checkState;
+import static com.googlesource.gerrit.plugins.eventseiffel.eiffel.dto.EiffelLinkType.PREVIOUS_VERSION;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
@@ -26,6 +27,7 @@
import com.googlesource.gerrit.plugins.eventseiffel.eiffel.EventKey;
import com.googlesource.gerrit.plugins.eventseiffel.eiffel.SourceChangeEventKey;
import com.googlesource.gerrit.plugins.eventseiffel.eiffel.dto.EiffelEvent;
+import java.util.Arrays;
import java.util.Deque;
import java.util.List;
import java.util.Map;
@@ -173,6 +175,29 @@
}
@Override
+ public Optional<List<UUID>> getParentLinks(EventKey key) throws EiffelEventIdLookupException {
+ final ReentrantLock idLookupLock = this.idLookupLock;
+ idLookupLock.lock();
+ try {
+ EiffelEvent fromHub = eventsInQueue.getOrDefault(key, null);
+ if (fromHub != null) {
+ if (key.matches(fromHub)) {
+ return Optional.of(
+ Arrays.stream(fromHub.links)
+ .filter(link -> link.type == PREVIOUS_VERSION)
+ .map(link -> link.target)
+ .collect(Collectors.toList()));
+ }
+ throw new EiffelEventIdLookupException(
+ "Key: %s does not match found event: %s.", key, EventKey.fromEvent(fromHub));
+ }
+ } finally {
+ idLookupLock.unlock();
+ }
+ return idCache.getParentLinks(key);
+ }
+
+ @Override
public boolean isOpen() {
return open;
}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/eventseiffel/cache/EiffelEventIdCache.java b/src/main/java/com/googlesource/gerrit/plugins/eventseiffel/cache/EiffelEventIdCache.java
index 1299a7e..59775e0 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/eventseiffel/cache/EiffelEventIdCache.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/eventseiffel/cache/EiffelEventIdCache.java
@@ -36,6 +36,19 @@
Optional<UUID> getEventId(EventKey key) throws EiffelEventIdLookupException;
/**
+ * Returns the ids that is linked with PREVIOUS_VERSION by event that matches:
+ *
+ * <p>{@code EventKey.fromEvent(event).equals(key)}
+ *
+ * <p>Optional.Empty if no such event exists.
+ *
+ * @param key
+ * @return Optional<List<UUID>>
+ * @throws EiffelEventIdLookupException if value failed to load.
+ */
+ Optional<List<UUID>> getParentLinks(EventKey key) throws EiffelEventIdLookupException;
+
+ /**
* Returns the id of an event that matches the repo and the commit:
*
* <p>Optional.Empty if no such event exists.
diff --git a/src/main/java/com/googlesource/gerrit/plugins/eventseiffel/cache/EiffelEventIdCacheImpl.java b/src/main/java/com/googlesource/gerrit/plugins/eventseiffel/cache/EiffelEventIdCacheImpl.java
index fa7d622..923039b 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/eventseiffel/cache/EiffelEventIdCacheImpl.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/eventseiffel/cache/EiffelEventIdCacheImpl.java
@@ -131,6 +131,18 @@
return !ids.isEmpty() ? Optional.of(ids.get(0)) : Optional.empty();
}
+ @Override
+ public Optional<List<UUID>> getParentLinks(EventKey key) throws EiffelEventIdLookupException {
+ try {
+ return eventStorage.getParentLinks(key);
+ } catch (EventStorageException e) {
+ throw new EiffelEventIdLookupException(
+ e,
+ key.type(),
+ String.format("failed to lookup Eiffel event links for %s from GraphQl", key));
+ }
+ }
+
/* (non-Javadoc)
* @see com.googlesource.gerrit.plugins.eventseiffel.EiffelEventIdCache#putId(com.googlesource.gerrit.plugins.eventseiffel.eiffel.EiffelEvent)
*/
diff --git a/src/main/java/com/googlesource/gerrit/plugins/eventseiffel/eiffel/api/EiffelClient.java b/src/main/java/com/googlesource/gerrit/plugins/eventseiffel/eiffel/api/EiffelClient.java
index 5bf5c75..002f6bc 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/eventseiffel/eiffel/api/EiffelClient.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/eventseiffel/eiffel/api/EiffelClient.java
@@ -60,6 +60,11 @@
}
@Override
+ public Optional<List<UUID>> getParentLinks(EventKey key) throws EventStorageException {
+ return restClient.getParentLinks(key);
+ }
+
+ @Override
public List<UUID> getScsIds(String repo, String commit) throws EventStorageException {
return graphQlClient.getScsIds(repo, commit);
}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/eventseiffel/eiffel/api/EiffelGoRestClient.java b/src/main/java/com/googlesource/gerrit/plugins/eventseiffel/eiffel/api/EiffelGoRestClient.java
index 1cece64..1936110 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/eventseiffel/eiffel/api/EiffelGoRestClient.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/eventseiffel/eiffel/api/EiffelGoRestClient.java
@@ -14,6 +14,8 @@
package com.googlesource.gerrit.plugins.eventseiffel.eiffel.api;
+import static com.googlesource.gerrit.plugins.eventseiffel.eiffel.dto.EiffelLinkType.PREVIOUS_VERSION;
+
import com.github.rholder.retry.RetryException;
import com.github.rholder.retry.Retryer;
import com.github.rholder.retry.RetryerBuilder;
@@ -23,16 +25,24 @@
import com.google.common.flogger.FluentLogger;
import com.google.gson.Gson;
import com.google.gson.JsonSyntaxException;
+import com.googlesource.gerrit.plugins.eventseiffel.eiffel.EventKey;
+import com.googlesource.gerrit.plugins.eventseiffel.eiffel.SourceChangeEventKey;
import com.googlesource.gerrit.plugins.eventseiffel.eiffel.dto.EiffelLinkInfo;
+import com.googlesource.gerrit.plugins.eventseiffel.eiffel.dto.EiffelLinkType;
import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.http.HttpResponse.BodyHandlers;
+import java.util.Arrays;
import java.util.List;
+import java.util.Optional;
+import java.util.UUID;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
public class EiffelGoRestClient {
public static FluentLogger logger = FluentLogger.forEnclosingClass();
@@ -49,6 +59,43 @@
this.goRestUrl = goRestUrl;
}
+ public Optional<List<UUID>> getParentLinks(EventKey key) throws EventStorageException {
+ String query;
+ switch (key.type()) {
+ case SCC:
+ SourceChangeEventKey sccKey = (SourceChangeEventKey) key;
+ query =
+ String.format(
+ LINKS_ID_URL,
+ sccKey.type().getType(),
+ sccKey.repo(),
+ sccKey.branch(),
+ sccKey.commit());
+ break;
+ case SCS:
+ SourceChangeEventKey scsKey = (SourceChangeEventKey) key;
+ query =
+ String.format(
+ LINKS_ID_URL,
+ scsKey.type().getType(),
+ scsKey.repo(),
+ scsKey.branch(),
+ scsKey.commit());
+ break;
+ default:
+ return Optional.empty();
+ }
+ QueryResult qr = restQuery(query);
+ if (qr == null || qr.isEmpty()) {
+ return Optional.empty();
+ }
+
+ if (qr.nbrOfFoundEvents() > 1) {
+ logger.atWarning().log("More than one event found (using first) for query:\"%s\"", query);
+ }
+ return Optional.of(qr.getParentLinks());
+ }
+
private QueryResult restQuery(String query) throws EventStorageException {
HttpResponse<String> response;
try {
@@ -95,5 +142,23 @@
class Data {
EiffelLinkInfo[] links;
}
+
+ int nbrOfFoundEvents() {
+ return items != null ? items.size() : 0;
+ }
+
+ boolean isEmpty() {
+ return items == null || items.isEmpty();
+ }
+
+ List<UUID> getParentLinks() {
+ return getLinks(PREVIOUS_VERSION).collect(Collectors.toList());
+ }
+
+ private Stream<UUID> getLinks(EiffelLinkType linkType) {
+ return Arrays.stream(items.get(0).links)
+ .filter(link -> link.type == linkType)
+ .map(link -> link.target);
+ }
}
}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/eventseiffel/eiffel/api/EiffelGraphQlClient.java b/src/main/java/com/googlesource/gerrit/plugins/eventseiffel/eiffel/api/EiffelGraphQlClient.java
index 468d030..2b0a79a 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/eventseiffel/eiffel/api/EiffelGraphQlClient.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/eventseiffel/eiffel/api/EiffelGraphQlClient.java
@@ -180,18 +180,22 @@
Data data;
List<Error> errors;
- List<UUID> getIds() {
+ List<Data.Field.Edge> getEdges() {
if (data != null) {
if (data.sourceChangeCreated != null) {
- return toIds(data.sourceChangeCreated.edges);
+ return data.sourceChangeCreated.edges;
}
if (data.sourceChangeSubmitted != null) {
- return toIds(data.sourceChangeSubmitted.edges);
+ return data.sourceChangeSubmitted.edges;
}
}
return Lists.newArrayList();
}
+ List<UUID> getIds() {
+ return toIds(getEdges());
+ }
+
List<String> getErrorMessages() {
return errors.stream().map(e -> e.message).collect(Collectors.toList());
}
@@ -208,18 +212,20 @@
class Field {
List<Edge> edges;
+ Meta meta;
class Edge {
Node node;
class Node {
+ List<Data> links;
Meta meta;
-
- class Meta {
- UUID id;
- }
}
}
+
+ class Meta {
+ UUID id;
+ }
}
}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/eventseiffel/eiffel/api/EventStorage.java b/src/main/java/com/googlesource/gerrit/plugins/eventseiffel/eiffel/api/EventStorage.java
index 399cc5b..56be459 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/eventseiffel/eiffel/api/EventStorage.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/eventseiffel/eiffel/api/EventStorage.java
@@ -34,6 +34,16 @@
public Optional<UUID> getEventId(EventKey key) throws EventStorageException;
/**
+ * Returns the links.target for links where links.type is PREVIOUS_VERSION for the event that
+ * matches EventKey key. Optional.empty() if there exists no such event.
+ *
+ * @param key
+ * @return {@link Optional} of {@link List} of {@link UUID} ids of the linked events.
+ * @throws EventStorageException
+ */
+ public Optional<List<UUID>> getParentLinks(EventKey key) throws EventStorageException;
+
+ /**
* Returns the meta.ids of the SCS events that match the repo and the commitid.
*
* @param repo the repo of the SCS events.
@@ -52,6 +62,11 @@
}
@Override
+ public Optional<List<UUID>> getParentLinks(EventKey key) throws EventStorageException {
+ throw new NotImplementedException();
+ }
+
+ @Override
public List<UUID> getScsIds(String repo, String commit) throws EventStorageException {
throw new NotImplementedException();
}
diff --git a/src/test/java/com/googlesource/gerrit/plugins/eventseiffel/TestEventHub.java b/src/test/java/com/googlesource/gerrit/plugins/eventseiffel/TestEventHub.java
index ddbb055..9957d69 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/eventseiffel/TestEventHub.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/eventseiffel/TestEventHub.java
@@ -22,6 +22,8 @@
import com.googlesource.gerrit.plugins.eventseiffel.eiffel.EventKey;
import com.googlesource.gerrit.plugins.eventseiffel.eiffel.SourceChangeEventKey;
import com.googlesource.gerrit.plugins.eventseiffel.eiffel.dto.EiffelEvent;
+import com.googlesource.gerrit.plugins.eventseiffel.eiffel.dto.EiffelLinkType;
+import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.Set;
@@ -70,6 +72,17 @@
return idCache.getScsForCommit(repo, commit, branches);
}
+ @Override
+ public Optional<List<UUID>> getParentLinks(EventKey key) throws EiffelEventIdLookupException {
+ return findEvent(key)
+ .map(
+ event ->
+ Arrays.stream(event.links)
+ .filter(link -> link.type.equals(EiffelLinkType.PREVIOUS_VERSION))
+ .map(link -> link.target)
+ .collect(Collectors.toList()));
+ }
+
private Optional<EiffelEvent> findEvent(EventKey key) {
for (EiffelEvent event : EVENTS) {
if (key.equals(EventKey.fromEvent(event))) {
diff --git a/src/test/java/com/googlesource/gerrit/plugins/eventseiffel/TestEventStorage.java b/src/test/java/com/googlesource/gerrit/plugins/eventseiffel/TestEventStorage.java
index b257679..74196c8 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/eventseiffel/TestEventStorage.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/eventseiffel/TestEventStorage.java
@@ -16,6 +16,7 @@
import static com.googlesource.gerrit.plugins.eventseiffel.eiffel.dto.EiffelEventType.SCS;
+import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.inject.Singleton;
import com.googlesource.gerrit.plugins.eventseiffel.eiffel.EventKey;
@@ -64,6 +65,11 @@
.collect(Collectors.toList());
}
+ @Override
+ public Optional<List<UUID>> getParentLinks(EventKey key) throws EventStorageException {
+ return Optional.of(Lists.newArrayList());
+ }
+
private boolean equalsSCSWithRepoAndCommit(EventKey key, String repo, String commit) {
if (!key.type().equals(SCS)) return false;
SourceChangeEventKey scsKey = (SourceChangeEventKey) key;