diff --git a/core/src/main/java/google/registry/flows/domain/DomainDeleteFlow.java b/core/src/main/java/google/registry/flows/domain/DomainDeleteFlow.java index 0a3da5183..f9d068f90 100644 --- a/core/src/main/java/google/registry/flows/domain/DomainDeleteFlow.java +++ b/core/src/main/java/google/registry/flows/domain/DomainDeleteFlow.java @@ -208,13 +208,21 @@ public final class DomainDeleteFlow implements TransactionalFlow { // Enqueue the deletion poll message if the delete is asynchronous or if requested by a // superuser (i.e. the registrar didn't request this delete and thus should be notified even if // it is synchronous). - if (!durationUntilDelete.equals(Duration.ZERO) || isSuperuser) { + if (durationUntilDelete.isLongerThan(Duration.ZERO) || isSuperuser) { PollMessage.OneTime deletePollMessage = createDeletePollMessage(existingDomain, historyEntry, deletionTime); entitiesToSave.add(deletePollMessage); builder.setDeletePollMessage(deletePollMessage.createVKey()); } + // Send a second poll message immediately if the domain is being deleted asynchronously by a + // registrar other than the sponsoring registrar (which will necessarily be a superuser). + if (durationUntilDelete.isLongerThan(Duration.ZERO) + && !clientId.equals(existingDomain.getPersistedCurrentSponsorClientId())) { + entitiesToSave.add( + createImmediateDeletePollMessage(existingDomain, historyEntry, now, deletionTime)); + } + // Cancel any grace periods that were still active, and set the expiration time accordingly. DateTime newExpirationTime = existingDomain.getRegistrationExpirationTime(); for (GracePeriod gracePeriod : existingDomain.getGracePeriods()) { @@ -346,6 +354,19 @@ public final class DomainDeleteFlow implements TransactionalFlow { .build(); } + private PollMessage.OneTime createImmediateDeletePollMessage( + DomainBase existingDomain, HistoryEntry historyEntry, DateTime now, DateTime deletionTime) { + return new PollMessage.OneTime.Builder() + .setClientId(existingDomain.getPersistedCurrentSponsorClientId()) + .setEventTime(now) + .setParent(historyEntry) + .setMsg( + String.format( + "Domain %s was deleted by registry administrator with final deletion effective: %s", + existingDomain.getDomainName(), deletionTime)) + .build(); + } + @Nullable private ImmutableList getResponseExtensions( DomainBase existingDomain, DateTime now) { diff --git a/core/src/test/java/google/registry/flows/domain/DomainDeleteFlowTest.java b/core/src/test/java/google/registry/flows/domain/DomainDeleteFlowTest.java index 8d8ff6d0b..6cadf91cd 100644 --- a/core/src/test/java/google/registry/flows/domain/DomainDeleteFlowTest.java +++ b/core/src/test/java/google/registry/flows/domain/DomainDeleteFlowTest.java @@ -59,6 +59,7 @@ import static org.joda.time.Duration.standardDays; import static org.joda.time.Duration.standardSeconds; import static org.junit.jupiter.api.Assertions.assertThrows; +import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSortedMap; @@ -87,6 +88,7 @@ import google.registry.model.eppcommon.StatusValue; import google.registry.model.eppcommon.Trid; import google.registry.model.host.HostResource; import google.registry.model.poll.PendingActionNotificationResponse; +import google.registry.model.poll.PendingActionNotificationResponse.DomainPendingActionNotificationResponse; import google.registry.model.poll.PollMessage; import google.registry.model.registry.Registry; import google.registry.model.registry.Registry.TldType; @@ -328,12 +330,12 @@ class DomainDeleteFlowTest extends ResourceFlowTestCase substitutions) @@ -355,7 +357,7 @@ class DomainDeleteFlowTest extends ResourceFlowTestCase getPollMessages(String clientId, DateTime now) { + public static ImmutableList getPollMessages(String clientId, DateTime beforeOrAt) { return transactIfJpaTm( () -> tm().loadAllOf(PollMessage.class).stream() .filter(pollMessage -> pollMessage.getClientId().equals(clientId)) - .filter( - pollMessage -> - pollMessage.getEventTime().isEqual(now) - || pollMessage.getEventTime().isBefore(now)) + .filter(pollMessage -> isBeforeOrAt(pollMessage.getEventTime(), beforeOrAt)) .collect(toImmutableList())); }