1
0
mirror of https://github.com/google/nomulus synced 2026-01-05 04:56:03 +00:00

Fail permamently in re-save entity action when entity doesn't exist (#2492)

Our logs are getting gummed up with an indefinitely failing and retrying task to
re-save a prober domain that doesn't exist (likely because it was hard-deleted
by delete prober data action), so this makes the re-save action resilient to
that failure case so that it stops assuming every enqueued re-save actually
corresponds to an entity that exists, thus allowing it to fail permanently if
the entity doesn't exist.  Failing permanently is the right thing to do as if
the entity doesn't exist now there's no reason to think it will in the future,
plus all re-saves are optimistic rather than guaranteed anyway.

This should fix http://b/350530720
This commit is contained in:
Ben McIlwain
2024-07-10 15:03:42 -04:00
committed by GitHub
parent 74f0a8dd7b
commit 75f09c2fdf
2 changed files with 24 additions and 4 deletions

View File

@@ -29,6 +29,7 @@ import google.registry.request.Action.Method;
import google.registry.request.Parameter;
import google.registry.request.Response;
import google.registry.request.auth.Auth;
import java.util.Optional;
import javax.inject.Inject;
import org.joda.time.DateTime;
@@ -74,8 +75,15 @@ public class ResaveEntityAction implements Runnable {
"Re-saving entity %s which was enqueued at %s.", resourceKey, requestedTime);
tm().transact(
() -> {
EppResource entity = tm().loadByKey(VKey.createEppVKeyFromString(resourceKey));
tm().put(entity.cloneProjectedAtTime(tm().getTransactionTime()));
Optional<EppResource> entity =
tm().loadByKeyIfPresent(VKey.createEppVKeyFromString(resourceKey));
if (entity.isEmpty()) {
logger.atSevere().log(
"Could not re-save entity %s because it does not exist; failing permanently.",
resourceKey);
return;
}
tm().put(entity.get().cloneProjectedAtTime(tm().getTransactionTime()));
if (!resaveTimes.isEmpty()) {
asyncTaskEnqueuer.enqueueAsyncResave(
VKey.createEppVKeyFromString(resourceKey), requestedTime, resaveTimes);

View File

@@ -20,6 +20,7 @@ import static google.registry.batch.AsyncTaskEnqueuer.PARAM_RESOURCE_KEY;
import static google.registry.batch.AsyncTaskEnqueuer.QUEUE_ASYNC_ACTIONS;
import static google.registry.testing.DatabaseHelper.createTld;
import static google.registry.testing.DatabaseHelper.loadByEntity;
import static google.registry.testing.DatabaseHelper.newDomain;
import static google.registry.testing.DatabaseHelper.persistActiveContact;
import static google.registry.testing.DatabaseHelper.persistDomainWithDependentResources;
import static google.registry.testing.DatabaseHelper.persistDomainWithPendingTransfer;
@@ -39,7 +40,6 @@ import google.registry.persistence.transaction.JpaTestExtensions.JpaIntegrationT
import google.registry.request.Response;
import google.registry.testing.CloudTasksHelper;
import google.registry.testing.CloudTasksHelper.TaskMatcher;
import google.registry.testing.DatabaseHelper;
import google.registry.testing.FakeClock;
import org.joda.time.DateTime;
import org.junit.jupiter.api.BeforeEach;
@@ -107,7 +107,7 @@ public class ResaveEntityActionTest {
@Test
void test_domainPendingDeletion_isResavedAndReenqueued() {
Domain newDomain = DatabaseHelper.newDomain("domain.tld");
Domain newDomain = newDomain("domain.tld");
Domain domain =
persistResource(
newDomain
@@ -144,4 +144,16 @@ public class ResaveEntityActionTest {
.param(PARAM_REQUESTED_TIME, requestedTime.toString())
.scheduleTime(clock.nowUtc().plus(standardDays(5))));
}
@Test
void test_queuedTaskForNonExistentDomain_failsPermanently() {
DateTime requestedTime = clock.nowUtc();
// It should complete its run without throwing an exception (that would cause a retry) ...
runAction(
newDomain("nonexistent.tld").createVKey().stringify(),
requestedTime,
ImmutableSortedSet.of(requestedTime.plusDays(5)));
// ... and it shouldn't enqueue the subsequent re-save 5 days later.
cloudTasksHelper.assertNoTasksEnqueued(QUEUE_ASYNC_ACTIONS);
}
}