Convert ResaveEntityAction and RelockDomainAction to tm() (#1048)

In addition, we move the deleteTestDomain method to DatabaseHelper since
it'll be useful in other places (e.g. RelockDomainActionTest) and remove
the duplicate definition of ResaveEntityAction.PATH.

We also can ignore deletions of non-persisted entities in the JPA
transaction manager.
This commit is contained in:
gbrodman
2021-03-31 15:52:25 -04:00
committed by GitHub
parent c9980fcdec
commit 36762b5e08
16 changed files with 147 additions and 144 deletions
@@ -57,8 +57,6 @@ public final class AsyncTaskEnqueuer {
public static final String QUEUE_ASYNC_DELETE = "async-delete-pull";
public static final String QUEUE_ASYNC_HOST_RENAME = "async-host-rename-pull";
public static final String PATH_RESAVE_ENTITY = "/_dr/task/resaveEntity";
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
private static final Duration MAX_ASYNC_ETA = Duration.standardDays(30);
@@ -112,7 +110,7 @@ public final class AsyncTaskEnqueuer {
logger.atInfo().log("Enqueuing async re-save of %s to run at %s.", entityKey, whenToResave);
String backendHostname = appEngineServiceUtils.getServiceHostname("backend");
TaskOptions task =
TaskOptions.Builder.withUrl(PATH_RESAVE_ENTITY)
TaskOptions.Builder.withUrl(ResaveEntityAction.PATH)
.method(Method.POST)
.header("Host", backendHostname)
.countdownMillis(etaDuration.getMillis())
@@ -16,7 +16,6 @@ package google.registry.batch;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.collect.ImmutableSet.toImmutableSet;
import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import static google.registry.request.Action.Method.POST;
@@ -33,6 +32,7 @@ import google.registry.model.eppcommon.StatusValue;
import google.registry.model.registrar.Registrar;
import google.registry.model.registrar.RegistrarContact;
import google.registry.model.registry.RegistryLockDao;
import google.registry.persistence.VKey;
import google.registry.request.Action;
import google.registry.request.Parameter;
import google.registry.request.Response;
@@ -125,6 +125,7 @@ public class RelockDomainAction implements Runnable {
response.setContentType(MediaType.PLAIN_TEXT_UTF_8);
// nb: DomainLockUtils relies on the JPA transaction being the outermost transaction
// if we have Datastore as the primary DB (if SQL is the primary DB, it's irrelevant)
jpaTm().transact(() -> tm().transact(this::relockDomain));
}
@@ -139,12 +140,8 @@ public class RelockDomainAction implements Runnable {
new IllegalArgumentException(
String.format("Unknown revision ID %d", oldUnlockRevisionId)));
domain =
ofy()
.load()
.type(DomainBase.class)
.id(oldLock.getRepoId())
.now()
.cloneProjectedAtTime(jpaTm().getTransactionTime());
tm().loadByKey(VKey.create(DomainBase.class, oldLock.getRepoId()))
.cloneProjectedAtTime(tm().getTransactionTime());
} catch (Throwable t) {
handleTransientFailure(Optional.ofNullable(oldLock), t);
return;
@@ -17,7 +17,6 @@ package google.registry.batch;
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;
import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import com.google.common.collect.ImmutableSet;
@@ -26,6 +25,7 @@ import com.google.common.flogger.FluentLogger;
import com.googlecode.objectify.Key;
import google.registry.model.EppResource;
import google.registry.model.ImmutableObject;
import google.registry.persistence.VKey;
import google.registry.request.Action;
import google.registry.request.Action.Method;
import google.registry.request.Parameter;
@@ -74,16 +74,17 @@ public class ResaveEntityAction implements Runnable {
public void run() {
logger.atInfo().log(
"Re-saving entity %s which was enqueued at %s.", resourceKey, requestedTime);
tm().transact(() -> {
ImmutableObject entity = ofy().load().key(resourceKey).now();
ofy().save().entity(
(entity instanceof EppResource)
? ((EppResource) entity).cloneProjectedAtTime(tm().getTransactionTime()) : entity
);
if (!resaveTimes.isEmpty()) {
asyncTaskEnqueuer.enqueueAsyncResave(entity, requestedTime, resaveTimes);
}
});
tm().transact(
() -> {
ImmutableObject entity = tm().loadByKey(VKey.from(resourceKey));
tm().put(
(entity instanceof EppResource)
? ((EppResource) entity).cloneProjectedAtTime(tm().getTransactionTime())
: entity);
if (!resaveTimes.isEmpty()) {
asyncTaskEnqueuer.enqueueAsyncResave(entity, requestedTime, resaveTimes);
}
});
response.setPayload("Entity re-saved.");
}
}
@@ -475,6 +475,9 @@ public class JpaTransactionManagerImpl implements JpaTransactionManager {
private int internalDelete(VKey<?> key) {
checkArgumentNotNull(key, "key must be specified");
assertInTransaction();
if (IGNORED_ENTITY_CLASSES.contains(key.getKind())) {
return 0;
}
EntityType<?> entityType = getEntityType(key.getKind());
ImmutableSet<EntityId> entityIds = getEntityIdsFromSqlKey(entityType, key.getSqlKey());
// TODO(b/179158393): use Criteria for query to leave not doubt about sql injection risk.
@@ -16,7 +16,6 @@ package google.registry.tools;
import static com.google.common.base.Preconditions.checkArgument;
import static google.registry.model.EppResourceUtils.loadByForeignKeyCached;
import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import static google.registry.tools.LockOrUnlockDomainCommand.REGISTRY_LOCK_STATUSES;
@@ -29,6 +28,7 @@ import google.registry.config.RegistryConfig.Config;
import google.registry.model.billing.BillingEvent;
import google.registry.model.billing.BillingEvent.Reason;
import google.registry.model.domain.DomainBase;
import google.registry.model.domain.DomainHistory;
import google.registry.model.registry.Registry;
import google.registry.model.registry.RegistryLockDao;
import google.registry.model.reporting.HistoryEntry;
@@ -363,8 +363,8 @@ public final class DomainLockUtils {
String reason =
String.format(
"%s of a domain through a RegistryLock operation", isLock ? "Lock" : "Unlock");
HistoryEntry historyEntry =
new HistoryEntry.Builder()
DomainHistory domainHistory =
new DomainHistory.Builder()
.setClientId(domain.getCurrentSponsorClientId())
.setBySuperuser(lock.isSuperuser())
.setRequestedByRegistrar(!lock.isSuperuser())
@@ -373,7 +373,8 @@ public final class DomainLockUtils {
.setParent(Key.create(domain))
.setReason(reason)
.build();
ofy().save().entities(domain, historyEntry);
tm().update(domain);
tm().insert(domainHistory);
if (!lock.isSuperuser()) { // admin actions shouldn't affect billing
BillingEvent.OneTime oneTime =
new BillingEvent.OneTime.Builder()
@@ -383,9 +384,9 @@ public final class DomainLockUtils {
.setCost(Registry.get(domain.getTld()).getRegistryLockOrUnlockBillingCost())
.setEventTime(now)
.setBillingTime(now)
.setParent(historyEntry)
.setParent(domainHistory)
.build();
ofy().save().entity(oneTime);
tm().insert(oneTime);
}
}
}