Handle batch-fetch requests in the replica
Add support for the `batch-fetch` endpoint in the
`PullReplicationFilter` class, which is used by the replica node in a
pull-replication setup.
Deserialise the json message into the appopriate class, and pass the
message for further processing to the relevant "action" class.
Bug: Issue 40015567
Change-Id: Id62a671f6436571846256d7dc4dac7c94416233c
diff --git a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/api/PullReplicationEndpoints.java b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/api/PullReplicationEndpoints.java
index 253af58..9fdf5d9 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/api/PullReplicationEndpoints.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/api/PullReplicationEndpoints.java
@@ -36,6 +36,7 @@
public static final String BATCH_APPLY_OBJECT_API_ENDPOINT = "batch-apply-object";
public static final String FETCH_ENDPOINT = "fetch";
+ public static final String BATCH_FETCH_ENDPOINT = "batch-fetch";
public static final String INIT_PROJECT_ENDPOINT = "init-project";
public static final String DELETE_PROJECT_ENDPOINT = "delete-project";
}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/api/PullReplicationFilter.java b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/api/PullReplicationFilter.java
index bfe51a2..207456a 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/api/PullReplicationFilter.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/api/PullReplicationFilter.java
@@ -86,6 +86,7 @@
Pattern.compile(".*/init-project/([^/]+.git)");
private FetchAction fetchAction;
+ private BatchFetchAction batchFetchAction;
private ApplyObjectAction applyObjectAction;
private ApplyObjectsAction applyObjectsAction;
private BatchApplyObjectAction batchApplyObjectAction;
@@ -100,6 +101,7 @@
@Inject
public PullReplicationFilter(
FetchAction fetchAction,
+ BatchFetchAction batchFetchAction,
ApplyObjectAction applyObjectAction,
ApplyObjectsAction applyObjectsAction,
BatchApplyObjectAction batchApplyObjectAction,
@@ -110,6 +112,7 @@
@PluginName String pluginName,
Provider<CurrentUser> currentUserProvider) {
this.fetchAction = fetchAction;
+ this.batchFetchAction = batchFetchAction;
this.applyObjectAction = applyObjectAction;
this.applyObjectsAction = applyObjectsAction;
this.batchApplyObjectAction = batchApplyObjectAction;
@@ -136,6 +139,9 @@
if (isFetchAction(httpRequest)) {
failIfcurrentUserIsAnonymous();
writeResponse(httpResponse, doFetch(httpRequest));
+ } else if (isBatchFetchAction(httpRequest)) {
+ failIfcurrentUserIsAnonymous();
+ writeResponse(httpResponse, doBatchFetch(httpRequest));
} else if (isApplyObjectAction(httpRequest)) {
failIfcurrentUserIsAnonymous();
writeResponse(httpResponse, doApplyObject(httpRequest));
@@ -281,6 +287,16 @@
return new ProjectResource(project.get(), currentUserProvider.get());
}
+ @SuppressWarnings("unchecked")
+ private Response<Map<String, Object>> doBatchFetch(HttpServletRequest httpRequest)
+ throws IOException, RestApiException, PermissionBackendException {
+ TypeToken<List<Input>> collectionType = new TypeToken<>() {};
+ List<Input> inputs = readJson(httpRequest, collectionType.getType());
+ IdString id = getProjectName(httpRequest).get();
+
+ return (Response<Map<String, Object>>) batchFetchAction.apply(parseProjectResource(id), inputs);
+ }
+
private <T> void writeResponse(HttpServletResponse httpResponse, Response<T> response)
throws IOException {
String responseJson = gson.toJson(response);
@@ -373,6 +389,12 @@
return httpRequest.getRequestURI().endsWith(String.format("/%s~" + FETCH_ENDPOINT, pluginName));
}
+ private boolean isBatchFetchAction(HttpServletRequest httpRequest) {
+ return httpRequest
+ .getRequestURI()
+ .endsWith(String.format("/%s~" + BATCH_FETCH_ENDPOINT, pluginName));
+ }
+
private boolean isInitProjectAction(HttpServletRequest httpRequest) {
return httpRequest
.getRequestURI()
diff --git a/src/test/java/com/googlesource/gerrit/plugins/replication/pull/api/PullReplicationFilterTest.java b/src/test/java/com/googlesource/gerrit/plugins/replication/pull/api/PullReplicationFilterTest.java
index 850d04a..e2afe92 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/replication/pull/api/PullReplicationFilterTest.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/replication/pull/api/PullReplicationFilterTest.java
@@ -39,6 +39,7 @@
@Mock HttpServletResponse response;
@Mock FilterChain filterChain;
@Mock private FetchAction fetchAction;
+ @Mock private BatchFetchAction batchFetchAction;
@Mock private ApplyObjectAction applyObjectAction;
@Mock private ApplyObjectsAction applyObjectsAction;
@Mock private BatchApplyObjectAction batchApplyObjectAction;
@@ -56,6 +57,8 @@
private final String PROJECT_NAME_GIT = "some-project.git";
private final String FETCH_URI =
String.format("any-prefix/projects/%s/%s~fetch", PROJECT_NAME, PLUGIN_NAME);
+ private final String BATCH_FETCH_URI =
+ String.format("any-prefix/projects/%s/%s~batch-fetch", PROJECT_NAME, PLUGIN_NAME);
private final String APPLY_OBJECT_URI =
String.format("any-prefix/projects/%s/%s~apply-object", PROJECT_NAME, PLUGIN_NAME);
private final String APPLY_OBJECTS_URI =
@@ -79,6 +82,7 @@
private PullReplicationFilter createPullReplicationFilter(CurrentUser currentUser) {
return new PullReplicationFilter(
fetchAction,
+ batchFetchAction,
applyObjectAction,
applyObjectsAction,
batchApplyObjectAction,
@@ -129,6 +133,31 @@
}
@Test
+ public void shouldFilterBatchFetchAction() throws Exception {
+ byte[] payloadBatchFetch =
+ ("[{"
+ + "\"label\":\"Replication\", "
+ + "\"ref_name\": \"refs/heads/master\", "
+ + "\"async\":false"
+ + "},"
+ + "{"
+ + "\"label\":\"Replication\", "
+ + "\"ref_name\": \"refs/heads/test\", "
+ + "\"async\":false"
+ + "}]")
+ .getBytes(StandardCharsets.UTF_8);
+
+ defineBehaviours(payloadBatchFetch, BATCH_FETCH_URI);
+ when(batchFetchAction.apply(any(), any())).thenReturn(OK_RESPONSE);
+
+ PullReplicationFilter pullReplicationFilter = createPullReplicationFilter();
+ pullReplicationFilter.doFilter(request, response, filterChain);
+
+ verifyBehaviours();
+ verify(batchFetchAction).apply(any(ProjectResource.class), any());
+ }
+
+ @Test
public void shouldFilterApplyObjectAction() throws Exception {
byte[] payloadApplyObject =