diff --git a/core/src/main/java/google/registry/batch/AsyncTaskEnqueuer.java b/core/src/main/java/google/registry/batch/AsyncTaskEnqueuer.java
index 8de7d16c4..65f249e76 100644
--- a/core/src/main/java/google/registry/batch/AsyncTaskEnqueuer.java
+++ b/core/src/main/java/google/registry/batch/AsyncTaskEnqueuer.java
@@ -31,6 +31,7 @@ import google.registry.model.ImmutableObject;
import google.registry.model.eppcommon.Trid;
import google.registry.model.host.HostResource;
import google.registry.persistence.VKey;
+import google.registry.schema.domain.RegistryLock;
import google.registry.util.AppEngineServiceUtils;
import google.registry.util.Retrier;
import javax.inject.Inject;
@@ -158,6 +159,26 @@ public final class AsyncTaskEnqueuer {
.param(PARAM_REQUESTED_TIME, now.toString()));
}
+ /**
+ * Enqueues a task to asynchronously re-lock a registry-locked domain after it was unlocked.
+ *
+ *
Note: the relockDuration must be present on the lock object.
+ */
+ public void enqueueDomainRelock(RegistryLock lock) {
+ checkArgument(
+ lock.getRelockDuration().isPresent(),
+ "Lock with ID %s not configured for relock",
+ lock.getRevisionId());
+ addTaskToQueueWithRetry(
+ asyncActionsPushQueue,
+ TaskOptions.Builder.withUrl(RelockDomainAction.PATH)
+ .method(Method.POST)
+ .param(
+ RelockDomainAction.OLD_UNLOCK_REVISION_ID_PARAM,
+ String.valueOf(lock.getRevisionId()))
+ .countdownMillis(lock.getRelockDuration().get().getMillis()));
+ }
+
/**
* Adds a task to a queue with retrying, to avoid aborting the entire flow over a transient issue
* enqueuing a task.
diff --git a/core/src/main/java/google/registry/batch/RelockDomainAction.java b/core/src/main/java/google/registry/batch/RelockDomainAction.java
index ef27f68f2..cf7319ea4 100644
--- a/core/src/main/java/google/registry/batch/RelockDomainAction.java
+++ b/core/src/main/java/google/registry/batch/RelockDomainAction.java
@@ -50,6 +50,7 @@ import javax.inject.Inject;
public class RelockDomainAction implements Runnable {
public static final String PATH = "/_dr/task/relockDomain";
+ public static final String OLD_UNLOCK_REVISION_ID_PARAM = "oldUnlockRevisionId";
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
@@ -59,7 +60,7 @@ public class RelockDomainAction implements Runnable {
@Inject
public RelockDomainAction(
- @Parameter("oldUnlockRevisionId") long oldUnlockRevisionId,
+ @Parameter(OLD_UNLOCK_REVISION_ID_PARAM) long oldUnlockRevisionId,
DomainLockUtils domainLockUtils,
Response response) {
this.oldUnlockRevisionId = oldUnlockRevisionId;
diff --git a/core/src/main/java/google/registry/module/frontend/FrontendRequestComponent.java b/core/src/main/java/google/registry/module/frontend/FrontendRequestComponent.java
index 9dd327526..b812a7fbe 100644
--- a/core/src/main/java/google/registry/module/frontend/FrontendRequestComponent.java
+++ b/core/src/main/java/google/registry/module/frontend/FrontendRequestComponent.java
@@ -16,6 +16,7 @@ package google.registry.module.frontend;
import dagger.Module;
import dagger.Subcomponent;
+import google.registry.batch.BatchModule;
import google.registry.dns.DnsModule;
import google.registry.flows.EppTlsAction;
import google.registry.flows.FlowComponent;
@@ -38,6 +39,7 @@ import google.registry.ui.server.registrar.RegistryLockVerifyAction;
@RequestScope
@Subcomponent(
modules = {
+ BatchModule.class,
DnsModule.class,
EppTlsModule.class,
RegistrarConsoleModule.class,
diff --git a/core/src/main/java/google/registry/tools/DomainLockUtils.java b/core/src/main/java/google/registry/tools/DomainLockUtils.java
index cd47f10c0..ee0bf4c4f 100644
--- a/core/src/main/java/google/registry/tools/DomainLockUtils.java
+++ b/core/src/main/java/google/registry/tools/DomainLockUtils.java
@@ -24,6 +24,7 @@ import static google.registry.tools.LockOrUnlockDomainCommand.REGISTRY_LOCK_STAT
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import com.googlecode.objectify.Key;
+import google.registry.batch.AsyncTaskEnqueuer;
import google.registry.model.billing.BillingEvent;
import google.registry.model.billing.BillingEvent.Reason;
import google.registry.model.domain.DomainBase;
@@ -51,10 +52,14 @@ public final class DomainLockUtils {
private static final int VERIFICATION_CODE_LENGTH = 32;
private final StringGenerator stringGenerator;
+ private final AsyncTaskEnqueuer asyncTaskEnqueuer;
@Inject
- public DomainLockUtils(@Named("base58StringGenerator") StringGenerator stringGenerator) {
+ public DomainLockUtils(
+ @Named("base58StringGenerator") StringGenerator stringGenerator,
+ AsyncTaskEnqueuer asyncTaskEnqueuer) {
this.stringGenerator = stringGenerator;
+ this.asyncTaskEnqueuer = asyncTaskEnqueuer;
}
/**
@@ -115,35 +120,41 @@ public final class DomainLockUtils {
/** Verifies and applies the unlock request previously requested by a user. */
public RegistryLock verifyAndApplyUnlock(String verificationCode, boolean isAdmin) {
- return jpaTm()
- .transact(
- () -> {
- DateTime now = jpaTm().getTransactionTime();
- RegistryLock lock = getByVerificationCode(verificationCode);
- checkArgument(
- !lock.getUnlockCompletionTimestamp().isPresent(),
- "Domain %s is already unlocked",
- lock.getDomainName());
+ RegistryLock lock =
+ jpaTm()
+ .transact(
+ () -> {
+ DateTime now = jpaTm().getTransactionTime();
+ RegistryLock previousLock = getByVerificationCode(verificationCode);
+ checkArgument(
+ !previousLock.getUnlockCompletionTimestamp().isPresent(),
+ "Domain %s is already unlocked",
+ previousLock.getDomainName());
- checkArgument(
- !lock.isUnlockRequestExpired(now),
- "The pending unlock has expired; please try again");
+ checkArgument(
+ !previousLock.isUnlockRequestExpired(now),
+ "The pending unlock has expired; please try again");
- checkArgument(
- isAdmin || !lock.isSuperuser(), "Non-admin user cannot complete admin unlock");
+ checkArgument(
+ isAdmin || !previousLock.isSuperuser(),
+ "Non-admin user cannot complete admin unlock");
- RegistryLock newLock =
- RegistryLockDao.save(lock.asBuilder().setUnlockCompletionTimestamp(now).build());
- tm().transact(() -> removeLockStatuses(newLock, isAdmin, now));
- return newLock;
- });
+ RegistryLock newLock =
+ RegistryLockDao.save(
+ previousLock.asBuilder().setUnlockCompletionTimestamp(now).build());
+ tm().transact(() -> removeLockStatuses(newLock, isAdmin, now));
+ return newLock;
+ });
+ // Submit relock outside of the transaction to make sure that it fully succeeded
+ submitRelockIfNecessary(lock);
+ return lock;
}
/**
- * Creates and applies a lock in one step -- this should only be used for admin actions, e.g.
- * Nomulus tool commands or relocks.
+ * Creates and applies a lock in one step.
*
- *
Note: in the case of relocks, isAdmin is determined by the previous lock.
+ *
This should only be used for admin actions, e.g. Nomulus tool commands or relocks.
+ * Note: in the case of relocks, isAdmin is determined by the previous lock.
*/
public RegistryLock administrativelyApplyLock(
String domainName, String registrarId, @Nullable String registrarPocId, boolean isAdmin) {
@@ -163,23 +174,34 @@ public final class DomainLockUtils {
}
/**
- * Creates and applies an unlock in one step -- this should only be used for admin actions, e.g.
- * Nomulus tool commands.
+ * Creates and applies an unlock in one step.
+ *
+ *
This should only be used for admin actions, e.g. Nomulus tool commands.
*/
public RegistryLock administrativelyApplyUnlock(
String domainName, String registrarId, boolean isAdmin, Optional relockDuration) {
- return jpaTm()
- .transact(
- () -> {
- DateTime now = jpaTm().getTransactionTime();
- RegistryLock result =
- RegistryLockDao.save(
- createUnlockBuilder(domainName, registrarId, isAdmin, relockDuration)
- .setUnlockCompletionTimestamp(now)
- .build());
- tm().transact(() -> removeLockStatuses(result, isAdmin, now));
- return result;
- });
+ RegistryLock lock =
+ jpaTm()
+ .transact(
+ () -> {
+ DateTime now = jpaTm().getTransactionTime();
+ RegistryLock result =
+ RegistryLockDao.save(
+ createUnlockBuilder(domainName, registrarId, isAdmin, relockDuration)
+ .setUnlockCompletionTimestamp(now)
+ .build());
+ tm().transact(() -> removeLockStatuses(result, isAdmin, now));
+ return result;
+ });
+ // Submit relock outside of the transaction to make sure that it fully succeeded
+ submitRelockIfNecessary(lock);
+ return lock;
+ }
+
+ private void submitRelockIfNecessary(RegistryLock lock) {
+ if (lock.getRelockDuration().isPresent()) {
+ asyncTaskEnqueuer.enqueueDomainRelock(lock);
+ }
}
private void setAsRelock(RegistryLock newLock) {
diff --git a/core/src/main/java/google/registry/tools/RegistryToolComponent.java b/core/src/main/java/google/registry/tools/RegistryToolComponent.java
index d855e9cd1..e2b18cfb9 100644
--- a/core/src/main/java/google/registry/tools/RegistryToolComponent.java
+++ b/core/src/main/java/google/registry/tools/RegistryToolComponent.java
@@ -16,6 +16,7 @@ package google.registry.tools;
import dagger.BindsInstance;
import dagger.Component;
+import google.registry.batch.BatchModule;
import google.registry.bigquery.BigqueryModule;
import google.registry.config.CredentialModule.LocalCredentialJson;
import google.registry.config.RegistryConfig.ConfigModule;
@@ -54,6 +55,7 @@ import javax.inject.Singleton;
modules = {
AppEngineAdminApiModule.class,
AuthModule.class,
+ BatchModule.class,
BigqueryModule.class,
ConfigModule.class,
CloudDnsWriterModule.class,
diff --git a/core/src/test/java/google/registry/batch/AsyncTaskEnqueuerTest.java b/core/src/test/java/google/registry/batch/AsyncTaskEnqueuerTest.java
index d05d1c3b2..5f5d26c9b 100644
--- a/core/src/test/java/google/registry/batch/AsyncTaskEnqueuerTest.java
+++ b/core/src/test/java/google/registry/batch/AsyncTaskEnqueuerTest.java
@@ -15,6 +15,7 @@
package google.registry.batch;
import static com.google.appengine.api.taskqueue.QueueFactory.getQueue;
+import static com.google.common.truth.Truth.assertThat;
import static google.registry.batch.AsyncTaskEnqueuer.PARAM_REQUESTED_TIME;
import static google.registry.batch.AsyncTaskEnqueuer.PARAM_RESAVE_TIMES;
import static google.registry.batch.AsyncTaskEnqueuer.PARAM_RESOURCE_KEY;
@@ -23,18 +24,21 @@ import static google.registry.batch.AsyncTaskEnqueuer.QUEUE_ASYNC_ACTIONS;
import static google.registry.batch.AsyncTaskEnqueuer.QUEUE_ASYNC_DELETE;
import static google.registry.batch.AsyncTaskEnqueuer.QUEUE_ASYNC_HOST_RENAME;
import static google.registry.testing.DatastoreHelper.persistActiveContact;
+import static google.registry.testing.SqlHelper.saveRegistryLock;
import static google.registry.testing.TaskQueueHelper.assertNoTasksEnqueued;
import static google.registry.testing.TaskQueueHelper.assertTasksEnqueued;
import static google.registry.testing.TestLogHandlerUtils.assertLogMessage;
import static org.joda.time.Duration.standardDays;
import static org.joda.time.Duration.standardHours;
import static org.joda.time.Duration.standardSeconds;
+import static org.junit.Assert.assertThrows;
import static org.mockito.Mockito.when;
import com.google.common.collect.ImmutableSortedSet;
import com.google.common.flogger.LoggerConfig;
import com.googlecode.objectify.Key;
import google.registry.model.contact.ContactResource;
+import google.registry.schema.domain.RegistryLock;
import google.registry.testing.AppEngineRule;
import google.registry.testing.FakeClock;
import google.registry.testing.FakeSleeper;
@@ -46,6 +50,7 @@ import google.registry.util.CapturingLogHandler;
import google.registry.util.Retrier;
import java.util.logging.Level;
import org.joda.time.DateTime;
+import org.joda.time.Duration;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -77,14 +82,18 @@ public class AsyncTaskEnqueuerTest extends ShardableTestCase {
public void setUp() {
LoggerConfig.getConfig(AsyncTaskEnqueuer.class).addHandler(logHandler);
when(appEngineServiceUtils.getServiceHostname("backend")).thenReturn("backend.hostname.fake");
- asyncTaskEnqueuer =
- new AsyncTaskEnqueuer(
- getQueue(QUEUE_ASYNC_ACTIONS),
- getQueue(QUEUE_ASYNC_DELETE),
- getQueue(QUEUE_ASYNC_HOST_RENAME),
- standardSeconds(90),
- appEngineServiceUtils,
- new Retrier(new FakeSleeper(clock), 1));
+ asyncTaskEnqueuer = createForTesting(appEngineServiceUtils, clock, standardSeconds(90));
+ }
+
+ public static AsyncTaskEnqueuer createForTesting(
+ AppEngineServiceUtils appEngineServiceUtils, FakeClock clock, Duration asyncDeleteDelay) {
+ return new AsyncTaskEnqueuer(
+ getQueue(QUEUE_ASYNC_ACTIONS),
+ getQueue(QUEUE_ASYNC_DELETE),
+ getQueue(QUEUE_ASYNC_HOST_RENAME),
+ asyncDeleteDelay,
+ appEngineServiceUtils,
+ new Retrier(new FakeSleeper(clock), 1));
}
@Test
@@ -137,4 +146,56 @@ public class AsyncTaskEnqueuerTest extends ShardableTestCase {
assertNoTasksEnqueued(QUEUE_ASYNC_ACTIONS);
assertLogMessage(logHandler, Level.INFO, "Ignoring async re-save");
}
+
+ @Test
+ public void testEnqueueRelock() {
+ RegistryLock lock =
+ saveRegistryLock(
+ new RegistryLock.Builder()
+ .setLockCompletionTimestamp(clock.nowUtc())
+ .setUnlockRequestTimestamp(clock.nowUtc())
+ .setUnlockCompletionTimestamp(clock.nowUtc())
+ .isSuperuser(false)
+ .setDomainName("example.tld")
+ .setRepoId("repoId")
+ .setRelockDuration(standardHours(6))
+ .setRegistrarId("TheRegistrar")
+ .setRegistrarPocId("someone@example.com")
+ .setVerificationCode("hi")
+ .build());
+ asyncTaskEnqueuer.enqueueDomainRelock(lock);
+ assertTasksEnqueued(
+ QUEUE_ASYNC_ACTIONS,
+ new TaskMatcher()
+ .url(RelockDomainAction.PATH)
+ .method("POST")
+ .param(
+ RelockDomainAction.OLD_UNLOCK_REVISION_ID_PARAM,
+ String.valueOf(lock.getRevisionId()))
+ .etaDelta(
+ standardHours(6).minus(standardSeconds(30)),
+ standardHours(6).plus(standardSeconds(30))));
+ }
+
+ @Test
+ public void testFailure_enqueueRelock_noDuration() {
+ RegistryLock lockWithoutDuration =
+ saveRegistryLock(
+ new RegistryLock.Builder()
+ .isSuperuser(false)
+ .setDomainName("example.tld")
+ .setRepoId("repoId")
+ .setRegistrarId("TheRegistrar")
+ .setRegistrarPocId("someone@example.com")
+ .setVerificationCode("hi")
+ .build());
+ assertThat(
+ assertThrows(
+ IllegalArgumentException.class,
+ () -> asyncTaskEnqueuer.enqueueDomainRelock(lockWithoutDuration)))
+ .hasMessageThat()
+ .isEqualTo(
+ String.format(
+ "Lock with ID %s not configured for relock", lockWithoutDuration.getRevisionId()));
+ }
}
diff --git a/core/src/test/java/google/registry/batch/DeleteContactsAndHostsActionTest.java b/core/src/test/java/google/registry/batch/DeleteContactsAndHostsActionTest.java
index 54641cbbd..c244b8ecb 100644
--- a/core/src/test/java/google/registry/batch/DeleteContactsAndHostsActionTest.java
+++ b/core/src/test/java/google/registry/batch/DeleteContactsAndHostsActionTest.java
@@ -18,9 +18,7 @@ import static com.google.appengine.api.taskqueue.QueueFactory.getQueue;
import static com.google.common.collect.MoreCollectors.onlyElement;
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth8.assertThat;
-import static google.registry.batch.AsyncTaskEnqueuer.QUEUE_ASYNC_ACTIONS;
import static google.registry.batch.AsyncTaskEnqueuer.QUEUE_ASYNC_DELETE;
-import static google.registry.batch.AsyncTaskEnqueuer.QUEUE_ASYNC_HOST_RENAME;
import static google.registry.batch.AsyncTaskMetrics.OperationResult.STALE;
import static google.registry.model.EppResourceUtils.loadByForeignKey;
import static google.registry.model.eppcommon.StatusValue.PENDING_DELETE;
@@ -151,13 +149,8 @@ public class DeleteContactsAndHostsActionTest
public void setup() {
inject.setStaticField(Ofy.class, "clock", clock);
enqueuer =
- new AsyncTaskEnqueuer(
- getQueue(QUEUE_ASYNC_ACTIONS),
- getQueue(QUEUE_ASYNC_DELETE),
- getQueue(QUEUE_ASYNC_HOST_RENAME),
- Duration.ZERO,
- mock(AppEngineServiceUtils.class),
- new Retrier(new FakeSleeper(clock), 1));
+ AsyncTaskEnqueuerTest.createForTesting(
+ mock(AppEngineServiceUtils.class), clock, Duration.ZERO);
AsyncTaskMetrics asyncTaskMetricsMock = mock(AsyncTaskMetrics.class);
action = new DeleteContactsAndHostsAction();
action.asyncTaskMetrics = asyncTaskMetricsMock;
diff --git a/core/src/test/java/google/registry/batch/RefreshDnsOnHostRenameActionTest.java b/core/src/test/java/google/registry/batch/RefreshDnsOnHostRenameActionTest.java
index 22e90b697..a459813e9 100644
--- a/core/src/test/java/google/registry/batch/RefreshDnsOnHostRenameActionTest.java
+++ b/core/src/test/java/google/registry/batch/RefreshDnsOnHostRenameActionTest.java
@@ -17,8 +17,6 @@ package google.registry.batch;
import static com.google.appengine.api.taskqueue.QueueFactory.getQueue;
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth8.assertThat;
-import static google.registry.batch.AsyncTaskEnqueuer.QUEUE_ASYNC_ACTIONS;
-import static google.registry.batch.AsyncTaskEnqueuer.QUEUE_ASYNC_DELETE;
import static google.registry.batch.AsyncTaskEnqueuer.QUEUE_ASYNC_HOST_RENAME;
import static google.registry.batch.AsyncTaskMetrics.OperationType.DNS_REFRESH;
import static google.registry.model.ofy.ObjectifyService.ofy;
@@ -86,13 +84,8 @@ public class RefreshDnsOnHostRenameActionTest
public void setup() {
createTld("tld");
enqueuer =
- new AsyncTaskEnqueuer(
- getQueue(QUEUE_ASYNC_ACTIONS),
- getQueue(QUEUE_ASYNC_DELETE),
- getQueue(QUEUE_ASYNC_HOST_RENAME),
- Duration.ZERO,
- mock(AppEngineServiceUtils.class),
- new Retrier(new FakeSleeper(clock), 1));
+ AsyncTaskEnqueuerTest.createForTesting(
+ mock(AppEngineServiceUtils.class), clock, Duration.ZERO);
AsyncTaskMetrics asyncTaskMetricsMock = mock(AsyncTaskMetrics.class);
action = new RefreshDnsOnHostRenameAction();
action.asyncTaskMetrics = asyncTaskMetricsMock;
diff --git a/core/src/test/java/google/registry/batch/RelockDomainActionTest.java b/core/src/test/java/google/registry/batch/RelockDomainActionTest.java
index f8137d69d..1e7feea04 100644
--- a/core/src/test/java/google/registry/batch/RelockDomainActionTest.java
+++ b/core/src/test/java/google/registry/batch/RelockDomainActionTest.java
@@ -28,6 +28,7 @@ import static google.registry.testing.SqlHelper.getRegistryLockByVerificationCod
import static google.registry.testing.SqlHelper.saveRegistryLock;
import static google.registry.tools.LockOrUnlockDomainCommand.REGISTRY_LOCK_STATUSES;
import static javax.servlet.http.HttpServletResponse.SC_NO_CONTENT;
+import static org.mockito.Mockito.mock;
import com.google.common.collect.ImmutableSet;
import google.registry.model.domain.DomainBase;
@@ -39,8 +40,10 @@ import google.registry.testing.FakeClock;
import google.registry.testing.FakeResponse;
import google.registry.testing.UserInfo;
import google.registry.tools.DomainLockUtils;
+import google.registry.util.AppEngineServiceUtils;
import google.registry.util.StringGenerator.Alphabets;
import java.util.Optional;
+import org.joda.time.Duration;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -58,7 +61,10 @@ public class RelockDomainActionTest {
private final FakeResponse response = new FakeResponse();
private final FakeClock clock = new FakeClock();
private final DomainLockUtils domainLockUtils =
- new DomainLockUtils(new DeterministicStringGenerator(Alphabets.BASE_58));
+ new DomainLockUtils(
+ new DeterministicStringGenerator(Alphabets.BASE_58),
+ AsyncTaskEnqueuerTest.createForTesting(
+ mock(AppEngineServiceUtils.class), clock, Duration.ZERO));
@Rule
public final AppEngineRule appEngineRule =
diff --git a/core/src/test/java/google/registry/batch/ResaveEntityActionTest.java b/core/src/test/java/google/registry/batch/ResaveEntityActionTest.java
index aae0ff413..4804684f0 100644
--- a/core/src/test/java/google/registry/batch/ResaveEntityActionTest.java
+++ b/core/src/test/java/google/registry/batch/ResaveEntityActionTest.java
@@ -14,14 +14,11 @@
package google.registry.batch;
-import static com.google.appengine.api.taskqueue.QueueFactory.getQueue;
import static com.google.common.truth.Truth.assertThat;
import static google.registry.batch.AsyncTaskEnqueuer.PARAM_REQUESTED_TIME;
import static google.registry.batch.AsyncTaskEnqueuer.PARAM_RESOURCE_KEY;
import static google.registry.batch.AsyncTaskEnqueuer.PATH_RESAVE_ENTITY;
import static google.registry.batch.AsyncTaskEnqueuer.QUEUE_ASYNC_ACTIONS;
-import static google.registry.batch.AsyncTaskEnqueuer.QUEUE_ASYNC_DELETE;
-import static google.registry.batch.AsyncTaskEnqueuer.QUEUE_ASYNC_HOST_RENAME;
import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.testing.DatastoreHelper.createTld;
import static google.registry.testing.DatastoreHelper.newDomainBase;
@@ -47,12 +44,10 @@ import google.registry.model.ofy.Ofy;
import google.registry.request.Response;
import google.registry.testing.AppEngineRule;
import google.registry.testing.FakeClock;
-import google.registry.testing.FakeSleeper;
import google.registry.testing.InjectRule;
import google.registry.testing.ShardableTestCase;
import google.registry.testing.TaskQueueHelper.TaskMatcher;
import google.registry.util.AppEngineServiceUtils;
-import google.registry.util.Retrier;
import org.joda.time.DateTime;
import org.joda.time.Duration;
import org.junit.Before;
@@ -85,13 +80,7 @@ public class ResaveEntityActionTest extends ShardableTestCase {
inject.setStaticField(Ofy.class, "clock", clock);
when(appEngineServiceUtils.getServiceHostname("backend")).thenReturn("backend.hostname.fake");
asyncTaskEnqueuer =
- new AsyncTaskEnqueuer(
- getQueue(QUEUE_ASYNC_ACTIONS),
- getQueue(QUEUE_ASYNC_DELETE),
- getQueue(QUEUE_ASYNC_HOST_RENAME),
- Duration.ZERO,
- appEngineServiceUtils,
- new Retrier(new FakeSleeper(clock), 1));
+ AsyncTaskEnqueuerTest.createForTesting(appEngineServiceUtils, clock, Duration.ZERO);
createTld("tld");
}
diff --git a/core/src/test/java/google/registry/flows/EppTestComponent.java b/core/src/test/java/google/registry/flows/EppTestComponent.java
index ac6b79ac5..80a278265 100644
--- a/core/src/test/java/google/registry/flows/EppTestComponent.java
+++ b/core/src/test/java/google/registry/flows/EppTestComponent.java
@@ -14,10 +14,7 @@
package google.registry.flows;
-import static com.google.appengine.api.taskqueue.QueueFactory.getQueue;
-import static google.registry.batch.AsyncTaskEnqueuer.QUEUE_ASYNC_ACTIONS;
-import static google.registry.batch.AsyncTaskEnqueuer.QUEUE_ASYNC_DELETE;
-import static google.registry.batch.AsyncTaskEnqueuer.QUEUE_ASYNC_HOST_RENAME;
+import static org.joda.time.Duration.standardSeconds;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@@ -26,6 +23,7 @@ import dagger.Module;
import dagger.Provides;
import dagger.Subcomponent;
import google.registry.batch.AsyncTaskEnqueuer;
+import google.registry.batch.AsyncTaskEnqueuerTest;
import google.registry.config.RegistryConfig.ConfigModule;
import google.registry.config.RegistryConfig.ConfigModule.TmchCaMode;
import google.registry.dns.DnsQueue;
@@ -42,10 +40,8 @@ import google.registry.tmch.TmchCertificateAuthority;
import google.registry.tmch.TmchXmlSignature;
import google.registry.util.AppEngineServiceUtils;
import google.registry.util.Clock;
-import google.registry.util.Retrier;
import google.registry.util.Sleeper;
import javax.inject.Singleton;
-import org.joda.time.Duration;
/** Dagger component for running EPP tests. */
@Singleton
@@ -84,20 +80,12 @@ interface EppTestComponent {
}
public static FakesAndMocksModule create(
- FakeClock clock,
- EppMetric.Builder eppMetricBuilder,
- TmchXmlSignature tmchXmlSignature) {
+ FakeClock clock, EppMetric.Builder eppMetricBuilder, TmchXmlSignature tmchXmlSignature) {
FakesAndMocksModule instance = new FakesAndMocksModule();
AppEngineServiceUtils appEngineServiceUtils = mock(AppEngineServiceUtils.class);
when(appEngineServiceUtils.getServiceHostname("backend")).thenReturn("backend.hostname.fake");
instance.asyncTaskEnqueuer =
- new AsyncTaskEnqueuer(
- getQueue(QUEUE_ASYNC_ACTIONS),
- getQueue(QUEUE_ASYNC_DELETE),
- getQueue(QUEUE_ASYNC_HOST_RENAME),
- Duration.standardSeconds(90),
- appEngineServiceUtils,
- new Retrier(new FakeSleeper(clock), 1));
+ AsyncTaskEnqueuerTest.createForTesting(appEngineServiceUtils, clock, standardSeconds(90));
instance.clock = clock;
instance.domainFlowTmchUtils = new DomainFlowTmchUtils(tmchXmlSignature);
instance.sleeper = new FakeSleeper(clock);
diff --git a/core/src/test/java/google/registry/tools/DomainLockUtilsTest.java b/core/src/test/java/google/registry/tools/DomainLockUtilsTest.java
index dfc03722b..3ee5706ae 100644
--- a/core/src/test/java/google/registry/tools/DomainLockUtilsTest.java
+++ b/core/src/test/java/google/registry/tools/DomainLockUtilsTest.java
@@ -15,6 +15,7 @@
package google.registry.tools;
import static com.google.common.truth.Truth.assertThat;
+import static google.registry.batch.AsyncTaskEnqueuer.QUEUE_ASYNC_ACTIONS;
import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.testing.DatastoreHelper.assertNoBillingEvents;
import static google.registry.testing.DatastoreHelper.createTlds;
@@ -25,10 +26,17 @@ import static google.registry.testing.DatastoreHelper.persistActiveHost;
import static google.registry.testing.DatastoreHelper.persistResource;
import static google.registry.testing.SqlHelper.getRegistryLockByRevisionId;
import static google.registry.testing.SqlHelper.getRegistryLockByVerificationCode;
+import static google.registry.testing.TaskQueueHelper.assertTasksEnqueued;
import static google.registry.tools.LockOrUnlockDomainCommand.REGISTRY_LOCK_STATUSES;
+import static org.joda.time.Duration.standardDays;
+import static org.joda.time.Duration.standardHours;
+import static org.joda.time.Duration.standardSeconds;
import static org.junit.Assert.assertThrows;
+import static org.mockito.Mockito.mock;
import com.google.common.collect.ImmutableList;
+import google.registry.batch.AsyncTaskEnqueuerTest;
+import google.registry.batch.RelockDomainAction;
import google.registry.model.billing.BillingEvent;
import google.registry.model.billing.BillingEvent.Reason;
import google.registry.model.domain.DomainBase;
@@ -40,12 +48,15 @@ import google.registry.testing.AppEngineRule;
import google.registry.testing.DatastoreHelper;
import google.registry.testing.DeterministicStringGenerator;
import google.registry.testing.FakeClock;
+import google.registry.testing.TaskQueueHelper.TaskMatcher;
import google.registry.testing.UserInfo;
+import google.registry.util.AppEngineServiceUtils;
import google.registry.util.StringGenerator.Alphabets;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
-import org.joda.time.Duration;
+import org.joda.time.DateTime;
+import org.joda.time.DateTimeZone;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -59,15 +70,19 @@ public final class DomainLockUtilsTest {
private static final String DOMAIN_NAME = "example.tld";
private static final String POC_ID = "marla.singer@example.com";
- private final FakeClock clock = new FakeClock();
+ private final FakeClock clock = new FakeClock(DateTime.now(DateTimeZone.UTC));
private final DomainLockUtils domainLockUtils =
- new DomainLockUtils(new DeterministicStringGenerator(Alphabets.BASE_58));
+ new DomainLockUtils(
+ new DeterministicStringGenerator(Alphabets.BASE_58),
+ AsyncTaskEnqueuerTest.createForTesting(
+ mock(AppEngineServiceUtils.class), clock, standardSeconds(90)));
@Rule
public final AppEngineRule appEngineRule =
AppEngineRule.builder()
.withDatastoreAndCloudSql()
.withClock(clock)
+ .withTaskQueue()
.withUserService(UserInfo.create(POC_ID, "12345"))
.build();
@@ -109,7 +124,7 @@ public final class DomainLockUtilsTest {
@Test
public void testSuccess_createLock_previousLockExpired() {
domainLockUtils.saveNewRegistryLockRequest(DOMAIN_NAME, "TheRegistrar", POC_ID, false);
- clock.advanceBy(Duration.standardDays(1));
+ clock.advanceBy(standardDays(1));
RegistryLock lock =
domainLockUtils.saveNewRegistryLockRequest(DOMAIN_NAME, "TheRegistrar", POC_ID, false);
domainLockUtils.verifyAndApplyLock(lock.getVerificationCode(), false);
@@ -121,7 +136,7 @@ public final class DomainLockUtilsTest {
domainLockUtils.administrativelyApplyLock(DOMAIN_NAME, "TheRegistrar", POC_ID, false);
domainLockUtils.saveNewRegistryUnlockRequest(
DOMAIN_NAME, "TheRegistrar", false, Optional.empty());
- clock.advanceBy(Duration.standardDays(1));
+ clock.advanceBy(standardDays(1));
RegistryLock unlockRequest =
domainLockUtils.saveNewRegistryUnlockRequest(
DOMAIN_NAME, "TheRegistrar", false, Optional.empty());
@@ -232,8 +247,28 @@ public final class DomainLockUtilsTest {
domainLockUtils.administrativelyApplyLock(DOMAIN_NAME, "TheRegistrar", POC_ID, false);
RegistryLock lock =
domainLockUtils.saveNewRegistryUnlockRequest(
- DOMAIN_NAME, "TheRegistrar", false, Optional.of(Duration.standardDays(1)));
- assertThat(lock.getRelockDuration()).isEqualTo(Optional.of(Duration.standardDays(1)));
+ DOMAIN_NAME, "TheRegistrar", false, Optional.of(standardDays(1)));
+ assertThat(lock.getRelockDuration()).isEqualTo(Optional.of(standardDays(1)));
+ }
+
+ @Test
+ public void testSuccess_unlock_relockSubmitted() {
+ domainLockUtils.administrativelyApplyLock(DOMAIN_NAME, "TheRegistrar", POC_ID, false);
+ RegistryLock lock =
+ domainLockUtils.saveNewRegistryUnlockRequest(
+ DOMAIN_NAME, "TheRegistrar", false, Optional.of(standardHours(6)));
+ domainLockUtils.verifyAndApplyUnlock(lock.getVerificationCode(), false);
+ assertTasksEnqueued(
+ QUEUE_ASYNC_ACTIONS,
+ new TaskMatcher()
+ .url(RelockDomainAction.PATH)
+ .method("POST")
+ .param(
+ RelockDomainAction.OLD_UNLOCK_REVISION_ID_PARAM,
+ String.valueOf(lock.getRevisionId()))
+ .etaDelta(
+ standardHours(6).minus(standardSeconds(30)),
+ standardDays(6).plus(standardSeconds(30))));
}
@Test
@@ -338,7 +373,7 @@ public final class DomainLockUtilsTest {
public void testFailure_applyLock_expired() {
RegistryLock lock =
domainLockUtils.saveNewRegistryLockRequest(DOMAIN_NAME, "TheRegistrar", POC_ID, false);
- clock.advanceBy(Duration.standardDays(1));
+ clock.advanceBy(standardDays(1));
assertThat(
assertThrows(
IllegalArgumentException.class,
diff --git a/core/src/test/java/google/registry/tools/LockDomainCommandTest.java b/core/src/test/java/google/registry/tools/LockDomainCommandTest.java
index b189fe5af..ea6fb6671 100644
--- a/core/src/test/java/google/registry/tools/LockDomainCommandTest.java
+++ b/core/src/test/java/google/registry/tools/LockDomainCommandTest.java
@@ -24,15 +24,19 @@ import static google.registry.testing.DatastoreHelper.persistResource;
import static google.registry.testing.SqlHelper.getMostRecentRegistryLockByRepoId;
import static google.registry.tools.LockOrUnlockDomainCommand.REGISTRY_LOCK_STATUSES;
import static org.junit.Assert.assertThrows;
+import static org.mockito.Mockito.mock;
import com.google.common.collect.ImmutableList;
+import google.registry.batch.AsyncTaskEnqueuerTest;
import google.registry.model.domain.DomainBase;
import google.registry.model.registrar.Registrar.Type;
import google.registry.testing.DeterministicStringGenerator;
+import google.registry.util.AppEngineServiceUtils;
import google.registry.util.StringGenerator.Alphabets;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
+import org.joda.time.Duration;
import org.junit.Before;
import org.junit.Test;
@@ -45,7 +49,10 @@ public class LockDomainCommandTest extends CommandTestCase {
createTld("tld");
command.registryAdminClientId = "adminreg";
command.domainLockUtils =
- new DomainLockUtils(new DeterministicStringGenerator(Alphabets.BASE_58));
+ new DomainLockUtils(
+ new DeterministicStringGenerator(Alphabets.BASE_58),
+ AsyncTaskEnqueuerTest.createForTesting(
+ mock(AppEngineServiceUtils.class), fakeClock, Duration.ZERO));
}
@Test
diff --git a/core/src/test/java/google/registry/tools/UnlockDomainCommandTest.java b/core/src/test/java/google/registry/tools/UnlockDomainCommandTest.java
index 5c91878ea..bfb7a2bdb 100644
--- a/core/src/test/java/google/registry/tools/UnlockDomainCommandTest.java
+++ b/core/src/test/java/google/registry/tools/UnlockDomainCommandTest.java
@@ -25,17 +25,21 @@ import static google.registry.testing.DatastoreHelper.persistResource;
import static google.registry.testing.SqlHelper.getMostRecentRegistryLockByRepoId;
import static google.registry.tools.LockOrUnlockDomainCommand.REGISTRY_LOCK_STATUSES;
import static org.junit.Assert.assertThrows;
+import static org.mockito.Mockito.mock;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
+import google.registry.batch.AsyncTaskEnqueuerTest;
import google.registry.model.domain.DomainBase;
import google.registry.model.registrar.Registrar.Type;
import google.registry.schema.domain.RegistryLock;
import google.registry.testing.DeterministicStringGenerator;
+import google.registry.util.AppEngineServiceUtils;
import google.registry.util.StringGenerator.Alphabets;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
+import org.joda.time.Duration;
import org.junit.Before;
import org.junit.Test;
@@ -48,7 +52,10 @@ public class UnlockDomainCommandTest extends CommandTestCase