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 =