mirror of
https://github.com/google/nomulus.git
synced 2025-07-21 18:26:12 +02:00
Finish RDE pipeline implementation in SQL mode (#1330)
This PR adds the final step in RDE pipeline (enqueueing the next action to Cloud Tasks) and makes some necessary changes, namely by making all CloudTasksUtils related classes serializable, so that they can be used on Beam. <!-- Reviewable:start --> This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/google/nomulus/1330) <!-- Reviewable:end -->
This commit is contained in:
parent
6cb0cf5f6d
commit
57e58ce8b7
27 changed files with 903 additions and 206 deletions
|
@ -37,7 +37,7 @@ import com.google.protobuf.ByteString;
|
|||
import java.io.Serializable;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Arrays;
|
||||
import javax.inject.Provider;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/** Utilities for dealing with Cloud Tasks. */
|
||||
public class CloudTasksUtils implements Serializable {
|
||||
|
@ -48,17 +48,14 @@ public class CloudTasksUtils implements Serializable {
|
|||
private final Retrier retrier;
|
||||
private final String projectId;
|
||||
private final String locationId;
|
||||
private final Provider<CloudTasksClient> clientProvider;
|
||||
private final SerializableCloudTasksClient client;
|
||||
|
||||
public CloudTasksUtils(
|
||||
Retrier retrier,
|
||||
String projectId,
|
||||
String locationId,
|
||||
Provider<CloudTasksClient> clientProvider) {
|
||||
Retrier retrier, String projectId, String locationId, SerializableCloudTasksClient client) {
|
||||
this.retrier = retrier;
|
||||
this.projectId = projectId;
|
||||
this.locationId = locationId;
|
||||
this.clientProvider = clientProvider;
|
||||
this.client = client;
|
||||
}
|
||||
|
||||
public Task enqueue(String queue, Task task) {
|
||||
|
@ -69,9 +66,7 @@ public class CloudTasksUtils implements Serializable {
|
|||
queue,
|
||||
task.getAppEngineHttpRequest().getRelativeUri(),
|
||||
task.getAppEngineHttpRequest().getAppEngineRouting().getService());
|
||||
try (CloudTasksClient client = clientProvider.get()) {
|
||||
return client.createTask(QueueName.of(projectId, locationId, queue), task);
|
||||
}
|
||||
return client.enqueue(projectId, locationId, queue, task);
|
||||
},
|
||||
ApiException.class);
|
||||
}
|
||||
|
@ -141,4 +136,28 @@ public class CloudTasksUtils implements Serializable {
|
|||
public static Task createGetTask(String path, String service, Multimap<String, String> params) {
|
||||
return createTask(path, HttpMethod.GET, service, params);
|
||||
}
|
||||
|
||||
public abstract static class SerializableCloudTasksClient implements Serializable {
|
||||
public abstract Task enqueue(String projectId, String locationId, String queueName, Task task);
|
||||
}
|
||||
|
||||
public static class GcpCloudTasksClient extends SerializableCloudTasksClient {
|
||||
|
||||
private static final long serialVersionUID = -5959253033129154037L;
|
||||
|
||||
// Use a supplier so that we can use try-with-resources with the client, which implements
|
||||
// Autocloseable.
|
||||
private final Supplier<CloudTasksClient> clientSupplier;
|
||||
|
||||
public GcpCloudTasksClient(Supplier<CloudTasksClient> clientSupplier) {
|
||||
this.clientSupplier = clientSupplier;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Task enqueue(String projectId, String locationId, String queueName, Task task) {
|
||||
try (CloudTasksClient client = clientSupplier.get()) {
|
||||
return client.createTask(QueueName.of(projectId, locationId, queueName), task);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,25 +22,23 @@ import com.google.api.client.http.HttpTransport;
|
|||
import com.google.api.client.json.JsonFactory;
|
||||
import com.google.auth.http.HttpCredentialsAdapter;
|
||||
import com.google.auth.oauth2.GoogleCredentials;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* Helper class to provide {@link HttpTransport}, {@link JsonFactory} and {@link
|
||||
* HttpRequestInitializer} for a given {@link GoogleCredentials}. These classes are normally needed
|
||||
* for creating the instance of a GCP client.
|
||||
*/
|
||||
public class GoogleCredentialsBundle {
|
||||
public class GoogleCredentialsBundle implements Serializable {
|
||||
|
||||
private static final HttpTransport HTTP_TRANSPORT = Utils.getDefaultTransport();
|
||||
private static final JsonFactory JSON_FACTORY = Utils.getDefaultJsonFactory();
|
||||
|
||||
private GoogleCredentials googleCredentials;
|
||||
private HttpTransport httpTransport;
|
||||
private JsonFactory jsonFactory;
|
||||
private HttpRequestInitializer httpRequestInitializer;
|
||||
|
||||
private GoogleCredentialsBundle(GoogleCredentials googleCredentials) {
|
||||
checkNotNull(googleCredentials);
|
||||
this.googleCredentials = googleCredentials;
|
||||
this.httpTransport = Utils.getDefaultTransport();
|
||||
this.jsonFactory = Utils.getDefaultJsonFactory();
|
||||
this.httpRequestInitializer = new HttpCredentialsAdapter(googleCredentials);
|
||||
}
|
||||
|
||||
/** Creates a {@link GoogleCredentialsBundle} instance from given {@link GoogleCredentials}. */
|
||||
|
@ -55,16 +53,16 @@ public class GoogleCredentialsBundle {
|
|||
|
||||
/** Returns the instance of {@link HttpTransport}. */
|
||||
public HttpTransport getHttpTransport() {
|
||||
return httpTransport;
|
||||
return HTTP_TRANSPORT;
|
||||
}
|
||||
|
||||
/** Returns the instance of {@link JsonFactory}. */
|
||||
public JsonFactory getJsonFactory() {
|
||||
return jsonFactory;
|
||||
return JSON_FACTORY;
|
||||
}
|
||||
|
||||
/** Returns the instance of {@link HttpRequestInitializer}. */
|
||||
public HttpRequestInitializer getHttpRequestInitializer() {
|
||||
return httpRequestInitializer;
|
||||
return new HttpCredentialsAdapter(googleCredentials);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,82 @@
|
|||
// Copyright 2020 The Nomulus Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package google.registry.util;
|
||||
|
||||
import com.google.apphosting.api.ApiProxy.Environment;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import java.util.Map;
|
||||
|
||||
/** A placeholder GAE environment class that is used when masquerading a thread as a GAE thread. */
|
||||
public final class PlaceholderEnvironment implements Environment {
|
||||
|
||||
private static final PlaceholderEnvironment INSTANCE = new PlaceholderEnvironment();
|
||||
|
||||
public static PlaceholderEnvironment get() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
private PlaceholderEnvironment() {}
|
||||
|
||||
@Override
|
||||
public String getAppId() {
|
||||
return "PlaceholderAppId";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> getAttributes() {
|
||||
return ImmutableMap.of();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getModuleId() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getVersionId() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEmail() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLoggedIn() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAdmin() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAuthDomain() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
public String getRequestNamespace() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getRemainingMillis() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
|
@ -17,18 +17,18 @@ package google.registry.util;
|
|||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import com.google.cloud.tasks.v2.CloudTasksClient;
|
||||
import com.google.cloud.tasks.v2.HttpMethod;
|
||||
import com.google.cloud.tasks.v2.QueueName;
|
||||
import com.google.cloud.tasks.v2.Task;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.LinkedListMultimap;
|
||||
import google.registry.testing.FakeClock;
|
||||
import google.registry.testing.FakeSleeper;
|
||||
import google.registry.util.CloudTasksUtils.SerializableCloudTasksClient;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
@ -37,21 +37,18 @@ import org.junit.jupiter.api.Test;
|
|||
public class CloudTasksUtilsTest {
|
||||
// Use a LinkedListMultimap to preserve order of the inserted entries for assertion.
|
||||
private final LinkedListMultimap<String, String> params = LinkedListMultimap.create();
|
||||
private final CloudTasksClient mockClient = mock(CloudTasksClient.class);
|
||||
private final SerializableCloudTasksClient mockClient = mock(SerializableCloudTasksClient.class);
|
||||
private final CloudTasksUtils cloudTasksUtils =
|
||||
new CloudTasksUtils(
|
||||
new Retrier(new FakeSleeper(new FakeClock()), 1),
|
||||
"project",
|
||||
"location",
|
||||
() -> mockClient);
|
||||
new Retrier(new FakeSleeper(new FakeClock()), 1), "project", "location", mockClient);
|
||||
|
||||
@BeforeEach
|
||||
void beforeEach() {
|
||||
params.put("key1", "val1");
|
||||
params.put("key2", "val2");
|
||||
params.put("key1", "val3");
|
||||
when(mockClient.createTask(any(QueueName.class), any(Task.class)))
|
||||
.thenAnswer(invocation -> invocation.getArgument(1));
|
||||
when(mockClient.enqueue(anyString(), anyString(), anyString(), any(Task.class)))
|
||||
.thenAnswer(invocation -> invocation.getArgument(3));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -94,7 +91,7 @@ public class CloudTasksUtilsTest {
|
|||
void testSuccess_enqueueTask() {
|
||||
Task task = CloudTasksUtils.createGetTask("/the/path", "myservice", params);
|
||||
cloudTasksUtils.enqueue("test-queue", task);
|
||||
verify(mockClient).createTask(QueueName.of("project", "location", "test-queue"), task);
|
||||
verify(mockClient).enqueue("project", "location", "test-queue", task);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -102,8 +99,8 @@ public class CloudTasksUtilsTest {
|
|||
Task task1 = CloudTasksUtils.createGetTask("/the/path", "myservice", params);
|
||||
Task task2 = CloudTasksUtils.createGetTask("/other/path", "yourservice", params);
|
||||
cloudTasksUtils.enqueue("test-queue", task1, task2);
|
||||
verify(mockClient).createTask(QueueName.of("project", "location", "test-queue"), task1);
|
||||
verify(mockClient).createTask(QueueName.of("project", "location", "test-queue"), task2);
|
||||
verify(mockClient).enqueue("project", "location", "test-queue", task1);
|
||||
verify(mockClient).enqueue("project", "location", "test-queue", task2);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -111,7 +108,7 @@ public class CloudTasksUtilsTest {
|
|||
Task task1 = CloudTasksUtils.createGetTask("/the/path", "myservice", params);
|
||||
Task task2 = CloudTasksUtils.createGetTask("/other/path", "yourservice", params);
|
||||
cloudTasksUtils.enqueue("test-queue", ImmutableList.of(task1, task2));
|
||||
verify(mockClient).createTask(QueueName.of("project", "location", "test-queue"), task1);
|
||||
verify(mockClient).createTask(QueueName.of("project", "location", "test-queue"), task2);
|
||||
verify(mockClient).enqueue("project", "location", "test-queue", task1);
|
||||
verify(mockClient).enqueue("project", "location", "test-queue", task2);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue