From a68b1a12fd5bb8d9880a78fe27256e9d2558c6f0 Mon Sep 17 00:00:00 2001 From: Shicong Huang Date: Wed, 7 Aug 2019 12:59:08 -0400 Subject: [PATCH] Implement TransactionManager for datastore (#207) This PR created the new interface named TransactionManager which defines methods to manage transaction. Also, the access to all transaction related methods of Ofy.java are restricted to package private, and they will be exposed by DatastoreTransactionManager which is the datastore implementation of TransactionManager. --- .../backup/CommitLogCheckpointAction.java | 3 +- .../backup/DeleteOldCommitLogsAction.java | 3 +- .../batch/DeleteContactsAndHostsAction.java | 5 +- .../batch/DeleteLoadTestDataAction.java | 3 +- .../batch/DeleteProberDataAction.java | 9 +- .../ExpandRecurringBillingEventsAction.java | 7 +- .../batch/ResaveAllEppResourcesAction.java | 5 +- .../registry/batch/ResaveEntityAction.java | 5 +- .../export/SyncGroupMembersAction.java | 3 +- .../export/sheet/SyncRegistrarsSheet.java | 3 +- .../google/registry/flows/FlowRunner.java | 4 +- .../registry/flows/ResourceFlowUtils.java | 3 +- .../flows/contact/ContactCreateFlow.java | 3 +- .../flows/contact/ContactDeleteFlow.java | 5 +- .../contact/ContactTransferApproveFlow.java | 3 +- .../contact/ContactTransferCancelFlow.java | 3 +- .../contact/ContactTransferRejectFlow.java | 3 +- .../contact/ContactTransferRequestFlow.java | 3 +- .../flows/contact/ContactUpdateFlow.java | 3 +- .../flows/domain/DomainCreateFlow.java | 4 +- .../flows/domain/DomainDeleteFlow.java | 3 +- .../flows/domain/DomainRenewFlow.java | 4 +- .../domain/DomainRestoreRequestFlow.java | 3 +- .../domain/DomainTransferApproveFlow.java | 3 +- .../domain/DomainTransferCancelFlow.java | 3 +- .../domain/DomainTransferRejectFlow.java | 3 +- .../domain/DomainTransferRequestFlow.java | 3 +- .../flows/domain/DomainUpdateFlow.java | 4 +- .../registry/flows/host/HostCreateFlow.java | 3 +- .../registry/flows/host/HostDeleteFlow.java | 5 +- .../registry/flows/host/HostUpdateFlow.java | 5 +- .../registry/flows/poll/PollAckFlow.java | 5 +- .../registry/keyring/kms/KmsUpdater.java | 3 +- .../google/registry/model/EppResource.java | 5 +- .../registry/model/OteAccountBuilder.java | 5 +- .../model/common/GaeUserIdConverter.java | 7 +- .../registry/model/index/ForeignKeyIndex.java | 7 +- .../registry/model/ofy/CommitLoggedWork.java | 21 +++-- .../ofy/DatastoreTransactionManager.java | 86 +++++++++++++++++++ .../java/google/registry/model/ofy/Ofy.java | 32 ++++--- .../registry/model/ofy/ReadOnlyWork.java | 6 +- .../registry/model/rde/RdeRevision.java | 3 +- .../registry/model/registrar/Registrar.java | 3 +- .../model/registrar/RegistrarContact.java | 3 +- .../registry/model/registry/Registries.java | 3 +- .../registry/model/registry/Registry.java | 3 +- .../model/registry/label/PremiumList.java | 7 +- .../registry/label/PremiumListUtils.java | 13 +-- .../google/registry/model/server/Lock.java | 9 +- .../registry/model/server/ServerSecret.java | 3 +- .../model/smd/SignedMarkRevocationList.java | 5 +- .../registry/model/tmch/ClaimsListShard.java | 7 +- .../google/registry/model/tmch/TmchCrl.java | 5 +- .../model/transaction/TransactionManager.java | 84 ++++++++++++++++++ .../TransactionManagerFactory.java | 37 ++++++++ .../CommitLogRevisionsTranslatorFactory.java | 3 +- .../CreateAutoTimestampTranslatorFactory.java | 4 +- .../UpdateAutoTimestampTranslatorFactory.java | 4 +- .../UpdateRegistrarRdapBaseUrlsAction.java | 3 +- .../google/registry/rde/EscrowTaskRunner.java | 3 +- .../registry/rde/PendingDepositChecker.java | 3 +- .../registry/rde/RdeStagingReducer.java | 3 +- .../google/registry/rde/RdeUploadAction.java | 5 +- .../google/registry/tmch/LordnTaskUtils.java | 8 +- .../tools/AckPollMessagesCommand.java | 3 +- .../tools/DeleteAllocationTokensCommand.java | 3 +- .../registry/tools/DeleteTldCommand.java | 3 +- .../GenerateAllocationTokensCommand.java | 3 +- .../registry/tools/MutatingCommand.java | 3 +- .../ResaveEnvironmentEntitiesCommand.java | 3 +- .../registry/tools/UnrenewDomainCommand.java | 7 +- .../tools/UpdateAllocationTokensCommand.java | 3 +- .../tools/server/DeleteEntityAction.java | 3 +- .../tools/server/KillAllEntitiesReducer.java | 3 +- .../server/ResaveAllHistoryEntriesAction.java | 3 +- .../ConsoleRegistrarCreatorAction.java | 3 +- .../registrar/RegistrarSettingsAction.java | 7 +- .../CommitLogCheckpointStrategyTest.java | 9 +- ...xpandRecurringBillingEventsActionTest.java | 3 +- .../TestDomainCreateFlowCustomLogic.java | 4 +- .../model/CreateAutoTimestampTest.java | 7 +- .../model/UpdateAutoTimestampTest.java | 9 +- .../registry/model/common/CursorTest.java | 9 +- .../model/common/GaeUserIdConverterTest.java | 3 +- .../model/ofy/CommitLogMutationTest.java | 5 +- .../registry/model/ofy/OfyCommitLogTest.java | 61 ++++++------- .../google/registry/model/ofy/OfyTest.java | 39 +++++---- .../registry/model/rde/RdeRevisionTest.java | 17 ++-- .../model/registrar/RegistrarTest.java | 3 +- .../registry/label/PremiumListUtilsTest.java | 3 +- .../smd/SignedMarkRevocationListTest.java | 7 +- .../model/tmch/ClaimsListShardTest.java | 5 +- ...mmitLogRevisionsTranslatorFactoryTest.java | 7 +- .../rde/PendingDepositCheckerTest.java | 3 +- .../registry/rde/RdeStagingActionTest.java | 3 +- .../registry/rde/RdeUploadActionTest.java | 6 +- .../registry/testing/DatastoreHelper.java | 19 ++-- .../registry/tmch/LordnTaskUtilsTest.java | 5 +- 98 files changed, 544 insertions(+), 247 deletions(-) create mode 100644 core/src/main/java/google/registry/model/ofy/DatastoreTransactionManager.java create mode 100644 core/src/main/java/google/registry/model/transaction/TransactionManager.java create mode 100644 core/src/main/java/google/registry/model/transaction/TransactionManagerFactory.java diff --git a/core/src/main/java/google/registry/backup/CommitLogCheckpointAction.java b/core/src/main/java/google/registry/backup/CommitLogCheckpointAction.java index 7617e0343..dc9e6485f 100644 --- a/core/src/main/java/google/registry/backup/CommitLogCheckpointAction.java +++ b/core/src/main/java/google/registry/backup/CommitLogCheckpointAction.java @@ -19,6 +19,7 @@ import static com.google.appengine.api.taskqueue.TaskOptions.Builder.withUrl; import static google.registry.backup.ExportCommitLogDiffAction.LOWER_CHECKPOINT_TIME_PARAM; import static google.registry.backup.ExportCommitLogDiffAction.UPPER_CHECKPOINT_TIME_PARAM; import static google.registry.model.ofy.ObjectifyService.ofy; +import static google.registry.model.transaction.TransactionManagerFactory.tm; import static google.registry.util.DateTimeUtils.isBeforeOrAt; import com.google.common.flogger.FluentLogger; @@ -63,7 +64,7 @@ public final class CommitLogCheckpointAction implements Runnable { final CommitLogCheckpoint checkpoint = strategy.computeCheckpoint(); logger.atInfo().log( "Generated candidate checkpoint for time: %s", checkpoint.getCheckpointTime()); - ofy() + tm() .transact( () -> { DateTime lastWrittenTime = CommitLogCheckpointRoot.loadRoot().getLastWrittenTime(); diff --git a/core/src/main/java/google/registry/backup/DeleteOldCommitLogsAction.java b/core/src/main/java/google/registry/backup/DeleteOldCommitLogsAction.java index 90a551e8b..a64af7357 100644 --- a/core/src/main/java/google/registry/backup/DeleteOldCommitLogsAction.java +++ b/core/src/main/java/google/registry/backup/DeleteOldCommitLogsAction.java @@ -18,6 +18,7 @@ import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkState; import static google.registry.mapreduce.MapreduceRunner.PARAM_DRY_RUN; import static google.registry.model.ofy.ObjectifyService.ofy; +import static google.registry.model.transaction.TransactionManagerFactory.tm; import static java.lang.Boolean.FALSE; import static java.lang.Boolean.TRUE; @@ -276,7 +277,7 @@ public final class DeleteOldCommitLogsAction implements Runnable { return; } - DeletionResult deletionResult = ofy().transactNew(() -> { + DeletionResult deletionResult = tm().transactNew(() -> { CommitLogManifest manifest = ofy().load().key(manifestKey).now(); // It is possible that the same manifestKey was run twice, if a shard had to be restarted // or some weird failure. If this happens, we want to exit immediately. diff --git a/core/src/main/java/google/registry/batch/DeleteContactsAndHostsAction.java b/core/src/main/java/google/registry/batch/DeleteContactsAndHostsAction.java index bf32e8f70..579a3e0a7 100644 --- a/core/src/main/java/google/registry/batch/DeleteContactsAndHostsAction.java +++ b/core/src/main/java/google/registry/batch/DeleteContactsAndHostsAction.java @@ -39,6 +39,7 @@ import static google.registry.model.reporting.HistoryEntry.Type.CONTACT_DELETE; import static google.registry.model.reporting.HistoryEntry.Type.CONTACT_DELETE_FAILURE; import static google.registry.model.reporting.HistoryEntry.Type.HOST_DELETE; import static google.registry.model.reporting.HistoryEntry.Type.HOST_DELETE_FAILURE; +import static google.registry.model.transaction.TransactionManagerFactory.tm; import static google.registry.model.transfer.TransferStatus.SERVER_CANCELLED; import static java.math.RoundingMode.CEILING; import static java.util.concurrent.TimeUnit.DAYS; @@ -308,7 +309,7 @@ public class DeleteContactsAndHostsAction implements Runnable { final boolean hasNoActiveReferences = !Iterators.contains(values, true); logger.atInfo().log("Processing async deletion request for %s", deletionRequest.key()); DeletionResult result = - ofy() + tm() .transactNew( () -> { DeletionResult deletionResult = @@ -329,7 +330,7 @@ public class DeleteContactsAndHostsAction implements Runnable { private DeletionResult attemptToDeleteResource( DeletionRequest deletionRequest, boolean hasNoActiveReferences) { - DateTime now = ofy().getTransactionTime(); + DateTime now = tm().getTransactionTime(); EppResource resource = ofy().load().key(deletionRequest.key()).now().cloneProjectedAtTime(now); // Double-check transactionally that the resource is still active and in PENDING_DELETE. diff --git a/core/src/main/java/google/registry/batch/DeleteLoadTestDataAction.java b/core/src/main/java/google/registry/batch/DeleteLoadTestDataAction.java index 4a80ee551..b31d61966 100644 --- a/core/src/main/java/google/registry/batch/DeleteLoadTestDataAction.java +++ b/core/src/main/java/google/registry/batch/DeleteLoadTestDataAction.java @@ -19,6 +19,7 @@ import static google.registry.config.RegistryEnvironment.PRODUCTION; import static google.registry.mapreduce.MapreduceRunner.PARAM_DRY_RUN; import static google.registry.mapreduce.inputs.EppResourceInputs.createEntityInput; import static google.registry.model.ofy.ObjectifyService.ofy; +import static google.registry.model.transaction.TransactionManagerFactory.tm; import static google.registry.request.Action.Method.POST; import com.google.appengine.tools.mapreduce.Mapper; @@ -124,7 +125,7 @@ public class DeleteLoadTestDataAction implements Runnable { Key.create(EppResourceIndex.create(Key.create(resource))); final Key> fki = ForeignKeyIndex.createKey(resource); int numEntitiesDeleted = - ofy() + tm() .transact( () -> { // This ancestor query selects all descendant entities. diff --git a/core/src/main/java/google/registry/batch/DeleteProberDataAction.java b/core/src/main/java/google/registry/batch/DeleteProberDataAction.java index a0ae9cf45..c03534c00 100644 --- a/core/src/main/java/google/registry/batch/DeleteProberDataAction.java +++ b/core/src/main/java/google/registry/batch/DeleteProberDataAction.java @@ -23,6 +23,7 @@ import static google.registry.model.ResourceTransferUtils.updateForeignKeyIndexD import static google.registry.model.ofy.ObjectifyService.ofy; import static google.registry.model.registry.Registries.getTldsOfType; import static google.registry.model.reporting.HistoryEntry.Type.DOMAIN_DELETE; +import static google.registry.model.transaction.TransactionManagerFactory.tm; import static google.registry.request.Action.Method.POST; import static google.registry.request.RequestParameters.PARAM_TLDS; import static org.joda.time.DateTimeZone.UTC; @@ -219,7 +220,7 @@ public class DeleteProberDataAction implements Runnable { final Key> fki = ForeignKeyIndex.createKey(domain); int entitiesDeleted = - ofy() + tm() .transact( () -> { // This ancestor query selects all descendant HistoryEntries, BillingEvents, @@ -245,16 +246,16 @@ public class DeleteProberDataAction implements Runnable { } private void softDeleteDomain(final DomainBase domain) { - ofy().transactNew(() -> { + tm().transactNew(() -> { DomainBase deletedDomain = domain .asBuilder() - .setDeletionTime(ofy().getTransactionTime()) + .setDeletionTime(tm().getTransactionTime()) .setStatusValues(null) .build(); HistoryEntry historyEntry = new HistoryEntry.Builder() .setParent(domain) .setType(DOMAIN_DELETE) - .setModificationTime(ofy().getTransactionTime()) + .setModificationTime(tm().getTransactionTime()) .setBySuperuser(true) .setReason("Deletion of prober data") .setClientId(registryAdminClientId) diff --git a/core/src/main/java/google/registry/batch/ExpandRecurringBillingEventsAction.java b/core/src/main/java/google/registry/batch/ExpandRecurringBillingEventsAction.java index 9eee1f9f5..b18ebdcb8 100644 --- a/core/src/main/java/google/registry/batch/ExpandRecurringBillingEventsAction.java +++ b/core/src/main/java/google/registry/batch/ExpandRecurringBillingEventsAction.java @@ -23,6 +23,7 @@ import static google.registry.model.common.Cursor.CursorType.RECURRING_BILLING; import static google.registry.model.domain.Period.Unit.YEARS; import static google.registry.model.ofy.ObjectifyService.ofy; import static google.registry.model.reporting.HistoryEntry.Type.DOMAIN_AUTORENEW; +import static google.registry.model.transaction.TransactionManagerFactory.tm; import static google.registry.pricing.PricingEngineProxy.getDomainRenewCost; import static google.registry.util.CollectionUtils.union; import static google.registry.util.DateTimeUtils.START_OF_TIME; @@ -150,7 +151,7 @@ public class ExpandRecurringBillingEventsAction implements Runnable { } int numBillingEventsSaved = 0; try { - numBillingEventsSaved = ofy().transactNew(() -> { + numBillingEventsSaved = tm().transactNew(() -> { ImmutableSet.Builder syntheticOneTimesBuilder = new ImmutableSet.Builder<>(); final Registry tld = Registry.get(getTldFromDomainName(recurring.getTargetId())); @@ -183,7 +184,7 @@ public class ExpandRecurringBillingEventsAction implements Runnable { HistoryEntry historyEntry = new HistoryEntry.Builder() .setBySuperuser(false) .setClientId(recurring.getClientId()) - .setModificationTime(ofy().getTransactionTime()) + .setModificationTime(tm().getTransactionTime()) .setParent(domainKey) .setPeriod(Period.create(1, YEARS)) .setReason("Domain autorenewal by ExpandRecurringBillingEventsAction") @@ -308,7 +309,7 @@ public class ExpandRecurringBillingEventsAction implements Runnable { logger.atInfo().log( "Recurring event expansion %s complete for billing event range [%s, %s).", isDryRun ? "(dry run) " : "", cursorTime, executionTime); - ofy() + tm() .transact( () -> { Cursor cursor = ofy().load().key(Cursor.createGlobalKey(RECURRING_BILLING)).now(); diff --git a/core/src/main/java/google/registry/batch/ResaveAllEppResourcesAction.java b/core/src/main/java/google/registry/batch/ResaveAllEppResourcesAction.java index efa3f3d3f..3b8689817 100644 --- a/core/src/main/java/google/registry/batch/ResaveAllEppResourcesAction.java +++ b/core/src/main/java/google/registry/batch/ResaveAllEppResourcesAction.java @@ -15,6 +15,7 @@ package google.registry.batch; import static google.registry.model.ofy.ObjectifyService.ofy; +import static google.registry.model.transaction.TransactionManagerFactory.tm; import com.google.appengine.tools.mapreduce.Mapper; import com.google.common.collect.ImmutableList; @@ -69,7 +70,7 @@ public class ResaveAllEppResourcesAction implements Runnable { @Override public final void map(final Key resourceKey) { - ofy() + tm() .transact( () -> { EppResource projectedResource = @@ -77,7 +78,7 @@ public class ResaveAllEppResourcesAction implements Runnable { .load() .key(resourceKey) .now() - .cloneProjectedAtTime(ofy().getTransactionTime()); + .cloneProjectedAtTime(tm().getTransactionTime()); ofy().save().entity(projectedResource).now(); }); getContext().incrementCounter(String.format("%s entities re-saved", resourceKey.getKind())); diff --git a/core/src/main/java/google/registry/batch/ResaveEntityAction.java b/core/src/main/java/google/registry/batch/ResaveEntityAction.java index 799ef5b25..e31a91f45 100644 --- a/core/src/main/java/google/registry/batch/ResaveEntityAction.java +++ b/core/src/main/java/google/registry/batch/ResaveEntityAction.java @@ -18,6 +18,7 @@ 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.model.transaction.TransactionManagerFactory.tm; import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSortedSet; @@ -73,11 +74,11 @@ public class ResaveEntityAction implements Runnable { public void run() { logger.atInfo().log( "Re-saving entity %s which was enqueued at %s.", resourceKey, requestedTime); - ofy().transact(() -> { + tm().transact(() -> { ImmutableObject entity = ofy().load().key(resourceKey).now(); ofy().save().entity( (entity instanceof EppResource) - ? ((EppResource) entity).cloneProjectedAtTime(ofy().getTransactionTime()) : entity + ? ((EppResource) entity).cloneProjectedAtTime(tm().getTransactionTime()) : entity ); if (!resaveTimes.isEmpty()) { asyncTaskEnqueuer.enqueueAsyncResave(entity, requestedTime, resaveTimes); diff --git a/core/src/main/java/google/registry/export/SyncGroupMembersAction.java b/core/src/main/java/google/registry/export/SyncGroupMembersAction.java index ffa1a064c..5c81470e5 100644 --- a/core/src/main/java/google/registry/export/SyncGroupMembersAction.java +++ b/core/src/main/java/google/registry/export/SyncGroupMembersAction.java @@ -17,6 +17,7 @@ package google.registry.export; import static com.google.common.collect.ImmutableList.toImmutableList; import static com.google.common.collect.ImmutableSet.toImmutableSet; import static google.registry.model.ofy.ObjectifyService.ofy; +import static google.registry.model.transaction.TransactionManagerFactory.tm; import static google.registry.request.Action.Method.POST; import static google.registry.util.CollectionUtils.nullToEmpty; import static google.registry.util.RegistrarUtils.normalizeClientId; @@ -163,7 +164,7 @@ public final class SyncGroupMembersAction implements Runnable { registrarsToSave.add(result.getKey().asBuilder().setContactsRequireSyncing(false).build()); } } - ofy().transactNew(() -> ofy().save().entities(registrarsToSave.build())); + tm().transactNew(() -> ofy().save().entities(registrarsToSave.build())); return errors; } diff --git a/core/src/main/java/google/registry/export/sheet/SyncRegistrarsSheet.java b/core/src/main/java/google/registry/export/sheet/SyncRegistrarsSheet.java index 92d1ae1fd..f81fa37a0 100644 --- a/core/src/main/java/google/registry/export/sheet/SyncRegistrarsSheet.java +++ b/core/src/main/java/google/registry/export/sheet/SyncRegistrarsSheet.java @@ -25,6 +25,7 @@ import static google.registry.model.registrar.RegistrarContact.Type.LEGAL; import static google.registry.model.registrar.RegistrarContact.Type.MARKETING; import static google.registry.model.registrar.RegistrarContact.Type.TECH; import static google.registry.model.registrar.RegistrarContact.Type.WHOIS; +import static google.registry.model.transaction.TransactionManagerFactory.tm; import static google.registry.util.DateTimeUtils.START_OF_TIME; import com.google.common.base.Joiner; @@ -152,7 +153,7 @@ class SyncRegistrarsSheet { return builder.build(); }) .collect(toImmutableList())); - ofy() + tm() .transact( () -> ofy().save().entity(Cursor.createGlobal(SYNC_REGISTRAR_SHEET, executionTime))); } diff --git a/core/src/main/java/google/registry/flows/FlowRunner.java b/core/src/main/java/google/registry/flows/FlowRunner.java index 8df7f0083..4e130e387 100644 --- a/core/src/main/java/google/registry/flows/FlowRunner.java +++ b/core/src/main/java/google/registry/flows/FlowRunner.java @@ -14,7 +14,7 @@ package google.registry.flows; -import static google.registry.model.ofy.ObjectifyService.ofy; +import static google.registry.model.transaction.TransactionManagerFactory.tm; import static google.registry.xml.XmlTransformer.prettyPrint; import com.google.common.base.Strings; @@ -80,7 +80,7 @@ public class FlowRunner { return eppOutput; } try { - return ofy() + return tm() .transact( () -> { try { diff --git a/core/src/main/java/google/registry/flows/ResourceFlowUtils.java b/core/src/main/java/google/registry/flows/ResourceFlowUtils.java index 9118f41da..d9549ddb2 100644 --- a/core/src/main/java/google/registry/flows/ResourceFlowUtils.java +++ b/core/src/main/java/google/registry/flows/ResourceFlowUtils.java @@ -19,6 +19,7 @@ import static google.registry.model.EppResourceUtils.loadByForeignKey; import static google.registry.model.EppResourceUtils.queryForLinkedDomains; import static google.registry.model.index.ForeignKeyIndex.loadAndGetKey; import static google.registry.model.ofy.ObjectifyService.ofy; +import static google.registry.model.transaction.TransactionManagerFactory.tm; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Sets; @@ -77,7 +78,7 @@ public final class ResourceFlowUtils { final Function> getPotentialReferences) throws EppException { // Enter a transactionless context briefly. EppException failfastException = - ofy() + tm() .doTransactionless( () -> { final ForeignKeyIndex fki = diff --git a/core/src/main/java/google/registry/flows/contact/ContactCreateFlow.java b/core/src/main/java/google/registry/flows/contact/ContactCreateFlow.java index 08b4754de..be4471b7d 100644 --- a/core/src/main/java/google/registry/flows/contact/ContactCreateFlow.java +++ b/core/src/main/java/google/registry/flows/contact/ContactCreateFlow.java @@ -20,6 +20,7 @@ import static google.registry.flows.contact.ContactFlowUtils.validateAsciiPostal import static google.registry.flows.contact.ContactFlowUtils.validateContactAgainstPolicy; import static google.registry.model.EppResourceUtils.createRepoId; import static google.registry.model.ofy.ObjectifyService.ofy; +import static google.registry.model.transaction.TransactionManagerFactory.tm; import com.googlecode.objectify.Key; import google.registry.config.RegistryConfig.Config; @@ -71,7 +72,7 @@ public final class ContactCreateFlow implements TransactionalFlow { extensionManager.validate(); validateClientIsLoggedIn(clientId); Create command = (Create) resourceCommand; - DateTime now = ofy().getTransactionTime(); + DateTime now = tm().getTransactionTime(); verifyResourceDoesNotExist(ContactResource.class, targetId, now, clientId); ContactResource newContact = new ContactResource.Builder() diff --git a/core/src/main/java/google/registry/flows/contact/ContactDeleteFlow.java b/core/src/main/java/google/registry/flows/contact/ContactDeleteFlow.java index 10fb6897a..41742d205 100644 --- a/core/src/main/java/google/registry/flows/contact/ContactDeleteFlow.java +++ b/core/src/main/java/google/registry/flows/contact/ContactDeleteFlow.java @@ -22,6 +22,7 @@ import static google.registry.flows.ResourceFlowUtils.verifyOptionalAuthInfo; import static google.registry.flows.ResourceFlowUtils.verifyResourceOwnership; import static google.registry.model.eppoutput.Result.Code.SUCCESS_WITH_ACTION_PENDING; import static google.registry.model.ofy.ObjectifyService.ofy; +import static google.registry.model.transaction.TransactionManagerFactory.tm; import com.google.common.collect.ImmutableSet; import com.googlecode.objectify.Key; @@ -84,7 +85,7 @@ public final class ContactDeleteFlow implements TransactionalFlow { extensionManager.register(MetadataExtension.class); extensionManager.validate(); validateClientIsLoggedIn(clientId); - DateTime now = ofy().getTransactionTime(); + DateTime now = tm().getTransactionTime(); failfastForAsyncDelete(targetId, now, ContactResource.class, DomainBase::getReferencedContacts); ContactResource existingContact = loadAndVerifyExistence(ContactResource.class, targetId, now); verifyNoDisallowedStatuses(existingContact, DISALLOWED_STATUSES); @@ -93,7 +94,7 @@ public final class ContactDeleteFlow implements TransactionalFlow { verifyResourceOwnership(clientId, existingContact); } asyncTaskEnqueuer.enqueueAsyncDelete( - existingContact, ofy().getTransactionTime(), clientId, trid, isSuperuser); + existingContact, tm().getTransactionTime(), clientId, trid, isSuperuser); ContactResource newContact = existingContact.asBuilder().addStatusValue(StatusValue.PENDING_DELETE).build(); historyBuilder diff --git a/core/src/main/java/google/registry/flows/contact/ContactTransferApproveFlow.java b/core/src/main/java/google/registry/flows/contact/ContactTransferApproveFlow.java index 4c0f8136c..87b9b4880 100644 --- a/core/src/main/java/google/registry/flows/contact/ContactTransferApproveFlow.java +++ b/core/src/main/java/google/registry/flows/contact/ContactTransferApproveFlow.java @@ -23,6 +23,7 @@ import static google.registry.flows.contact.ContactFlowUtils.createGainingTransf import static google.registry.flows.contact.ContactFlowUtils.createTransferResponse; import static google.registry.model.ResourceTransferUtils.approvePendingTransfer; import static google.registry.model.ofy.ObjectifyService.ofy; +import static google.registry.model.transaction.TransactionManagerFactory.tm; import com.googlecode.objectify.Key; import google.registry.flows.EppException; @@ -78,7 +79,7 @@ public final class ContactTransferApproveFlow implements TransactionalFlow { extensionManager.register(MetadataExtension.class); extensionManager.validate(); validateClientIsLoggedIn(clientId); - DateTime now = ofy().getTransactionTime(); + DateTime now = tm().getTransactionTime(); ContactResource existingContact = loadAndVerifyExistence(ContactResource.class, targetId, now); verifyOptionalAuthInfo(authInfo, existingContact); verifyHasPendingTransfer(existingContact); diff --git a/core/src/main/java/google/registry/flows/contact/ContactTransferCancelFlow.java b/core/src/main/java/google/registry/flows/contact/ContactTransferCancelFlow.java index ceb3c4a17..aae58f227 100644 --- a/core/src/main/java/google/registry/flows/contact/ContactTransferCancelFlow.java +++ b/core/src/main/java/google/registry/flows/contact/ContactTransferCancelFlow.java @@ -23,6 +23,7 @@ import static google.registry.flows.contact.ContactFlowUtils.createLosingTransfe import static google.registry.flows.contact.ContactFlowUtils.createTransferResponse; import static google.registry.model.ResourceTransferUtils.denyPendingTransfer; import static google.registry.model.ofy.ObjectifyService.ofy; +import static google.registry.model.transaction.TransactionManagerFactory.tm; import com.googlecode.objectify.Key; import google.registry.flows.EppException; @@ -74,7 +75,7 @@ public final class ContactTransferCancelFlow implements TransactionalFlow { extensionManager.register(MetadataExtension.class); extensionManager.validate(); validateClientIsLoggedIn(clientId); - DateTime now = ofy().getTransactionTime(); + DateTime now = tm().getTransactionTime(); ContactResource existingContact = loadAndVerifyExistence(ContactResource.class, targetId, now); verifyOptionalAuthInfo(authInfo, existingContact); verifyHasPendingTransfer(existingContact); diff --git a/core/src/main/java/google/registry/flows/contact/ContactTransferRejectFlow.java b/core/src/main/java/google/registry/flows/contact/ContactTransferRejectFlow.java index a0e503dda..e744d3fd3 100644 --- a/core/src/main/java/google/registry/flows/contact/ContactTransferRejectFlow.java +++ b/core/src/main/java/google/registry/flows/contact/ContactTransferRejectFlow.java @@ -23,6 +23,7 @@ import static google.registry.flows.contact.ContactFlowUtils.createGainingTransf import static google.registry.flows.contact.ContactFlowUtils.createTransferResponse; import static google.registry.model.ResourceTransferUtils.denyPendingTransfer; import static google.registry.model.ofy.ObjectifyService.ofy; +import static google.registry.model.transaction.TransactionManagerFactory.tm; import com.googlecode.objectify.Key; import google.registry.flows.EppException; @@ -72,7 +73,7 @@ public final class ContactTransferRejectFlow implements TransactionalFlow { extensionManager.register(MetadataExtension.class); extensionManager.validate(); validateClientIsLoggedIn(clientId); - DateTime now = ofy().getTransactionTime(); + DateTime now = tm().getTransactionTime(); ContactResource existingContact = loadAndVerifyExistence(ContactResource.class, targetId, now); verifyOptionalAuthInfo(authInfo, existingContact); verifyHasPendingTransfer(existingContact); diff --git a/core/src/main/java/google/registry/flows/contact/ContactTransferRequestFlow.java b/core/src/main/java/google/registry/flows/contact/ContactTransferRequestFlow.java index 2adadcb93..12d911fd7 100644 --- a/core/src/main/java/google/registry/flows/contact/ContactTransferRequestFlow.java +++ b/core/src/main/java/google/registry/flows/contact/ContactTransferRequestFlow.java @@ -24,6 +24,7 @@ import static google.registry.flows.contact.ContactFlowUtils.createLosingTransfe import static google.registry.flows.contact.ContactFlowUtils.createTransferResponse; import static google.registry.model.eppoutput.Result.Code.SUCCESS_WITH_ACTION_PENDING; import static google.registry.model.ofy.ObjectifyService.ofy; +import static google.registry.model.transaction.TransactionManagerFactory.tm; import com.google.common.collect.ImmutableSet; import com.googlecode.objectify.Key; @@ -91,7 +92,7 @@ public final class ContactTransferRequestFlow implements TransactionalFlow { extensionManager.register(MetadataExtension.class); extensionManager.validate(); validateClientIsLoggedIn(gainingClientId); - DateTime now = ofy().getTransactionTime(); + DateTime now = tm().getTransactionTime(); ContactResource existingContact = loadAndVerifyExistence(ContactResource.class, targetId, now); verifyAuthInfoPresentForResourceTransfer(authInfo); verifyAuthInfo(authInfo.get(), existingContact); diff --git a/core/src/main/java/google/registry/flows/contact/ContactUpdateFlow.java b/core/src/main/java/google/registry/flows/contact/ContactUpdateFlow.java index 34cb11733..e53c63fd7 100644 --- a/core/src/main/java/google/registry/flows/contact/ContactUpdateFlow.java +++ b/core/src/main/java/google/registry/flows/contact/ContactUpdateFlow.java @@ -25,6 +25,7 @@ import static google.registry.flows.ResourceFlowUtils.verifyResourceOwnership; import static google.registry.flows.contact.ContactFlowUtils.validateAsciiPostalInfo; import static google.registry.flows.contact.ContactFlowUtils.validateContactAgainstPolicy; import static google.registry.model.ofy.ObjectifyService.ofy; +import static google.registry.model.transaction.TransactionManagerFactory.tm; import com.google.common.collect.ImmutableSet; import com.googlecode.objectify.Key; @@ -92,7 +93,7 @@ public final class ContactUpdateFlow implements TransactionalFlow { extensionManager.validate(); validateClientIsLoggedIn(clientId); Update command = (Update) resourceCommand; - DateTime now = ofy().getTransactionTime(); + DateTime now = tm().getTransactionTime(); ContactResource existingContact = loadAndVerifyExistence(ContactResource.class, targetId, now); verifyOptionalAuthInfo(authInfo, existingContact); ImmutableSet statusToRemove = command.getInnerRemove().getStatusValues(); diff --git a/core/src/main/java/google/registry/flows/domain/DomainCreateFlow.java b/core/src/main/java/google/registry/flows/domain/DomainCreateFlow.java index f415a27a9..680480660 100644 --- a/core/src/main/java/google/registry/flows/domain/DomainCreateFlow.java +++ b/core/src/main/java/google/registry/flows/domain/DomainCreateFlow.java @@ -42,11 +42,11 @@ import static google.registry.flows.domain.DomainFlowUtils.verifyRegistrarIsActi import static google.registry.flows.domain.DomainFlowUtils.verifyUnitIsYears; import static google.registry.model.EppResourceUtils.createDomainRepoId; import static google.registry.model.eppcommon.StatusValue.SERVER_HOLD; -import static google.registry.model.ofy.ObjectifyService.ofy; import static google.registry.model.registry.Registry.TldState.GENERAL_AVAILABILITY; import static google.registry.model.registry.Registry.TldState.QUIET_PERIOD; import static google.registry.model.registry.Registry.TldState.START_DATE_SUNRISE; import static google.registry.model.registry.label.ReservationType.NAME_COLLISION; +import static google.registry.model.transaction.TransactionManagerFactory.tm; import static google.registry.util.DateTimeUtils.END_OF_TIME; import static google.registry.util.DateTimeUtils.leapSafeAddYears; @@ -221,7 +221,7 @@ public class DomainCreateFlow implements TransactionalFlow { extensionManager.validate(); validateClientIsLoggedIn(clientId); verifyRegistrarIsActive(clientId); - DateTime now = ofy().getTransactionTime(); + DateTime now = tm().getTransactionTime(); DomainCommand.Create command = cloneAndLinkReferences((Create) resourceCommand, now); Period period = command.getPeriod(); verifyUnitIsYears(period); 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 ee0989e8d..4ab308588 100644 --- a/core/src/main/java/google/registry/flows/domain/DomainDeleteFlow.java +++ b/core/src/main/java/google/registry/flows/domain/DomainDeleteFlow.java @@ -34,6 +34,7 @@ import static google.registry.model.eppoutput.Result.Code.SUCCESS_WITH_ACTION_PE import static google.registry.model.ofy.ObjectifyService.ofy; import static google.registry.model.reporting.DomainTransactionRecord.TransactionReportField.ADD_FIELDS; import static google.registry.model.reporting.DomainTransactionRecord.TransactionReportField.RENEW_FIELDS; +import static google.registry.model.transaction.TransactionManagerFactory.tm; import static google.registry.pricing.PricingEngineProxy.getDomainRenewCost; import static google.registry.util.CollectionUtils.nullToEmpty; import static google.registry.util.CollectionUtils.union; @@ -140,7 +141,7 @@ public final class DomainDeleteFlow implements TransactionalFlow { flowCustomLogic.beforeValidation(); extensionManager.validate(); validateClientIsLoggedIn(clientId); - DateTime now = ofy().getTransactionTime(); + DateTime now = tm().getTransactionTime(); // Loads the target resource if it exists DomainBase existingDomain = loadAndVerifyExistence(DomainBase.class, targetId, now); Registry registry = Registry.get(existingDomain.getTld()); diff --git a/core/src/main/java/google/registry/flows/domain/DomainRenewFlow.java b/core/src/main/java/google/registry/flows/domain/DomainRenewFlow.java index ffb580d93..b755c51c4 100644 --- a/core/src/main/java/google/registry/flows/domain/DomainRenewFlow.java +++ b/core/src/main/java/google/registry/flows/domain/DomainRenewFlow.java @@ -28,7 +28,7 @@ import static google.registry.flows.domain.DomainFlowUtils.validateFeeChallenge; import static google.registry.flows.domain.DomainFlowUtils.validateRegistrationPeriod; import static google.registry.flows.domain.DomainFlowUtils.verifyRegistrarIsActive; import static google.registry.flows.domain.DomainFlowUtils.verifyUnitIsYears; -import static google.registry.model.ofy.ObjectifyService.ofy; +import static google.registry.model.transaction.TransactionManagerFactory.tm; import static google.registry.util.DateTimeUtils.leapSafeAddYears; import com.google.common.collect.ImmutableList; @@ -137,7 +137,7 @@ public final class DomainRenewFlow implements TransactionalFlow { extensionManager.validate(); validateClientIsLoggedIn(clientId); verifyRegistrarIsActive(clientId); - DateTime now = ofy().getTransactionTime(); + DateTime now = tm().getTransactionTime(); Renew command = (Renew) resourceCommand; // Loads the target resource if it exists DomainBase existingDomain = loadAndVerifyExistence(DomainBase.class, targetId, now); diff --git a/core/src/main/java/google/registry/flows/domain/DomainRestoreRequestFlow.java b/core/src/main/java/google/registry/flows/domain/DomainRestoreRequestFlow.java index d2e4e951d..32577ebd6 100644 --- a/core/src/main/java/google/registry/flows/domain/DomainRestoreRequestFlow.java +++ b/core/src/main/java/google/registry/flows/domain/DomainRestoreRequestFlow.java @@ -27,6 +27,7 @@ import static google.registry.flows.domain.DomainFlowUtils.verifyPremiumNameIsNo import static google.registry.flows.domain.DomainFlowUtils.verifyRegistrarIsActive; import static google.registry.model.ResourceTransferUtils.updateForeignKeyIndexDeletionTime; import static google.registry.model.ofy.ObjectifyService.ofy; +import static google.registry.model.transaction.TransactionManagerFactory.tm; import static google.registry.util.DateTimeUtils.END_OF_TIME; import com.google.common.collect.ImmutableList; @@ -133,7 +134,7 @@ public final class DomainRestoreRequestFlow implements TransactionalFlow { validateClientIsLoggedIn(clientId); verifyRegistrarIsActive(clientId); Update command = (Update) resourceCommand; - DateTime now = ofy().getTransactionTime(); + DateTime now = tm().getTransactionTime(); DomainBase existingDomain = loadAndVerifyExistence(DomainBase.class, targetId, now); FeesAndCredits feesAndCredits = pricingLogic.getRestorePrice(Registry.get(existingDomain.getTld()), targetId, now); diff --git a/core/src/main/java/google/registry/flows/domain/DomainTransferApproveFlow.java b/core/src/main/java/google/registry/flows/domain/DomainTransferApproveFlow.java index d8881ae52..ae14b7f61 100644 --- a/core/src/main/java/google/registry/flows/domain/DomainTransferApproveFlow.java +++ b/core/src/main/java/google/registry/flows/domain/DomainTransferApproveFlow.java @@ -29,6 +29,7 @@ import static google.registry.model.ResourceTransferUtils.approvePendingTransfer import static google.registry.model.domain.DomainBase.extendRegistrationWithCap; import static google.registry.model.ofy.ObjectifyService.ofy; import static google.registry.model.reporting.DomainTransactionRecord.TransactionReportField.TRANSFER_SUCCESSFUL; +import static google.registry.model.transaction.TransactionManagerFactory.tm; import static google.registry.pricing.PricingEngineProxy.getDomainRenewCost; import static google.registry.util.CollectionUtils.union; import static google.registry.util.DateTimeUtils.END_OF_TIME; @@ -102,7 +103,7 @@ public final class DomainTransferApproveFlow implements TransactionalFlow { extensionManager.register(MetadataExtension.class); extensionManager.validate(); validateClientIsLoggedIn(clientId); - DateTime now = ofy().getTransactionTime(); + DateTime now = tm().getTransactionTime(); DomainBase existingDomain = loadAndVerifyExistence(DomainBase.class, targetId, now); verifyOptionalAuthInfo(authInfo, existingDomain); verifyHasPendingTransfer(existingDomain); diff --git a/core/src/main/java/google/registry/flows/domain/DomainTransferCancelFlow.java b/core/src/main/java/google/registry/flows/domain/DomainTransferCancelFlow.java index 7251180cb..57ddc1f87 100644 --- a/core/src/main/java/google/registry/flows/domain/DomainTransferCancelFlow.java +++ b/core/src/main/java/google/registry/flows/domain/DomainTransferCancelFlow.java @@ -27,6 +27,7 @@ import static google.registry.flows.domain.DomainTransferUtils.createTransferRes import static google.registry.model.ResourceTransferUtils.denyPendingTransfer; import static google.registry.model.ofy.ObjectifyService.ofy; import static google.registry.model.reporting.DomainTransactionRecord.TransactionReportField.TRANSFER_SUCCESSFUL; +import static google.registry.model.transaction.TransactionManagerFactory.tm; import static google.registry.util.DateTimeUtils.END_OF_TIME; import com.google.common.collect.ImmutableSet; @@ -87,7 +88,7 @@ public final class DomainTransferCancelFlow implements TransactionalFlow { extensionManager.register(MetadataExtension.class); extensionManager.validate(); validateClientIsLoggedIn(clientId); - DateTime now = ofy().getTransactionTime(); + DateTime now = tm().getTransactionTime(); DomainBase existingDomain = loadAndVerifyExistence(DomainBase.class, targetId, now); verifyOptionalAuthInfo(authInfo, existingDomain); verifyHasPendingTransfer(existingDomain); diff --git a/core/src/main/java/google/registry/flows/domain/DomainTransferRejectFlow.java b/core/src/main/java/google/registry/flows/domain/DomainTransferRejectFlow.java index 4b01ab1b9..5a47ae27d 100644 --- a/core/src/main/java/google/registry/flows/domain/DomainTransferRejectFlow.java +++ b/core/src/main/java/google/registry/flows/domain/DomainTransferRejectFlow.java @@ -28,6 +28,7 @@ import static google.registry.model.ResourceTransferUtils.denyPendingTransfer; import static google.registry.model.ofy.ObjectifyService.ofy; import static google.registry.model.reporting.DomainTransactionRecord.TransactionReportField.TRANSFER_NACKED; import static google.registry.model.reporting.DomainTransactionRecord.TransactionReportField.TRANSFER_SUCCESSFUL; +import static google.registry.model.transaction.TransactionManagerFactory.tm; import static google.registry.util.CollectionUtils.union; import static google.registry.util.DateTimeUtils.END_OF_TIME; @@ -89,7 +90,7 @@ public final class DomainTransferRejectFlow implements TransactionalFlow { extensionManager.register(MetadataExtension.class); extensionManager.validate(); validateClientIsLoggedIn(clientId); - DateTime now = ofy().getTransactionTime(); + DateTime now = tm().getTransactionTime(); DomainBase existingDomain = loadAndVerifyExistence(DomainBase.class, targetId, now); Registry registry = Registry.get(existingDomain.getTld()); HistoryEntry historyEntry = buildHistoryEntry(existingDomain, registry, now); diff --git a/core/src/main/java/google/registry/flows/domain/DomainTransferRequestFlow.java b/core/src/main/java/google/registry/flows/domain/DomainTransferRequestFlow.java index 3c728bd2e..83613dc35 100644 --- a/core/src/main/java/google/registry/flows/domain/DomainTransferRequestFlow.java +++ b/core/src/main/java/google/registry/flows/domain/DomainTransferRequestFlow.java @@ -32,6 +32,7 @@ import static google.registry.flows.domain.DomainTransferUtils.createTransferSer import static google.registry.model.domain.DomainBase.extendRegistrationWithCap; import static google.registry.model.eppoutput.Result.Code.SUCCESS_WITH_ACTION_PENDING; import static google.registry.model.ofy.ObjectifyService.ofy; +import static google.registry.model.transaction.TransactionManagerFactory.tm; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; @@ -143,7 +144,7 @@ public final class DomainTransferRequestFlow implements TransactionalFlow { extensionManager.validate(); validateClientIsLoggedIn(gainingClientId); verifyRegistrarIsActive(gainingClientId); - DateTime now = ofy().getTransactionTime(); + DateTime now = tm().getTransactionTime(); DomainBase existingDomain = loadAndVerifyExistence(DomainBase.class, targetId, now); Optional superuserExtension = eppInput.getSingleExtension(DomainTransferRequestSuperuserExtension.class); diff --git a/core/src/main/java/google/registry/flows/domain/DomainUpdateFlow.java b/core/src/main/java/google/registry/flows/domain/DomainUpdateFlow.java index d969e11e2..0e877e314 100644 --- a/core/src/main/java/google/registry/flows/domain/DomainUpdateFlow.java +++ b/core/src/main/java/google/registry/flows/domain/DomainUpdateFlow.java @@ -38,7 +38,7 @@ import static google.registry.flows.domain.DomainFlowUtils.validateRegistrantAll import static google.registry.flows.domain.DomainFlowUtils.validateRequiredContactsPresent; import static google.registry.flows.domain.DomainFlowUtils.verifyClientUpdateNotProhibited; import static google.registry.flows.domain.DomainFlowUtils.verifyNotInPendingDelete; -import static google.registry.model.ofy.ObjectifyService.ofy; +import static google.registry.model.transaction.TransactionManagerFactory.tm; import com.google.common.collect.ImmutableSet; import com.google.common.net.InternetDomainName; @@ -154,7 +154,7 @@ public final class DomainUpdateFlow implements TransactionalFlow { flowCustomLogic.beforeValidation(); extensionManager.validate(); validateClientIsLoggedIn(clientId); - DateTime now = ofy().getTransactionTime(); + DateTime now = tm().getTransactionTime(); Update command = cloneAndLinkReferences((Update) resourceCommand, now); DomainBase existingDomain = loadAndVerifyExistence(DomainBase.class, targetId, now); verifyUpdateAllowed(command, existingDomain, now); diff --git a/core/src/main/java/google/registry/flows/host/HostCreateFlow.java b/core/src/main/java/google/registry/flows/host/HostCreateFlow.java index ec6078c09..4ef0306e3 100644 --- a/core/src/main/java/google/registry/flows/host/HostCreateFlow.java +++ b/core/src/main/java/google/registry/flows/host/HostCreateFlow.java @@ -22,6 +22,7 @@ import static google.registry.flows.host.HostFlowUtils.verifySuperordinateDomain import static google.registry.flows.host.HostFlowUtils.verifySuperordinateDomainOwnership; import static google.registry.model.EppResourceUtils.createRepoId; import static google.registry.model.ofy.ObjectifyService.ofy; +import static google.registry.model.transaction.TransactionManagerFactory.tm; import static google.registry.util.CollectionUtils.isNullOrEmpty; import static google.registry.util.CollectionUtils.union; @@ -103,7 +104,7 @@ public final class HostCreateFlow implements TransactionalFlow { extensionManager.validate(); validateClientIsLoggedIn(clientId); Create command = (Create) resourceCommand; - DateTime now = ofy().getTransactionTime(); + DateTime now = tm().getTransactionTime(); verifyResourceDoesNotExist(HostResource.class, targetId, now, clientId); // The superordinate domain of the host object if creating an in-bailiwick host, or null if // creating an external host. This is looked up before we actually create the Host object so diff --git a/core/src/main/java/google/registry/flows/host/HostDeleteFlow.java b/core/src/main/java/google/registry/flows/host/HostDeleteFlow.java index fc395d734..2b6c0bf2e 100644 --- a/core/src/main/java/google/registry/flows/host/HostDeleteFlow.java +++ b/core/src/main/java/google/registry/flows/host/HostDeleteFlow.java @@ -22,6 +22,7 @@ import static google.registry.flows.ResourceFlowUtils.verifyResourceOwnership; import static google.registry.flows.host.HostFlowUtils.validateHostName; import static google.registry.model.eppoutput.Result.Code.SUCCESS_WITH_ACTION_PENDING; import static google.registry.model.ofy.ObjectifyService.ofy; +import static google.registry.model.transaction.TransactionManagerFactory.tm; import com.google.common.collect.ImmutableSet; import com.googlecode.objectify.Key; @@ -85,7 +86,7 @@ public final class HostDeleteFlow implements TransactionalFlow { extensionManager.register(MetadataExtension.class); extensionManager.validate(); validateClientIsLoggedIn(clientId); - DateTime now = ofy().getTransactionTime(); + DateTime now = tm().getTransactionTime(); validateHostName(targetId); failfastForAsyncDelete(targetId, now, HostResource.class, DomainBase::getNameservers); HostResource existingHost = loadAndVerifyExistence(HostResource.class, targetId, now); @@ -101,7 +102,7 @@ public final class HostDeleteFlow implements TransactionalFlow { verifyResourceOwnership(clientId, owningResource); } asyncTaskEnqueuer.enqueueAsyncDelete( - existingHost, ofy().getTransactionTime(), clientId, trid, isSuperuser); + existingHost, tm().getTransactionTime(), clientId, trid, isSuperuser); HostResource newHost = existingHost.asBuilder().addStatusValue(StatusValue.PENDING_DELETE).build(); historyBuilder diff --git a/core/src/main/java/google/registry/flows/host/HostUpdateFlow.java b/core/src/main/java/google/registry/flows/host/HostUpdateFlow.java index 72a4493ec..fdbb96cf8 100644 --- a/core/src/main/java/google/registry/flows/host/HostUpdateFlow.java +++ b/core/src/main/java/google/registry/flows/host/HostUpdateFlow.java @@ -28,6 +28,7 @@ import static google.registry.flows.host.HostFlowUtils.verifySuperordinateDomain import static google.registry.flows.host.HostFlowUtils.verifySuperordinateDomainOwnership; import static google.registry.model.index.ForeignKeyIndex.loadAndGetKey; import static google.registry.model.ofy.ObjectifyService.ofy; +import static google.registry.model.transaction.TransactionManagerFactory.tm; import static google.registry.util.CollectionUtils.isNullOrEmpty; import com.google.common.collect.ImmutableSet; @@ -129,7 +130,7 @@ public final class HostUpdateFlow implements TransactionalFlow { Update command = (Update) resourceCommand; Change change = command.getInnerChange(); String suppliedNewHostName = change.getFullyQualifiedHostName(); - DateTime now = ofy().getTransactionTime(); + DateTime now = tm().getTransactionTime(); validateHostName(targetId); HostResource existingHost = loadAndVerifyExistence(HostResource.class, targetId, now); boolean isHostRename = suppliedNewHostName != null; @@ -271,7 +272,7 @@ public final class HostUpdateFlow implements TransactionalFlow { } // We must also enqueue updates for all domains that use this host as their nameserver so // that their NS records can be updated to point at the new name. - asyncTaskEnqueuer.enqueueAsyncDnsRefresh(existingHost, ofy().getTransactionTime()); + asyncTaskEnqueuer.enqueueAsyncDnsRefresh(existingHost, tm().getTransactionTime()); } } diff --git a/core/src/main/java/google/registry/flows/poll/PollAckFlow.java b/core/src/main/java/google/registry/flows/poll/PollAckFlow.java index 008629bd8..b98bdf77d 100644 --- a/core/src/main/java/google/registry/flows/poll/PollAckFlow.java +++ b/core/src/main/java/google/registry/flows/poll/PollAckFlow.java @@ -21,6 +21,7 @@ import static google.registry.model.eppoutput.Result.Code.SUCCESS_WITH_NO_MESSAG import static google.registry.model.ofy.ObjectifyService.ofy; import static google.registry.model.poll.PollMessageExternalKeyConverter.makePollMessageExternalId; import static google.registry.model.poll.PollMessageExternalKeyConverter.parsePollMessageExternalId; +import static google.registry.model.transaction.TransactionManagerFactory.tm; import static google.registry.util.DateTimeUtils.isBeforeOrAt; import com.googlecode.objectify.Key; @@ -78,7 +79,7 @@ public class PollAckFlow implements TransactionalFlow { throw new InvalidMessageIdException(messageId); } - final DateTime now = ofy().getTransactionTime(); + final DateTime now = tm().getTransactionTime(); // Load the message to be acked. If a message is queued to be delivered in the future, we treat // it as if it doesn't exist yet. Same for if the message ID year isn't the same as the actual @@ -124,7 +125,7 @@ public class PollAckFlow implements TransactionalFlow { // acked, then we return a special status code indicating that. Note that the query will // include the message being acked. - int messageCount = ofy().doTransactionless(() -> getPollMessagesQuery(clientId, now).count()); + int messageCount = tm().doTransactionless(() -> getPollMessagesQuery(clientId, now).count()); if (!includeAckedMessageInCount) { messageCount--; } diff --git a/core/src/main/java/google/registry/keyring/kms/KmsUpdater.java b/core/src/main/java/google/registry/keyring/kms/KmsUpdater.java index 970a4eab5..2b522b2e7 100644 --- a/core/src/main/java/google/registry/keyring/kms/KmsUpdater.java +++ b/core/src/main/java/google/registry/keyring/kms/KmsUpdater.java @@ -33,6 +33,7 @@ import static google.registry.keyring.kms.KmsKeyring.StringKeyLabel.RDE_SSH_CLIE import static google.registry.keyring.kms.KmsKeyring.StringKeyLabel.RDE_SSH_CLIENT_PUBLIC_STRING; import static google.registry.keyring.kms.KmsKeyring.StringKeyLabel.SAFE_BROWSING_API_KEY; import static google.registry.model.ofy.ObjectifyService.ofy; +import static google.registry.model.transaction.TransactionManagerFactory.tm; import static google.registry.util.PreconditionsUtils.checkArgumentNotNull; import com.google.common.collect.ImmutableMap; @@ -182,7 +183,7 @@ public final class KmsUpdater { */ private static void persistEncryptedValues( final ImmutableMap encryptedValues) { - ofy() + tm() .transact( () -> { for (Map.Entry entry : encryptedValues.entrySet()) { diff --git a/core/src/main/java/google/registry/model/EppResource.java b/core/src/main/java/google/registry/model/EppResource.java index b14d08806..22dbca018 100644 --- a/core/src/main/java/google/registry/model/EppResource.java +++ b/core/src/main/java/google/registry/model/EppResource.java @@ -22,6 +22,7 @@ import static com.google.common.collect.Sets.union; import static google.registry.config.RegistryConfig.getEppResourceCachingDuration; import static google.registry.config.RegistryConfig.getEppResourceMaxCachedEntries; import static google.registry.model.ofy.ObjectifyService.ofy; +import static google.registry.model.transaction.TransactionManagerFactory.tm; import static google.registry.util.CollectionUtils.nullToEmpty; import static google.registry.util.CollectionUtils.nullToEmptyImmutableCopy; import static google.registry.util.DateTimeUtils.END_OF_TIME; @@ -325,13 +326,13 @@ public abstract class EppResource extends BackupGroupRoot implements Buildable { @Override public EppResource load(Key key) { - return ofy().doTransactionless(() -> ofy().load().key(key).now()); + return tm().doTransactionless(() -> ofy().load().key(key).now()); } @Override public Map, EppResource> loadAll( Iterable> keys) { - return ofy().doTransactionless(() -> loadMultiple(keys)); + return tm().doTransactionless(() -> loadMultiple(keys)); } }; diff --git a/core/src/main/java/google/registry/model/OteAccountBuilder.java b/core/src/main/java/google/registry/model/OteAccountBuilder.java index 5c10742df..f40c3d822 100644 --- a/core/src/main/java/google/registry/model/OteAccountBuilder.java +++ b/core/src/main/java/google/registry/model/OteAccountBuilder.java @@ -21,6 +21,7 @@ import static com.google.common.collect.ImmutableList.toImmutableList; import static google.registry.model.ofy.ObjectifyService.ofy; import static google.registry.model.registry.Registry.TldState.GENERAL_AVAILABILITY; import static google.registry.model.registry.Registry.TldState.START_DATE_SUNRISE; +import static google.registry.model.transaction.TransactionManagerFactory.tm; import static google.registry.util.DateTimeUtils.START_OF_TIME; import com.google.common.collect.ImmutableList; @@ -236,7 +237,7 @@ public final class OteAccountBuilder { */ public ImmutableMap buildAndPersist() { // save all the entitiesl in a single transaction - ofy().transact(this::saveAllEntities); + tm().transact(this::saveAllEntities); return clientIdToTld; } @@ -249,7 +250,7 @@ public final class OteAccountBuilder { /** Saves all the OT&E entities we created. */ private void saveAllEntities() { - ofy().assertInTransaction(); + tm().assertInTransaction(); ImmutableList registries = ImmutableList.of(sunriseTld, gaTld, eapTld); ImmutableList contacts = contactsBuilder.build(); diff --git a/core/src/main/java/google/registry/model/common/GaeUserIdConverter.java b/core/src/main/java/google/registry/model/common/GaeUserIdConverter.java index 57d08e156..02fd44556 100644 --- a/core/src/main/java/google/registry/model/common/GaeUserIdConverter.java +++ b/core/src/main/java/google/registry/model/common/GaeUserIdConverter.java @@ -17,6 +17,7 @@ package google.registry.model.common; import static com.google.common.base.Preconditions.checkState; import static google.registry.model.ofy.ObjectifyService.allocateId; import static google.registry.model.ofy.ObjectifyService.ofy; +import static google.registry.model.transaction.TransactionManagerFactory.tm; import com.google.appengine.api.users.User; import com.google.common.base.Splitter; @@ -55,13 +56,13 @@ public class GaeUserIdConverter extends ImmutableObject { try { // Perform these operations in a transactionless context to avoid enlisting in some outer // transaction (if any). - ofy().doTransactionless(() -> ofy().saveWithoutBackup().entity(gaeUserIdConverter).now()); + tm().doTransactionless(() -> ofy().saveWithoutBackup().entity(gaeUserIdConverter).now()); // The read must be done in its own transaction to avoid reading from the session cache. - return ofy() + return tm() .transactNew(() -> ofy().load().entity(gaeUserIdConverter).safe().user.getUserId()); } finally { - ofy().doTransactionless(() -> ofy().deleteWithoutBackup().entity(gaeUserIdConverter).now()); + tm().doTransactionless(() -> ofy().deleteWithoutBackup().entity(gaeUserIdConverter).now()); } } } diff --git a/core/src/main/java/google/registry/model/index/ForeignKeyIndex.java b/core/src/main/java/google/registry/model/index/ForeignKeyIndex.java index b98bc77c9..d0a6dc6fc 100644 --- a/core/src/main/java/google/registry/model/index/ForeignKeyIndex.java +++ b/core/src/main/java/google/registry/model/index/ForeignKeyIndex.java @@ -19,6 +19,7 @@ import static com.google.common.collect.Maps.filterValues; import static google.registry.config.RegistryConfig.getEppResourceCachingDuration; import static google.registry.config.RegistryConfig.getEppResourceMaxCachedEntries; import static google.registry.model.ofy.ObjectifyService.ofy; +import static google.registry.model.transaction.TransactionManagerFactory.tm; import static google.registry.util.TypeUtils.instantiate; import static java.util.concurrent.TimeUnit.MILLISECONDS; @@ -188,7 +189,7 @@ public abstract class ForeignKeyIndex extends BackupGroup @Override public Optional> load(Key> key) { - return Optional.ofNullable(ofy().doTransactionless(() -> ofy().load().key(key).now())); + return Optional.ofNullable(tm().doTransactionless(() -> ofy().load().key(key).now())); } @Override @@ -196,7 +197,7 @@ public abstract class ForeignKeyIndex extends BackupGroup Iterable>> keys) { ImmutableSet>> typedKeys = ImmutableSet.copyOf(keys); Map>, ForeignKeyIndex> existingFkis = - ofy().doTransactionless(() -> ofy().load().keys(typedKeys)); + tm().doTransactionless(() -> ofy().load().keys(typedKeys)); // ofy() omits keys that don't have values in Datastore, so re-add them in // here with Optional.empty() values. return Maps.asMap( @@ -250,7 +251,7 @@ public abstract class ForeignKeyIndex extends BackupGroup public static Map> loadCached( Class clazz, Iterable foreignKeys, final DateTime now) { if (!RegistryConfig.isEppResourceCachingEnabled()) { - return ofy().doTransactionless(() -> load(clazz, foreignKeys, now)); + return tm().doTransactionless(() -> load(clazz, foreignKeys, now)); } ImmutableList>> fkiKeys = Streams.stream(foreignKeys) diff --git a/core/src/main/java/google/registry/model/ofy/CommitLoggedWork.java b/core/src/main/java/google/registry/model/ofy/CommitLoggedWork.java index 8da543c85..f3e76e6a6 100644 --- a/core/src/main/java/google/registry/model/ofy/CommitLoggedWork.java +++ b/core/src/main/java/google/registry/model/ofy/CommitLoggedWork.java @@ -28,10 +28,9 @@ import static google.registry.util.DateTimeUtils.isBeforeOrAt; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.googlecode.objectify.Key; -import com.googlecode.objectify.VoidWork; -import com.googlecode.objectify.Work; import google.registry.model.BackupGroupRoot; import google.registry.model.ImmutableObject; +import google.registry.model.transaction.TransactionManager.Work; import google.registry.util.Clock; import java.util.HashSet; import java.util.Map; @@ -40,7 +39,7 @@ import java.util.Set; import org.joda.time.DateTime; /** Wrapper for {@link Work} that associates a time with each attempt. */ -class CommitLoggedWork extends VoidWork { +class CommitLoggedWork implements Runnable { private final Work work; private final Clock clock; @@ -74,8 +73,8 @@ class CommitLoggedWork extends VoidWork { */ protected ImmutableSet mutations = ImmutableSet.of(); - /** Lifecycle marker to track whether {@link #vrun} has been called. */ - private boolean vrunCalled; + /** Lifecycle marker to track whether {@link #run} has been called. */ + private boolean runCalled; CommitLoggedWork(Work work, Clock clock) { this.work = work; @@ -87,26 +86,26 @@ class CommitLoggedWork extends VoidWork { } boolean hasRun() { - return vrunCalled; + return runCalled; } R getResult() { - checkState(vrunCalled, "Cannot call getResult() before vrun()"); + checkState(runCalled, "Cannot call getResult() before run()"); return result; } CommitLogManifest getManifest() { - checkState(vrunCalled, "Cannot call getManifest() before vrun()"); + checkState(runCalled, "Cannot call getManifest() before run()"); return manifest; } ImmutableSet getMutations() { - checkState(vrunCalled, "Cannot call getMutations() before vrun()"); + checkState(runCalled, "Cannot call getMutations() before run()"); return mutations; } @Override - public void vrun() { + public void run() { // The previous time will generally be null, except when using transactNew. TransactionInfo previous = Ofy.TRANSACTION_INFO.get(); // Set the time to be used for "now" within the transaction. @@ -117,7 +116,7 @@ class CommitLoggedWork extends VoidWork { } finally { Ofy.TRANSACTION_INFO.set(previous); } - vrunCalled = true; + runCalled = true; } /** Records all mutations enrolled by this transaction to a {@link CommitLogManifest} entry. */ diff --git a/core/src/main/java/google/registry/model/ofy/DatastoreTransactionManager.java b/core/src/main/java/google/registry/model/ofy/DatastoreTransactionManager.java new file mode 100644 index 000000000..ded206aa1 --- /dev/null +++ b/core/src/main/java/google/registry/model/ofy/DatastoreTransactionManager.java @@ -0,0 +1,86 @@ +// Copyright 2019 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.model.ofy; + + +import static google.registry.model.ofy.ObjectifyService.ofy; + +import google.registry.model.transaction.TransactionManager; +import org.joda.time.DateTime; + +/** Datastore implementation of {@link TransactionManager}. */ +public class DatastoreTransactionManager implements TransactionManager { + + private Ofy injectedOfy; + + /** Constructs an instance. */ + public DatastoreTransactionManager(Ofy injectedOfy) { + this.injectedOfy = injectedOfy; + } + + private Ofy getOfy() { + return injectedOfy == null ? ofy() : injectedOfy; + } + + @Override + public boolean inTransaction() { + return getOfy().inTransaction(); + } + + @Override + public void assertInTransaction() { + getOfy().assertInTransaction(); + } + + @Override + public T transact(Work work) { + return getOfy().transact(work); + } + + @Override + public void transact(Runnable work) { + getOfy().transact(work); + } + + @Override + public T transactNew(Work work) { + return getOfy().transactNew(work); + } + + @Override + public void transactNew(Runnable work) { + getOfy().transactNew(work); + } + + @Override + public R transactNewReadOnly(Work work) { + return getOfy().transactNewReadOnly(work); + } + + @Override + public void transactNewReadOnly(Runnable work) { + getOfy().transactNewReadOnly(work); + } + + @Override + public R doTransactionless(Work work) { + return getOfy().doTransactionless(work); + } + + @Override + public DateTime getTransactionTime() { + return getOfy().getTransactionTime(); + } +} diff --git a/core/src/main/java/google/registry/model/ofy/Ofy.java b/core/src/main/java/google/registry/model/ofy/Ofy.java index e94024d24..fbf834d8d 100644 --- a/core/src/main/java/google/registry/model/ofy/Ofy.java +++ b/core/src/main/java/google/registry/model/ofy/Ofy.java @@ -32,13 +32,13 @@ import com.google.common.flogger.FluentLogger; import com.googlecode.objectify.Key; import com.googlecode.objectify.Objectify; import com.googlecode.objectify.ObjectifyFactory; -import com.googlecode.objectify.Work; import com.googlecode.objectify.cmd.Deleter; import com.googlecode.objectify.cmd.Loader; import com.googlecode.objectify.cmd.Saver; import google.registry.model.annotations.NotBackedUp; import google.registry.model.annotations.VirtualEntity; import google.registry.model.ofy.ReadOnlyWork.KillTransactionException; +import google.registry.model.transaction.TransactionManager.Work; import google.registry.util.Clock; import google.registry.util.NonFinalForTesting; import google.registry.util.Sleeper; @@ -111,11 +111,11 @@ public class Ofy { ofy().clear(); } - public boolean inTransaction() { + boolean inTransaction() { return ofy().getTransaction() != null; } - public void assertInTransaction() { + void assertInTransaction() { checkState(inTransaction(), "Must be called in a transaction"); } @@ -194,7 +194,7 @@ public class Ofy { } /** Execute a transaction. */ - public R transact(Work work) { + R transact(Work work) { // If we are already in a transaction, don't wrap in a CommitLoggedWork. return inTransaction() ? work.run() : transactNew(work); } @@ -205,7 +205,7 @@ public class Ofy { *

This overload is used for transactions that don't return a value, formerly implemented using * VoidWork. */ - public void transact(Runnable work) { + void transact(Runnable work) { transact( () -> { work.run(); @@ -214,7 +214,7 @@ public class Ofy { } /** Pause the current transaction (if any) and complete this one before returning to it. */ - public R transactNew(Work work) { + R transactNew(Work work) { // Wrap the Work in a CommitLoggedWork so that we can give transactions a frozen view of time // and maintain commit logs for them. return transactCommitLoggedWork(new CommitLoggedWork<>(work, getClock())); @@ -226,7 +226,7 @@ public class Ofy { *

This overload is used for transactions that don't return a value, formerly implemented using * VoidWork. */ - public void transactNew(Runnable work) { + void transactNew(Runnable work) { transactNew( () -> { work.run(); @@ -246,7 +246,10 @@ public class Ofy { true; attempt++, sleepMillis *= 2) { try { - ofy().transactNew(work); + ofy().transactNew(() -> { + work.run(); + return null; + }); return work.getResult(); } catch (TransientFailureException | TimestampInversionException @@ -295,10 +298,13 @@ public class Ofy { } /** A read-only transaction is useful to get strongly consistent reads at a shared timestamp. */ - public R transactNewReadOnly(Work work) { + R transactNewReadOnly(Work work) { ReadOnlyWork readOnlyWork = new ReadOnlyWork<>(work, getClock()); try { - ofy().transactNew(readOnlyWork); + ofy().transactNew(() -> { + readOnlyWork.run(); + return null; + }); } catch (TransientFailureException | DatastoreTimeoutException | DatastoreFailureException e) { // These are always retryable for a read-only operation. return transactNewReadOnly(work); @@ -309,7 +315,7 @@ public class Ofy { throw new AssertionError(); // How on earth did we get here? } - public void transactNewReadOnly(Runnable work) { + void transactNewReadOnly(Runnable work) { transactNewReadOnly( () -> { work.run(); @@ -318,7 +324,7 @@ public class Ofy { } /** Execute some work in a transactionless context. */ - public R doTransactionless(Work work) { + R doTransactionless(Work work) { try { com.googlecode.objectify.ObjectifyService.push( com.googlecode.objectify.ObjectifyService.ofy().transactionless()); @@ -347,7 +353,7 @@ public class Ofy { } /** Get the time associated with the start of this particular transaction attempt. */ - public DateTime getTransactionTime() { + DateTime getTransactionTime() { assertInTransaction(); return TRANSACTION_INFO.get().transactionTime; } diff --git a/core/src/main/java/google/registry/model/ofy/ReadOnlyWork.java b/core/src/main/java/google/registry/model/ofy/ReadOnlyWork.java index 70a7b419e..c93873ddf 100644 --- a/core/src/main/java/google/registry/model/ofy/ReadOnlyWork.java +++ b/core/src/main/java/google/registry/model/ofy/ReadOnlyWork.java @@ -14,7 +14,7 @@ package google.registry.model.ofy; -import com.googlecode.objectify.Work; +import google.registry.model.transaction.TransactionManager.Work; import google.registry.util.Clock; /** Wrapper for {@link Work} that disallows mutations and fails the transaction at the end. */ @@ -30,8 +30,8 @@ class ReadOnlyWork extends CommitLoggedWork { } @Override - public void vrun() { - super.vrun(); + public void run() { + super.run(); throw new KillTransactionException(); } diff --git a/core/src/main/java/google/registry/model/rde/RdeRevision.java b/core/src/main/java/google/registry/model/rde/RdeRevision.java index 3ae7bf494..4fc8dfa16 100644 --- a/core/src/main/java/google/registry/model/rde/RdeRevision.java +++ b/core/src/main/java/google/registry/model/rde/RdeRevision.java @@ -19,6 +19,7 @@ import static com.google.common.base.Verify.verify; import static com.google.common.base.Verify.verifyNotNull; import static google.registry.model.ofy.ObjectifyService.ofy; import static google.registry.model.rde.RdeNamingUtils.makePartialName; +import static google.registry.model.transaction.TransactionManagerFactory.tm; import com.google.common.base.VerifyException; import com.googlecode.objectify.annotation.Entity; @@ -70,7 +71,7 @@ public final class RdeRevision extends ImmutableObject { public static void saveRevision(String tld, DateTime date, RdeMode mode, int revision) { checkArgument(revision >= 0, "Negative revision: %s", revision); String triplet = makePartialName(tld, date, mode); - ofy().assertInTransaction(); + tm().assertInTransaction(); RdeRevision object = ofy().load().type(RdeRevision.class).id(triplet).now(); if (revision == 0) { verify(object == null, "RdeRevision object already created: %s", object); diff --git a/core/src/main/java/google/registry/model/registrar/Registrar.java b/core/src/main/java/google/registry/model/registrar/Registrar.java index 16e450050..fa15c3101 100644 --- a/core/src/main/java/google/registry/model/registrar/Registrar.java +++ b/core/src/main/java/google/registry/model/registrar/Registrar.java @@ -31,6 +31,7 @@ import static google.registry.model.CacheUtils.memoizeWithShortExpiration; import static google.registry.model.common.EntityGroupRoot.getCrossTldKey; import static google.registry.model.ofy.ObjectifyService.ofy; import static google.registry.model.registry.Registries.assertTldsExist; +import static google.registry.model.transaction.TransactionManagerFactory.tm; import static google.registry.util.CollectionUtils.nullToEmptyImmutableCopy; import static google.registry.util.CollectionUtils.nullToEmptyImmutableSortedCopy; import static google.registry.util.PreconditionsUtils.checkArgumentNotNull; @@ -206,7 +207,7 @@ public class Registrar extends ImmutableObject implements Buildable, Jsonifiable private static final Supplier> CACHE_BY_CLIENT_ID = memoizeWithShortExpiration( () -> - ofy() + tm() .doTransactionless( () -> Maps.uniqueIndex(loadAll(), Registrar::getClientId))); diff --git a/core/src/main/java/google/registry/model/registrar/RegistrarContact.java b/core/src/main/java/google/registry/model/registrar/RegistrarContact.java index b7ff0d85f..c660b724d 100644 --- a/core/src/main/java/google/registry/model/registrar/RegistrarContact.java +++ b/core/src/main/java/google/registry/model/registrar/RegistrarContact.java @@ -19,6 +19,7 @@ import static com.google.common.collect.ImmutableSet.toImmutableSet; import static com.google.common.collect.Sets.difference; import static google.registry.model.ofy.ObjectifyService.ofy; import static google.registry.model.registrar.Registrar.checkValidEmail; +import static google.registry.model.transaction.TransactionManagerFactory.tm; import static google.registry.util.CollectionUtils.nullToEmptyImmutableSortedCopy; import static java.util.stream.Collectors.joining; @@ -154,7 +155,7 @@ public class RegistrarContact extends ImmutableObject implements Jsonifiable { */ public static void updateContacts( final Registrar registrar, final Set contacts) { - ofy() + tm() .transact( () -> { ofy() diff --git a/core/src/main/java/google/registry/model/registry/Registries.java b/core/src/main/java/google/registry/model/registry/Registries.java index f1c3f8e4c..3805f4c77 100644 --- a/core/src/main/java/google/registry/model/registry/Registries.java +++ b/core/src/main/java/google/registry/model/registry/Registries.java @@ -24,6 +24,7 @@ import static com.google.common.collect.Maps.filterValues; import static google.registry.model.CacheUtils.memoizeWithShortExpiration; import static google.registry.model.common.EntityGroupRoot.getCrossTldKey; import static google.registry.model.ofy.ObjectifyService.ofy; +import static google.registry.model.transaction.TransactionManagerFactory.tm; import static google.registry.util.PreconditionsUtils.checkArgumentNotNull; import com.google.common.base.Joiner; @@ -52,7 +53,7 @@ public final class Registries { private static Supplier> createFreshCache() { return memoizeWithShortExpiration( () -> - ofy() + tm() .doTransactionless( () -> { ImmutableMap.Builder builder = diff --git a/core/src/main/java/google/registry/model/registry/Registry.java b/core/src/main/java/google/registry/model/registry/Registry.java index 5fb481f86..e4501ac2f 100644 --- a/core/src/main/java/google/registry/model/registry/Registry.java +++ b/core/src/main/java/google/registry/model/registry/Registry.java @@ -21,6 +21,7 @@ import static com.google.common.base.Predicates.not; import static google.registry.config.RegistryConfig.getSingletonCacheRefreshDuration; import static google.registry.model.common.EntityGroupRoot.getCrossTldKey; import static google.registry.model.ofy.ObjectifyService.ofy; +import static google.registry.model.transaction.TransactionManagerFactory.tm; import static google.registry.util.CollectionUtils.nullToEmptyImmutableCopy; import static google.registry.util.DateTimeUtils.END_OF_TIME; import static google.registry.util.DateTimeUtils.START_OF_TIME; @@ -222,7 +223,7 @@ public class Registry extends ImmutableObject implements Buildable { // Enter a transactionless context briefly; we don't want to enroll every TLD in a // transaction that might be wrapping this call. return Optional.ofNullable( - ofy() + tm() .doTransactionless( () -> ofy() .load() diff --git a/core/src/main/java/google/registry/model/registry/label/PremiumList.java b/core/src/main/java/google/registry/model/registry/label/PremiumList.java index 2158db1d8..6e5ccb014 100644 --- a/core/src/main/java/google/registry/model/registry/label/PremiumList.java +++ b/core/src/main/java/google/registry/model/registry/label/PremiumList.java @@ -22,6 +22,7 @@ import static google.registry.config.RegistryConfig.getStaticPremiumListMaxCache import static google.registry.model.common.EntityGroupRoot.getCrossTldKey; import static google.registry.model.ofy.ObjectifyService.allocateId; import static google.registry.model.ofy.ObjectifyService.ofy; +import static google.registry.model.transaction.TransactionManagerFactory.tm; import static java.util.concurrent.TimeUnit.MILLISECONDS; import com.google.common.annotations.VisibleForTesting; @@ -150,7 +151,7 @@ public final class PremiumList extends BaseDomainLabelList() { @Override public PremiumList load(final String name) { - return ofy().doTransactionless(() -> loadPremiumList(name)); + return tm().doTransactionless(() -> loadPremiumList(name)); } }); } @@ -174,7 +175,7 @@ public final class PremiumList extends BaseDomainLabelList, PremiumListRevision>() { @Override public PremiumListRevision load(final Key revisionKey) { - return ofy().doTransactionless(() -> ofy().load().key(revisionKey).now()); + return tm().doTransactionless(() -> ofy().load().key(revisionKey).now()); } }); @@ -214,7 +215,7 @@ public final class PremiumList extends BaseDomainLabelList, Optional>() { @Override public Optional load(final Key entryKey) { - return ofy() + return tm() .doTransactionless(() -> Optional.ofNullable(ofy().load().key(entryKey).now())); } }); diff --git a/core/src/main/java/google/registry/model/registry/label/PremiumListUtils.java b/core/src/main/java/google/registry/model/registry/label/PremiumListUtils.java index d8df27851..3faeda30e 100644 --- a/core/src/main/java/google/registry/model/registry/label/PremiumListUtils.java +++ b/core/src/main/java/google/registry/model/registry/label/PremiumListUtils.java @@ -27,6 +27,7 @@ import static google.registry.model.registry.label.DomainLabelMetrics.PremiumLis import static google.registry.model.registry.label.PremiumList.cachePremiumListEntries; import static google.registry.model.registry.label.PremiumList.cachePremiumListRevisions; import static google.registry.model.registry.label.PremiumList.cachePremiumLists; +import static google.registry.model.transaction.TransactionManagerFactory.tm; import static org.joda.time.DateTimeZone.UTC; import com.google.auto.value.AutoValue; @@ -151,12 +152,12 @@ public final class PremiumListUtils { // Save the new child entities in a series of transactions. for (final List batch : partition(parentedEntries, TRANSACTION_BATCH_SIZE)) { - ofy().transactNew(() -> ofy().save().entities(batch)); + tm().transactNew(() -> ofy().save().entities(batch)); } // Save the new PremiumList and revision itself. - PremiumList updated = ofy().transactNew(() -> { - DateTime now = ofy().getTransactionTime(); + PremiumList updated = tm().transactNew(() -> { + DateTime now = tm().getTransactionTime(); // Assert that the premium list hasn't been changed since we started this process. PremiumList existing = ofy().load() .type(PremiumList.class) @@ -201,7 +202,7 @@ public final class PremiumListUtils { /** Deletes the PremiumList and all of its child entities. */ public static void deletePremiumList(final PremiumList premiumList) { - ofy().transactNew(() -> ofy().delete().entity(premiumList)); + tm().transactNew(() -> ofy().delete().entity(premiumList)); deleteRevisionAndEntriesOfPremiumList(premiumList); cachePremiumLists.invalidate(premiumList.getName()); } @@ -214,9 +215,9 @@ public final class PremiumListUtils { partition( ofy().load().type(PremiumListEntry.class).ancestor(premiumList.revisionKey).keys(), TRANSACTION_BATCH_SIZE)) { - ofy().transactNew(() -> ofy().delete().keys(batch)); + tm().transactNew(() -> ofy().delete().keys(batch)); } - ofy().transactNew(() -> ofy().delete().key(premiumList.getRevisionKey())); + tm().transactNew(() -> ofy().delete().key(premiumList.getRevisionKey())); } /** diff --git a/core/src/main/java/google/registry/model/server/Lock.java b/core/src/main/java/google/registry/model/server/Lock.java index b897c76e0..bd008a905 100644 --- a/core/src/main/java/google/registry/model/server/Lock.java +++ b/core/src/main/java/google/registry/model/server/Lock.java @@ -16,6 +16,7 @@ package google.registry.model.server; import static com.google.common.base.Preconditions.checkArgument; import static google.registry.model.ofy.ObjectifyService.ofy; +import static google.registry.model.transaction.TransactionManagerFactory.tm; import static google.registry.util.DateTimeUtils.isAtOrAfter; import com.google.auto.value.AutoValue; @@ -176,10 +177,10 @@ public class Lock extends ImmutableObject implements Serializable { // access to resources like GCS that can't be transactionally rolled back. Therefore, the lock // must be definitively acquired before it is used, even when called inside another transaction. AcquireResult acquireResult = - ofy() + tm() .transactNew( () -> { - DateTime now = ofy().getTransactionTime(); + DateTime now = tm().getTransactionTime(); // Checking if an unexpired lock still exists - if so, the lock can't be acquired. Lock lock = ofy().load().type(Lock.class).id(lockId).now(); @@ -217,7 +218,7 @@ public class Lock extends ImmutableObject implements Serializable { /** Release the lock. */ public void release() { // Just use the default clock because we aren't actually doing anything that will use the clock. - ofy() + tm() .transact( () -> { // To release a lock, check that no one else has already obtained it and if not @@ -231,7 +232,7 @@ public class Lock extends ImmutableObject implements Serializable { logger.atInfo().log("Deleting lock: %s", lockId); ofy().deleteWithoutBackup().entity(Lock.this); lockMetrics.recordRelease( - resourceName, tld, new Duration(acquiredTime, ofy().getTransactionTime())); + resourceName, tld, new Duration(acquiredTime, tm().getTransactionTime())); } else { logger.atSevere().log( "The lock we acquired was transferred to someone else before we" diff --git a/core/src/main/java/google/registry/model/server/ServerSecret.java b/core/src/main/java/google/registry/model/server/ServerSecret.java index b36fd5d0c..107d6cd34 100644 --- a/core/src/main/java/google/registry/model/server/ServerSecret.java +++ b/core/src/main/java/google/registry/model/server/ServerSecret.java @@ -15,6 +15,7 @@ package google.registry.model.server; import static google.registry.model.ofy.ObjectifyService.ofy; +import static google.registry.model.transaction.TransactionManagerFactory.tm; import com.google.common.annotations.VisibleForTesting; import com.google.common.cache.CacheBuilder; @@ -54,7 +55,7 @@ public class ServerSecret extends CrossTldSingleton { return secret; } // Slow path - transactionally create a new ServerSecret (once per app setup). - return ofy().transact(() -> { + return tm().transact(() -> { // Check again for an existing secret within the transaction to avoid races. ServerSecret secret1 = ofy().load().entity(new ServerSecret()).now(); if (secret1 == null) { diff --git a/core/src/main/java/google/registry/model/smd/SignedMarkRevocationList.java b/core/src/main/java/google/registry/model/smd/SignedMarkRevocationList.java index e5222d229..73d5a2f82 100644 --- a/core/src/main/java/google/registry/model/smd/SignedMarkRevocationList.java +++ b/core/src/main/java/google/registry/model/smd/SignedMarkRevocationList.java @@ -22,6 +22,7 @@ import static google.registry.model.CacheUtils.memoizeWithShortExpiration; import static google.registry.model.common.EntityGroupRoot.getCrossTldKey; import static google.registry.model.ofy.ObjectifyService.allocateId; import static google.registry.model.ofy.ObjectifyService.ofy; +import static google.registry.model.transaction.TransactionManagerFactory.tm; import static google.registry.util.DateTimeUtils.START_OF_TIME; import static google.registry.util.DateTimeUtils.isBeforeOrAt; @@ -92,7 +93,7 @@ public class SignedMarkRevocationList extends ImmutableObject { private static final Supplier CACHE = memoizeWithShortExpiration( () -> - ofy() + tm() .transactNewReadOnly( () -> { Iterable shards = @@ -150,7 +151,7 @@ public class SignedMarkRevocationList extends ImmutableObject { /** Save this list to Datastore in sharded form. Returns {@code this}. */ public SignedMarkRevocationList save() { - ofy() + tm() .transact( () -> { ofy() diff --git a/core/src/main/java/google/registry/model/tmch/ClaimsListShard.java b/core/src/main/java/google/registry/model/tmch/ClaimsListShard.java index 7527296b5..b3dd8cbd0 100644 --- a/core/src/main/java/google/registry/model/tmch/ClaimsListShard.java +++ b/core/src/main/java/google/registry/model/tmch/ClaimsListShard.java @@ -21,6 +21,7 @@ import static com.google.common.base.Verify.verify; import static google.registry.model.CacheUtils.memoizeWithShortExpiration; import static google.registry.model.ofy.ObjectifyService.allocateId; import static google.registry.model.ofy.ObjectifyService.ofy; +import static google.registry.model.transaction.TransactionManagerFactory.tm; import static google.registry.util.DateTimeUtils.START_OF_TIME; import com.google.common.annotations.VisibleForTesting; @@ -111,7 +112,7 @@ public class ClaimsListShard extends ImmutableObject { Concurrent.transform( shardKeys, key -> - ofy() + tm() .transactNewReadOnly( () -> { ClaimsListShard claimsListShard = ofy().load().key(key).now(); @@ -188,7 +189,7 @@ public class ClaimsListShard extends ImmutableObject { Concurrent.transform( CollectionUtils.partitionMap(labelsToKeys, shardSize), (final ImmutableMap labelsToKeysShard) -> - ofy() + tm() .transactNew( () -> { ClaimsListShard shard = create(creationTime, labelsToKeysShard); @@ -199,7 +200,7 @@ public class ClaimsListShard extends ImmutableObject { })); // Persist the new revision, thus causing the newly created shards to go live. - ofy() + tm() .transactNew( () -> { verify( diff --git a/core/src/main/java/google/registry/model/tmch/TmchCrl.java b/core/src/main/java/google/registry/model/tmch/TmchCrl.java index 939474750..2a61c915b 100644 --- a/core/src/main/java/google/registry/model/tmch/TmchCrl.java +++ b/core/src/main/java/google/registry/model/tmch/TmchCrl.java @@ -16,6 +16,7 @@ package google.registry.model.tmch; import static com.google.common.base.Preconditions.checkNotNull; import static google.registry.model.ofy.ObjectifyService.ofy; +import static google.registry.model.transaction.TransactionManagerFactory.tm; import com.googlecode.objectify.annotation.Entity; import google.registry.model.annotations.NotBackedUp; @@ -48,11 +49,11 @@ public final class TmchCrl extends CrossTldSingleton { * and actually newer than the one currently in Datastore. */ public static void set(final String crl, final String url) { - ofy() + tm() .transactNew( () -> { TmchCrl tmchCrl = new TmchCrl(); - tmchCrl.updated = ofy().getTransactionTime(); + tmchCrl.updated = tm().getTransactionTime(); tmchCrl.crl = checkNotNull(crl, "crl"); tmchCrl.url = checkNotNull(url, "url"); ofy().saveWithoutBackup().entity(tmchCrl); diff --git a/core/src/main/java/google/registry/model/transaction/TransactionManager.java b/core/src/main/java/google/registry/model/transaction/TransactionManager.java new file mode 100644 index 000000000..ba1ec7e6a --- /dev/null +++ b/core/src/main/java/google/registry/model/transaction/TransactionManager.java @@ -0,0 +1,84 @@ +// Copyright 2019 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.model.transaction; + +import org.joda.time.DateTime; + +/** + * This interface defines the methods to execute database operations with or without a transaction. + */ +public interface TransactionManager { + + /** This functional interface defines a method to execute a work and return the result. */ + @FunctionalInterface + interface Work { + R run(); + } + + /** Returns {@code true} if the caller is in a transaction. + * + *

Note that this function is kept for backward compatibility. We will review the use case + * later when adding the cloud sql implementation. + */ + boolean inTransaction(); + + /** Throws {@link IllegalStateException} if the caller is not in a transaction. + * + *

Note that this function is kept for backward compatibility. We will review the use case + * later when adding the cloud sql implementation. + */ + void assertInTransaction(); + + /** Executes the work in a transaction and returns the result. */ + T transact(Work work); + + /** Executes the work in a transaction. */ + void transact(Runnable work); + + /** Pauses the current transaction (if any), executes the work in a new transaction + * and returns the result. + * + *

Note that this function is kept for backward compatibility. We will review the use case + * later when adding the cloud sql implementation. + */ + T transactNew(Work work); + + /** Pauses the current transaction (if any) and executes the work in a new transaction. + * + *

Note that this function is kept for backward compatibility. We will review the use case + * later when adding the cloud sql implementation. + */ + void transactNew(Runnable work); + + /** Executes the work in a read-only transaction and returns the result. + * + *

Note that this function is kept for backward compatibility. We will review the use case + * later when adding the cloud sql implementation. + */ + R transactNewReadOnly(Work work); + + /** Executes the work in a read-only transaction. + * + *

Note that this function is kept for backward compatibility. We will review the use case + * later when adding the cloud sql implementation. + */ + void transactNewReadOnly(Runnable work); + + /** Executes the work in a transactionless context. */ + R doTransactionless(Work work); + + /** Returns the time associated with the start of this particular transaction attempt. */ + DateTime getTransactionTime(); +} diff --git a/core/src/main/java/google/registry/model/transaction/TransactionManagerFactory.java b/core/src/main/java/google/registry/model/transaction/TransactionManagerFactory.java new file mode 100644 index 000000000..1dc0231f9 --- /dev/null +++ b/core/src/main/java/google/registry/model/transaction/TransactionManagerFactory.java @@ -0,0 +1,37 @@ +// Copyright 2019 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.model.transaction; + +import google.registry.model.ofy.DatastoreTransactionManager; + +/** Factory class to create {@link TransactionManager} instance. */ +public class TransactionManagerFactory { + + private static final TransactionManager TM = createTransactionManager(); + + private TransactionManagerFactory() {} + + private static TransactionManager createTransactionManager() { + // TODO: Conditionally returns the corresponding implementation once we have + // CloudSqlTransactionManager + return new DatastoreTransactionManager(null); + } + + /** Returns {@link TransactionManager} instance. */ + public static TransactionManager tm() { + + return TM; + } +} diff --git a/core/src/main/java/google/registry/model/translators/CommitLogRevisionsTranslatorFactory.java b/core/src/main/java/google/registry/model/translators/CommitLogRevisionsTranslatorFactory.java index 45f9a65f0..e3601e9af 100644 --- a/core/src/main/java/google/registry/model/translators/CommitLogRevisionsTranslatorFactory.java +++ b/core/src/main/java/google/registry/model/translators/CommitLogRevisionsTranslatorFactory.java @@ -17,6 +17,7 @@ package google.registry.model.translators; import static com.google.common.base.MoreObjects.firstNonNull; import static google.registry.config.RegistryConfig.getCommitLogDatastoreRetention; import static google.registry.model.ofy.ObjectifyService.ofy; +import static google.registry.model.transaction.TransactionManagerFactory.tm; import static google.registry.util.DateTimeUtils.START_OF_TIME; import com.google.common.collect.ImmutableSortedMap; @@ -62,7 +63,7 @@ public final class CommitLogRevisionsTranslatorFactory @Override ImmutableSortedMap> transformBeforeSave( ImmutableSortedMap> revisions) { - DateTime now = ofy().getTransactionTime(); + DateTime now = tm().getTransactionTime(); DateTime threshold = now.minus(getCommitLogDatastoreRetention()); DateTime preThresholdTime = firstNonNull(revisions.floorKey(threshold), START_OF_TIME); return new ImmutableSortedMap.Builder>(Ordering.natural()) diff --git a/core/src/main/java/google/registry/model/translators/CreateAutoTimestampTranslatorFactory.java b/core/src/main/java/google/registry/model/translators/CreateAutoTimestampTranslatorFactory.java index e8b9825c2..61f69017b 100644 --- a/core/src/main/java/google/registry/model/translators/CreateAutoTimestampTranslatorFactory.java +++ b/core/src/main/java/google/registry/model/translators/CreateAutoTimestampTranslatorFactory.java @@ -15,7 +15,7 @@ package google.registry.model.translators; import static com.google.common.base.MoreObjects.firstNonNull; -import static google.registry.model.ofy.ObjectifyService.ofy; +import static google.registry.model.transaction.TransactionManagerFactory.tm; import static org.joda.time.DateTimeZone.UTC; import google.registry.model.CreateAutoTimestamp; @@ -46,7 +46,7 @@ public class CreateAutoTimestampTranslatorFactory /** Save a timestamp, setting it to the current time if it did not have a previous value. */ @Override public Date saveValue(CreateAutoTimestamp pojoValue) { - return firstNonNull(pojoValue.getTimestamp(), ofy().getTransactionTime()).toDate(); + return firstNonNull(pojoValue.getTimestamp(), tm().getTransactionTime()).toDate(); }}; } } diff --git a/core/src/main/java/google/registry/model/translators/UpdateAutoTimestampTranslatorFactory.java b/core/src/main/java/google/registry/model/translators/UpdateAutoTimestampTranslatorFactory.java index d70329a17..ea73848ea 100644 --- a/core/src/main/java/google/registry/model/translators/UpdateAutoTimestampTranslatorFactory.java +++ b/core/src/main/java/google/registry/model/translators/UpdateAutoTimestampTranslatorFactory.java @@ -14,7 +14,7 @@ package google.registry.model.translators; -import static google.registry.model.ofy.ObjectifyService.ofy; +import static google.registry.model.transaction.TransactionManagerFactory.tm; import static org.joda.time.DateTimeZone.UTC; import google.registry.model.UpdateAutoTimestamp; @@ -46,7 +46,7 @@ public class UpdateAutoTimestampTranslatorFactory /** Save a timestamp, setting it to the current time. */ @Override public Date saveValue(UpdateAutoTimestamp pojoValue) { - return ofy().getTransactionTime().toDate(); + return tm().getTransactionTime().toDate(); }}; } } diff --git a/core/src/main/java/google/registry/rdap/UpdateRegistrarRdapBaseUrlsAction.java b/core/src/main/java/google/registry/rdap/UpdateRegistrarRdapBaseUrlsAction.java index b62e25569..7f1290f8c 100644 --- a/core/src/main/java/google/registry/rdap/UpdateRegistrarRdapBaseUrlsAction.java +++ b/core/src/main/java/google/registry/rdap/UpdateRegistrarRdapBaseUrlsAction.java @@ -17,6 +17,7 @@ package google.registry.rdap; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkState; import static google.registry.model.ofy.ObjectifyService.ofy; +import static google.registry.model.transaction.TransactionManagerFactory.tm; import static java.nio.charset.StandardCharsets.UTF_8; import com.google.api.client.http.GenericUrl; @@ -197,7 +198,7 @@ public final class UpdateRegistrarRdapBaseUrlsAction implements Runnable { ImmutableSetMultimap ianaToBaseUrls = getRdapBaseUrlsPerIanaId(); for (Key registrarKey : ofy().load().type(Registrar.class).keys()) { - ofy() + tm() .transact( () -> { Registrar registrar = ofy().load().key(registrarKey).now(); diff --git a/core/src/main/java/google/registry/rde/EscrowTaskRunner.java b/core/src/main/java/google/registry/rde/EscrowTaskRunner.java index e68a404f9..3052894f6 100644 --- a/core/src/main/java/google/registry/rde/EscrowTaskRunner.java +++ b/core/src/main/java/google/registry/rde/EscrowTaskRunner.java @@ -15,6 +15,7 @@ package google.registry.rde; import static google.registry.model.ofy.ObjectifyService.ofy; +import static google.registry.model.transaction.TransactionManagerFactory.tm; import com.google.common.flogger.FluentLogger; import google.registry.model.common.Cursor; @@ -98,7 +99,7 @@ class EscrowTaskRunner { task.runWithLock(nextRequiredRun); DateTime nextRun = nextRequiredRun.plus(interval); logger.atInfo().log("Rolling cursor forward to %s.", nextRun); - ofy().transact(() -> ofy().save().entity(Cursor.create(cursorType, nextRun, registry))); + tm().transact(() -> ofy().save().entity(Cursor.create(cursorType, nextRun, registry))); return null; }; String lockName = String.format("EscrowTaskRunner %s", task.getClass().getSimpleName()); diff --git a/core/src/main/java/google/registry/rde/PendingDepositChecker.java b/core/src/main/java/google/registry/rde/PendingDepositChecker.java index 64c91a1e5..89b1415c1 100644 --- a/core/src/main/java/google/registry/rde/PendingDepositChecker.java +++ b/core/src/main/java/google/registry/rde/PendingDepositChecker.java @@ -16,6 +16,7 @@ package google.registry.rde; import static com.google.common.base.Preconditions.checkArgument; import static google.registry.model.ofy.ObjectifyService.ofy; +import static google.registry.model.transaction.TransactionManagerFactory.tm; import static google.registry.util.DateTimeUtils.isBeforeOrAt; import com.google.common.collect.ImmutableSetMultimap; @@ -106,7 +107,7 @@ public final class PendingDepositChecker { final Registry registry, final CursorType cursorType, final DateTime initialValue) { - return ofy() + return tm() .transact( () -> { Cursor cursor = ofy().load().key(Cursor.createKey(cursorType, registry)).now(); diff --git a/core/src/main/java/google/registry/rde/RdeStagingReducer.java b/core/src/main/java/google/registry/rde/RdeStagingReducer.java index 0b51d9e3b..170903cb3 100644 --- a/core/src/main/java/google/registry/rde/RdeStagingReducer.java +++ b/core/src/main/java/google/registry/rde/RdeStagingReducer.java @@ -21,6 +21,7 @@ import static com.google.common.base.Preconditions.checkState; import static com.google.common.base.Verify.verify; import static google.registry.model.common.Cursor.getCursorTimeOrStartOfTime; import static google.registry.model.ofy.ObjectifyService.ofy; +import static google.registry.model.transaction.TransactionManagerFactory.tm; import static java.nio.charset.StandardCharsets.UTF_8; import com.google.appengine.tools.cloudstorage.GcsFilename; @@ -202,7 +203,7 @@ public final class RdeStagingReducer extends Reducer { Registry registry = Registry.get(tld); diff --git a/core/src/main/java/google/registry/rde/RdeUploadAction.java b/core/src/main/java/google/registry/rde/RdeUploadAction.java index b2d446d5e..c1f5991a1 100644 --- a/core/src/main/java/google/registry/rde/RdeUploadAction.java +++ b/core/src/main/java/google/registry/rde/RdeUploadAction.java @@ -22,6 +22,7 @@ import static google.registry.model.common.Cursor.CursorType.RDE_UPLOAD_SFTP; import static google.registry.model.common.Cursor.getCursorTimeOrStartOfTime; import static google.registry.model.ofy.ObjectifyService.ofy; import static google.registry.model.rde.RdeMode.FULL; +import static google.registry.model.transaction.TransactionManagerFactory.tm; import static google.registry.request.Action.Method.POST; import static google.registry.util.DateTimeUtils.isBeforeOrAt; import static java.util.Arrays.asList; @@ -169,11 +170,11 @@ public final class RdeUploadAction implements Runnable, EscrowTask { () -> upload(xmlFilename, xmlLength, watermark, name), JSchException.class); logger.atInfo().log( "Updating RDE cursor '%s' for TLD '%s' following successful upload.", RDE_UPLOAD_SFTP, tld); - ofy() + tm() .transact( () -> { Cursor updatedSftpCursor = - Cursor.create(RDE_UPLOAD_SFTP, ofy().getTransactionTime(), Registry.get(tld)); + Cursor.create(RDE_UPLOAD_SFTP, tm().getTransactionTime(), Registry.get(tld)); ofy().save().entity(updatedSftpCursor); }); response.setContentType(PLAIN_TEXT_UTF_8); diff --git a/core/src/main/java/google/registry/tmch/LordnTaskUtils.java b/core/src/main/java/google/registry/tmch/LordnTaskUtils.java index 855a73b3e..ab8fe8218 100644 --- a/core/src/main/java/google/registry/tmch/LordnTaskUtils.java +++ b/core/src/main/java/google/registry/tmch/LordnTaskUtils.java @@ -16,7 +16,7 @@ package google.registry.tmch; import static com.google.appengine.api.taskqueue.QueueFactory.getQueue; import static com.google.common.base.Preconditions.checkState; -import static google.registry.model.ofy.ObjectifyService.ofy; +import static google.registry.model.transaction.TransactionManagerFactory.tm; import com.google.appengine.api.taskqueue.TaskOptions; import com.google.appengine.api.taskqueue.TaskOptions.Method; @@ -47,7 +47,7 @@ public final class LordnTaskUtils { * Enqueues a task in the LORDN queue representing a line of CSV for LORDN export. */ public static void enqueueDomainBaseTask(DomainBase domain) { - ofy().assertInTransaction(); + tm().assertInTransaction(); // This method needs to use ofy transactionTime as the DomainBase's creationTime because // CreationTime isn't yet populated when this method is called during the resource flow. String tld = domain.getTld(); @@ -55,12 +55,12 @@ public final class LordnTaskUtils { getQueue(QUEUE_SUNRISE).add(TaskOptions.Builder .withTag(tld) .method(Method.PULL) - .payload(getCsvLineForSunriseDomain(domain, ofy().getTransactionTime()))); + .payload(getCsvLineForSunriseDomain(domain, tm().getTransactionTime()))); } else { getQueue(QUEUE_CLAIMS).add(TaskOptions.Builder .withTag(tld) .method(Method.PULL) - .payload(getCsvLineForClaimsDomain(domain, ofy().getTransactionTime()))); + .payload(getCsvLineForClaimsDomain(domain, tm().getTransactionTime()))); } } diff --git a/core/src/main/java/google/registry/tools/AckPollMessagesCommand.java b/core/src/main/java/google/registry/tools/AckPollMessagesCommand.java index 1169f0263..b73a190b1 100644 --- a/core/src/main/java/google/registry/tools/AckPollMessagesCommand.java +++ b/core/src/main/java/google/registry/tools/AckPollMessagesCommand.java @@ -19,6 +19,7 @@ import static com.google.common.collect.ImmutableList.toImmutableList; import static google.registry.flows.poll.PollFlowUtils.getPollMessagesQuery; import static google.registry.model.ofy.ObjectifyService.ofy; import static google.registry.model.poll.PollMessageExternalKeyConverter.makePollMessageExternalId; +import static google.registry.model.transaction.TransactionManagerFactory.tm; import com.beust.jcommander.Parameter; import com.beust.jcommander.Parameters; @@ -85,7 +86,7 @@ final class AckPollMessagesCommand implements CommandWithRemoteApi { public void run() { QueryKeys query = getPollMessagesQuery(clientId, clock.nowUtc()).keys(); for (List> keys : Iterables.partition(query, BATCH_SIZE)) { - ofy() + tm() .transact( () -> { // Load poll messages and filter to just those of interest. diff --git a/core/src/main/java/google/registry/tools/DeleteAllocationTokensCommand.java b/core/src/main/java/google/registry/tools/DeleteAllocationTokensCommand.java index 6ee184d12..9a5d66ab5 100644 --- a/core/src/main/java/google/registry/tools/DeleteAllocationTokensCommand.java +++ b/core/src/main/java/google/registry/tools/DeleteAllocationTokensCommand.java @@ -19,6 +19,7 @@ import static com.google.common.collect.Iterables.partition; import static com.google.common.collect.Streams.stream; import static google.registry.model.domain.token.AllocationToken.TokenType.SINGLE_USE; import static google.registry.model.ofy.ObjectifyService.ofy; +import static google.registry.model.transaction.TransactionManagerFactory.tm; import com.beust.jcommander.Parameter; import com.beust.jcommander.Parameters; @@ -64,7 +65,7 @@ final class DeleteAllocationTokensCommand extends UpdateOrDeleteAllocationTokens protected String execute() { long numDeleted = stream(partition(tokensToDelete, BATCH_SIZE)) - .mapToLong(batch -> ofy().transact(() -> deleteBatch(batch))) + .mapToLong(batch -> tm().transact(() -> deleteBatch(batch))) .sum(); return String.format("Deleted %d tokens in total.", numDeleted); } diff --git a/core/src/main/java/google/registry/tools/DeleteTldCommand.java b/core/src/main/java/google/registry/tools/DeleteTldCommand.java index 4859f2e4d..cbe246a11 100644 --- a/core/src/main/java/google/registry/tools/DeleteTldCommand.java +++ b/core/src/main/java/google/registry/tools/DeleteTldCommand.java @@ -16,6 +16,7 @@ package google.registry.tools; import static com.google.common.base.Preconditions.checkState; import static google.registry.model.ofy.ObjectifyService.ofy; +import static google.registry.model.transaction.TransactionManagerFactory.tm; import com.beust.jcommander.Parameter; import com.beust.jcommander.Parameters; @@ -76,7 +77,7 @@ final class DeleteTldCommand extends ConfirmingCommand implements CommandWithRem @Override protected String execute() { - ofy().transactNew(() -> ofy().delete().entity(registry).now()); + tm().transactNew(() -> ofy().delete().entity(registry).now()); registry.invalidateInCache(); return String.format("Deleted TLD '%s'.\n", tld); } diff --git a/core/src/main/java/google/registry/tools/GenerateAllocationTokensCommand.java b/core/src/main/java/google/registry/tools/GenerateAllocationTokensCommand.java index eadaf99a9..08a869f25 100644 --- a/core/src/main/java/google/registry/tools/GenerateAllocationTokensCommand.java +++ b/core/src/main/java/google/registry/tools/GenerateAllocationTokensCommand.java @@ -21,6 +21,7 @@ import static com.google.common.collect.Sets.difference; import static google.registry.model.domain.token.AllocationToken.TokenType.SINGLE_USE; import static google.registry.model.domain.token.AllocationToken.TokenType.UNLIMITED_USE; import static google.registry.model.ofy.ObjectifyService.ofy; +import static google.registry.model.transaction.TransactionManagerFactory.tm; import static google.registry.util.CollectionUtils.nullToEmpty; import static google.registry.util.StringGenerator.DEFAULT_PASSWORD_LENGTH; import static java.nio.charset.StandardCharsets.UTF_8; @@ -191,7 +192,7 @@ class GenerateAllocationTokensCommand implements CommandWithRemoteApi { @VisibleForTesting int saveTokens(final ImmutableSet tokens) { Collection savedTokens = - dryRun ? tokens : ofy().transact(() -> ofy().save().entities(tokens).now().values()); + dryRun ? tokens : tm().transact(() -> ofy().save().entities(tokens).now().values()); savedTokens.forEach( t -> System.out.println(SKIP_NULLS.join(t.getDomainName().orElse(null), t.getToken()))); return savedTokens.size(); diff --git a/core/src/main/java/google/registry/tools/MutatingCommand.java b/core/src/main/java/google/registry/tools/MutatingCommand.java index c0ac3d525..a7f88898e 100644 --- a/core/src/main/java/google/registry/tools/MutatingCommand.java +++ b/core/src/main/java/google/registry/tools/MutatingCommand.java @@ -21,6 +21,7 @@ import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkState; import static com.google.common.base.Strings.emptyToNull; import static google.registry.model.ofy.ObjectifyService.ofy; +import static google.registry.model.transaction.TransactionManagerFactory.tm; import static google.registry.util.DatastoreServiceUtils.getNameOrId; import static google.registry.util.DiffUtils.prettyPrintEntityDeepDiff; import static java.util.stream.Collectors.joining; @@ -140,7 +141,7 @@ public abstract class MutatingCommand extends ConfirmingCommand implements Comma @Override protected String execute() throws Exception { for (final List batch : getCollatedEntityChangeBatches()) { - ofy().transact(() -> batch.forEach(this::executeChange)); + tm().transact(() -> batch.forEach(this::executeChange)); } return String.format("Updated %d entities.\n", changedEntitiesMap.size()); } diff --git a/core/src/main/java/google/registry/tools/ResaveEnvironmentEntitiesCommand.java b/core/src/main/java/google/registry/tools/ResaveEnvironmentEntitiesCommand.java index 790bf47c1..dd693c5b9 100644 --- a/core/src/main/java/google/registry/tools/ResaveEnvironmentEntitiesCommand.java +++ b/core/src/main/java/google/registry/tools/ResaveEnvironmentEntitiesCommand.java @@ -17,6 +17,7 @@ package google.registry.tools; import static com.google.common.collect.Lists.partition; import static google.registry.model.common.EntityGroupRoot.getCrossTldKey; import static google.registry.model.ofy.ObjectifyService.ofy; +import static google.registry.model.transaction.TransactionManagerFactory.tm; import com.beust.jcommander.Parameters; import com.googlecode.objectify.Key; @@ -46,7 +47,7 @@ final class ResaveEnvironmentEntitiesCommand implements CommandWithRemoteApi { System.out.printf("Re-saving %s entities.\n", clazz.getSimpleName()); for (final Iterable> batch : partition(ofy().load().type(clazz).ancestor(getCrossTldKey()).keys().list(), BATCH_SIZE)) { - ofy().transact(() -> ofy().save().entities(ofy().load().keys(batch).values())); + tm().transact(() -> ofy().save().entities(ofy().load().keys(batch).values())); System.out.printf("Re-saved entities batch: %s.\n", batch); } } diff --git a/core/src/main/java/google/registry/tools/UnrenewDomainCommand.java b/core/src/main/java/google/registry/tools/UnrenewDomainCommand.java index 385eee325..f49c267e6 100644 --- a/core/src/main/java/google/registry/tools/UnrenewDomainCommand.java +++ b/core/src/main/java/google/registry/tools/UnrenewDomainCommand.java @@ -21,6 +21,7 @@ import static google.registry.flows.domain.DomainFlowUtils.newAutorenewPollMessa import static google.registry.flows.domain.DomainFlowUtils.updateAutorenewRecurrenceEndTime; import static google.registry.model.EppResourceUtils.loadByForeignKey; import static google.registry.model.ofy.ObjectifyService.ofy; +import static google.registry.model.transaction.TransactionManagerFactory.tm; import static google.registry.util.DateTimeUtils.isBeforeOrAt; import static google.registry.util.DateTimeUtils.leapSafeSubtractYears; @@ -153,15 +154,15 @@ class UnrenewDomainCommand extends ConfirmingCommand implements CommandWithRemot @Override protected String execute() { for (String domainName : mainParameters) { - ofy().transact(() -> unrenewDomain(domainName)); + tm().transact(() -> unrenewDomain(domainName)); System.out.printf("Unrenewed %s\n", domainName); } return "Successfully unrenewed all domains."; } private void unrenewDomain(String domainName) { - ofy().assertInTransaction(); - DateTime now = ofy().getTransactionTime(); + tm().assertInTransaction(); + DateTime now = tm().getTransactionTime(); Optional domainOptional = loadByForeignKey(DomainBase.class, domainName, now); // Transactional sanity checks on the off chance that something changed between init() running diff --git a/core/src/main/java/google/registry/tools/UpdateAllocationTokensCommand.java b/core/src/main/java/google/registry/tools/UpdateAllocationTokensCommand.java index 171b9e760..b31fad518 100644 --- a/core/src/main/java/google/registry/tools/UpdateAllocationTokensCommand.java +++ b/core/src/main/java/google/registry/tools/UpdateAllocationTokensCommand.java @@ -19,6 +19,7 @@ import static com.google.common.collect.ImmutableSet.toImmutableSet; import static com.google.common.collect.Iterables.partition; import static com.google.common.collect.Streams.stream; import static google.registry.model.ofy.ObjectifyService.ofy; +import static google.registry.model.transaction.TransactionManagerFactory.tm; import com.beust.jcommander.Parameter; import com.beust.jcommander.Parameters; @@ -109,7 +110,7 @@ final class UpdateAllocationTokensCommand extends UpdateOrDeleteAllocationTokens protected String execute() { long numUpdated = stream(partition(tokensToSave, BATCH_SIZE)) - .mapToLong(batch -> ofy().transact(() -> saveBatch(batch))) + .mapToLong(batch -> tm().transact(() -> saveBatch(batch))) .sum(); return String.format("Updated %d tokens in total.", numUpdated); } diff --git a/core/src/main/java/google/registry/tools/server/DeleteEntityAction.java b/core/src/main/java/google/registry/tools/server/DeleteEntityAction.java index 157d0282f..cf96d81b0 100644 --- a/core/src/main/java/google/registry/tools/server/DeleteEntityAction.java +++ b/core/src/main/java/google/registry/tools/server/DeleteEntityAction.java @@ -17,6 +17,7 @@ package google.registry.tools.server; import static com.google.appengine.api.datastore.DatastoreServiceFactory.getDatastoreService; import static com.googlecode.objectify.Key.create; import static google.registry.model.ofy.ObjectifyService.ofy; +import static google.registry.model.transaction.TransactionManagerFactory.tm; import com.google.appengine.api.datastore.Entity; import com.google.appengine.api.datastore.EntityNotFoundException; @@ -94,7 +95,7 @@ public class DeleteEntityAction implements Runnable { getDatastoreService().delete(rawDeletions); // Delete ofy entities. final ImmutableList ofyDeletions = ofyDeletionsBuilder.build(); - ofy().transactNew(() -> ofy().delete().entities(ofyDeletions).now()); + tm().transactNew(() -> ofy().delete().entities(ofyDeletions).now()); String message = String.format( "Deleted %d raw entities and %d registered entities", rawDeletions.size(), diff --git a/core/src/main/java/google/registry/tools/server/KillAllEntitiesReducer.java b/core/src/main/java/google/registry/tools/server/KillAllEntitiesReducer.java index eb6a6ac9c..a99662b1a 100644 --- a/core/src/main/java/google/registry/tools/server/KillAllEntitiesReducer.java +++ b/core/src/main/java/google/registry/tools/server/KillAllEntitiesReducer.java @@ -16,6 +16,7 @@ package google.registry.tools.server; import static com.google.common.collect.Iterators.partition; import static google.registry.model.ofy.ObjectifyService.ofy; +import static google.registry.model.transaction.TransactionManagerFactory.tm; import com.google.appengine.tools.mapreduce.Reducer; import com.google.appengine.tools.mapreduce.ReducerInput; @@ -36,7 +37,7 @@ public class KillAllEntitiesReducer extends Reducer, Key, Void> { while (batches.hasNext()) { final List> batch = batches.next(); // Use a transaction to get retrying for free. - ofy().transact(() -> ofy().deleteWithoutBackup().keys(batch)); + tm().transact(() -> ofy().deleteWithoutBackup().keys(batch)); getContext().incrementCounter("entities deleted", batch.size()); for (Key key : batch) { getContext().incrementCounter(String.format("%s deleted", key.getKind())); diff --git a/core/src/main/java/google/registry/tools/server/ResaveAllHistoryEntriesAction.java b/core/src/main/java/google/registry/tools/server/ResaveAllHistoryEntriesAction.java index 6f48430f9..24cb7529d 100644 --- a/core/src/main/java/google/registry/tools/server/ResaveAllHistoryEntriesAction.java +++ b/core/src/main/java/google/registry/tools/server/ResaveAllHistoryEntriesAction.java @@ -15,6 +15,7 @@ package google.registry.tools.server; import static google.registry.model.ofy.ObjectifyService.ofy; +import static google.registry.model.transaction.TransactionManagerFactory.tm; import com.google.appengine.tools.mapreduce.Mapper; import com.google.common.collect.ImmutableList; @@ -68,7 +69,7 @@ public class ResaveAllHistoryEntriesAction implements Runnable { @Override public final void map(final HistoryEntry historyEntry) { - ofy().transact(() -> ofy().save().entity(ofy().load().entity(historyEntry).now()).now()); + tm().transact(() -> ofy().save().entity(ofy().load().entity(historyEntry).now()).now()); getContext().incrementCounter( String.format( "HistoryEntries parented under %s re-saved", historyEntry.getParent().getKind())); diff --git a/core/src/main/java/google/registry/ui/server/registrar/ConsoleRegistrarCreatorAction.java b/core/src/main/java/google/registry/ui/server/registrar/ConsoleRegistrarCreatorAction.java index c3071e7ae..83098c812 100644 --- a/core/src/main/java/google/registry/ui/server/registrar/ConsoleRegistrarCreatorAction.java +++ b/core/src/main/java/google/registry/ui/server/registrar/ConsoleRegistrarCreatorAction.java @@ -22,6 +22,7 @@ import static com.google.common.net.HttpHeaders.LOCATION; import static com.google.common.net.HttpHeaders.X_FRAME_OPTIONS; import static google.registry.model.common.GaeUserIdConverter.convertEmailAddressToGaeUserId; import static google.registry.model.ofy.ObjectifyService.ofy; +import static google.registry.model.transaction.TransactionManagerFactory.tm; import static javax.servlet.http.HttpServletResponse.SC_FORBIDDEN; import static javax.servlet.http.HttpServletResponse.SC_MOVED_TEMPORARILY; @@ -294,7 +295,7 @@ public final class ConsoleRegistrarCreatorAction implements Runnable { .setEmailAddress(consoleUserEmail.get()) .setGaeUserId(gaeUserId) .build(); - ofy() + tm() .transact( () -> { checkState( diff --git a/core/src/main/java/google/registry/ui/server/registrar/RegistrarSettingsAction.java b/core/src/main/java/google/registry/ui/server/registrar/RegistrarSettingsAction.java index f63d0891d..4a4e68c6c 100644 --- a/core/src/main/java/google/registry/ui/server/registrar/RegistrarSettingsAction.java +++ b/core/src/main/java/google/registry/ui/server/registrar/RegistrarSettingsAction.java @@ -21,6 +21,7 @@ import static com.google.common.collect.Sets.difference; import static google.registry.config.RegistryEnvironment.PRODUCTION; import static google.registry.export.sheet.SyncRegistrarsSheetAction.enqueueRegistrarSheetSync; import static google.registry.model.ofy.ObjectifyService.ofy; +import static google.registry.model.transaction.TransactionManagerFactory.tm; import static google.registry.security.JsonResponseHelper.Status.ERROR; import static google.registry.security.JsonResponseHelper.Status.SUCCESS; import static google.registry.util.PreconditionsUtils.checkArgumentPresent; @@ -174,7 +175,7 @@ public class RegistrarSettingsAction implements Runnable, JsonActionRunner.JsonA } private RegistrarResult update(final Map args, String clientId) { - return ofy() + return tm() .transact( () -> { // We load the registrar here rather than outside of the transaction - to make @@ -302,12 +303,12 @@ public class RegistrarSettingsAction implements Runnable, JsonActionRunner.JsonA RegistrarFormFields.CLIENT_CERTIFICATE_FIELD .extractUntyped(args) .ifPresent( - certificate -> builder.setClientCertificate(certificate, ofy().getTransactionTime())); + certificate -> builder.setClientCertificate(certificate, tm().getTransactionTime())); RegistrarFormFields.FAILOVER_CLIENT_CERTIFICATE_FIELD .extractUntyped(args) .ifPresent( certificate -> - builder.setFailoverClientCertificate(certificate, ofy().getTransactionTime())); + builder.setFailoverClientCertificate(certificate, tm().getTransactionTime())); return checkNotChangedUnlessAllowed(builder, initialRegistrar, Role.OWNER); } diff --git a/core/src/test/java/google/registry/backup/CommitLogCheckpointStrategyTest.java b/core/src/test/java/google/registry/backup/CommitLogCheckpointStrategyTest.java index ce91a46a9..a31d31849 100644 --- a/core/src/test/java/google/registry/backup/CommitLogCheckpointStrategyTest.java +++ b/core/src/test/java/google/registry/backup/CommitLogCheckpointStrategyTest.java @@ -27,8 +27,10 @@ import com.google.common.collect.ImmutableMap; import google.registry.model.common.Cursor; import google.registry.model.ofy.CommitLogBucket; import google.registry.model.ofy.CommitLogCheckpoint; +import google.registry.model.ofy.DatastoreTransactionManager; import google.registry.model.ofy.Ofy; import google.registry.model.registry.Registry; +import google.registry.model.transaction.TransactionManager; import google.registry.testing.AppEngineRule; import google.registry.testing.FakeClock; import google.registry.testing.InjectRule; @@ -54,6 +56,7 @@ public class CommitLogCheckpointStrategyTest { final FakeClock clock = new FakeClock(DateTime.parse("2000-01-01TZ")); final Ofy ofy = new Ofy(clock); + final TransactionManager tm = new DatastoreTransactionManager(ofy); final CommitLogCheckpointStrategy strategy = new CommitLogCheckpointStrategy(); /** @@ -289,17 +292,17 @@ public class CommitLogCheckpointStrategyTest { private void writeCommitLogToBucket(final int bucketId) { fakeBucketIdSupplier.value = bucketId; - ofy.transact( + tm.transact( () -> { Cursor cursor = - Cursor.create(RDE_REPORT, ofy.getTransactionTime(), Registry.get("tld" + bucketId)); + Cursor.create(RDE_REPORT, tm.getTransactionTime(), Registry.get("tld" + bucketId)); ofy().save().entity(cursor); }); fakeBucketIdSupplier.value = null; } private void saveBucketWithLastWrittenTime(final int bucketId, final DateTime lastWrittenTime) { - ofy.transact( + tm.transact( () -> ofy.saveWithoutBackup() .entity( diff --git a/core/src/test/java/google/registry/batch/ExpandRecurringBillingEventsActionTest.java b/core/src/test/java/google/registry/batch/ExpandRecurringBillingEventsActionTest.java index 7362fb5b9..ce77a7fa1 100644 --- a/core/src/test/java/google/registry/batch/ExpandRecurringBillingEventsActionTest.java +++ b/core/src/test/java/google/registry/batch/ExpandRecurringBillingEventsActionTest.java @@ -19,6 +19,7 @@ import static google.registry.model.common.Cursor.CursorType.RECURRING_BILLING; import static google.registry.model.domain.Period.Unit.YEARS; import static google.registry.model.ofy.ObjectifyService.ofy; import static google.registry.model.reporting.HistoryEntry.Type.DOMAIN_AUTORENEW; +import static google.registry.model.transaction.TransactionManagerFactory.tm; import static google.registry.testing.DatastoreHelper.assertBillingEvents; import static google.registry.testing.DatastoreHelper.assertBillingEventsForResource; import static google.registry.testing.DatastoreHelper.createTld; @@ -101,7 +102,7 @@ public class ExpandRecurringBillingEventsActionTest } void saveCursor(final DateTime cursorTime) { - ofy().transact(() -> ofy().save().entity(Cursor.createGlobal(RECURRING_BILLING, cursorTime))); + tm().transact(() -> ofy().save().entity(Cursor.createGlobal(RECURRING_BILLING, cursorTime))); } void runMapreduce() throws Exception { diff --git a/core/src/test/java/google/registry/flows/custom/TestDomainCreateFlowCustomLogic.java b/core/src/test/java/google/registry/flows/custom/TestDomainCreateFlowCustomLogic.java index ac00748c1..fb2451386 100644 --- a/core/src/test/java/google/registry/flows/custom/TestDomainCreateFlowCustomLogic.java +++ b/core/src/test/java/google/registry/flows/custom/TestDomainCreateFlowCustomLogic.java @@ -14,7 +14,7 @@ package google.registry.flows.custom; -import static google.registry.model.ofy.ObjectifyService.ofy; +import static google.registry.model.transaction.TransactionManagerFactory.tm; import google.registry.flows.FlowMetadata; import google.registry.flows.SessionMetadata; @@ -35,7 +35,7 @@ public class TestDomainCreateFlowCustomLogic extends DomainCreateFlowCustomLogic PollMessage extraPollMessage = new PollMessage.OneTime.Builder() .setParent(parameters.historyEntry()) - .setEventTime(ofy().getTransactionTime()) + .setEventTime(tm().getTransactionTime()) .setClientId(getSessionMetadata().getClientId()) .setMsg("Custom logic was triggered") .build(); diff --git a/core/src/test/java/google/registry/model/CreateAutoTimestampTest.java b/core/src/test/java/google/registry/model/CreateAutoTimestampTest.java index 59e198dbd..b361c7185 100644 --- a/core/src/test/java/google/registry/model/CreateAutoTimestampTest.java +++ b/core/src/test/java/google/registry/model/CreateAutoTimestampTest.java @@ -16,6 +16,7 @@ package google.registry.model; import static com.google.common.truth.Truth.assertThat; import static google.registry.model.ofy.ObjectifyService.ofy; +import static google.registry.model.transaction.TransactionManagerFactory.tm; import static org.joda.time.DateTimeZone.UTC; import com.googlecode.objectify.ObjectifyService; @@ -56,13 +57,13 @@ public class CreateAutoTimestampTest { @Test public void testSaveSetsTime() { DateTime transactionTime = - ofy() + tm() .transact( () -> { TestObject object = new TestObject(); assertThat(object.createTime.getTimestamp()).isNull(); ofy().save().entity(object); - return ofy().getTransactionTime(); + return tm().getTransactionTime(); }); ofy().clearSessionCache(); assertThat(reload().createTime.timestamp).isEqualTo(transactionTime); @@ -71,7 +72,7 @@ public class CreateAutoTimestampTest { @Test public void testResavingRespectsOriginalTime() { final DateTime oldCreateTime = DateTime.now(UTC).minusDays(1); - ofy() + tm() .transact( () -> { TestObject object = new TestObject(); diff --git a/core/src/test/java/google/registry/model/UpdateAutoTimestampTest.java b/core/src/test/java/google/registry/model/UpdateAutoTimestampTest.java index 00be0f9c2..3236d2039 100644 --- a/core/src/test/java/google/registry/model/UpdateAutoTimestampTest.java +++ b/core/src/test/java/google/registry/model/UpdateAutoTimestampTest.java @@ -16,6 +16,7 @@ package google.registry.model; import static com.google.common.truth.Truth.assertThat; import static google.registry.model.ofy.ObjectifyService.ofy; +import static google.registry.model.transaction.TransactionManagerFactory.tm; import static org.joda.time.DateTimeZone.UTC; import com.googlecode.objectify.ObjectifyService; @@ -56,13 +57,13 @@ public class UpdateAutoTimestampTest { @Test public void testSaveSetsTime() { DateTime transactionTime = - ofy() + tm() .transact( () -> { TestObject object = new TestObject(); assertThat(object.updateTime.timestamp).isNull(); ofy().save().entity(object); - return ofy().getTransactionTime(); + return tm().getTransactionTime(); }); ofy().clearSessionCache(); assertThat(reload().updateTime.timestamp).isEqualTo(transactionTime); @@ -71,13 +72,13 @@ public class UpdateAutoTimestampTest { @Test public void testResavingOverwritesOriginalTime() { DateTime transactionTime = - ofy() + tm() .transact( () -> { TestObject object = new TestObject(); object.updateTime = UpdateAutoTimestamp.create(DateTime.now(UTC).minusDays(1)); ofy().save().entity(object); - return ofy().getTransactionTime(); + return tm().getTransactionTime(); }); ofy().clearSessionCache(); assertThat(reload().updateTime.timestamp).isEqualTo(transactionTime); diff --git a/core/src/test/java/google/registry/model/common/CursorTest.java b/core/src/test/java/google/registry/model/common/CursorTest.java index 2a87f8c7d..c20dcfc15 100644 --- a/core/src/test/java/google/registry/model/common/CursorTest.java +++ b/core/src/test/java/google/registry/model/common/CursorTest.java @@ -19,6 +19,7 @@ import static google.registry.model.common.Cursor.CursorType.BRDA; import static google.registry.model.common.Cursor.CursorType.RDE_UPLOAD; import static google.registry.model.common.Cursor.CursorType.RECURRING_BILLING; import static google.registry.model.ofy.ObjectifyService.ofy; +import static google.registry.model.transaction.TransactionManagerFactory.tm; import static google.registry.testing.DatastoreHelper.createTld; import static google.registry.testing.DatastoreHelper.persistActiveDomain; import static google.registry.testing.JUnitBackports.assertThrows; @@ -38,7 +39,7 @@ public class CursorTest extends EntityTestCase { createTld("tld"); clock.advanceOneMilli(); final DateTime time = DateTime.parse("2012-07-12T03:30:00.000Z"); - ofy().transact(() -> ofy().save().entity(Cursor.create(RDE_UPLOAD, time, Registry.get("tld")))); + tm().transact(() -> ofy().save().entity(Cursor.create(RDE_UPLOAD, time, Registry.get("tld")))); assertThat(ofy().load().key(Cursor.createKey(BRDA, Registry.get("tld"))).now()).isNull(); assertThat( ofy() @@ -52,7 +53,7 @@ public class CursorTest extends EntityTestCase { @Test public void testSuccess_persistGlobalCursor() { final DateTime time = DateTime.parse("2012-07-12T03:30:00.000Z"); - ofy().transact(() -> ofy().save().entity(Cursor.createGlobal(RECURRING_BILLING, time))); + tm().transact(() -> ofy().save().entity(Cursor.createGlobal(RECURRING_BILLING, time))); assertThat(ofy().load().key(Cursor.createGlobalKey(RECURRING_BILLING)).now().getCursorTime()) .isEqualTo(time); } @@ -60,7 +61,7 @@ public class CursorTest extends EntityTestCase { @Test public void testIndexing() throws Exception { final DateTime time = DateTime.parse("2012-07-12T03:30:00.000Z"); - ofy().transact(() -> ofy().save().entity(Cursor.createGlobal(RECURRING_BILLING, time))); + tm().transact(() -> ofy().save().entity(Cursor.createGlobal(RECURRING_BILLING, time))); Cursor cursor = ofy().load().key(Cursor.createGlobalKey(RECURRING_BILLING)).now(); verifyIndexing(cursor); } @@ -75,7 +76,7 @@ public class CursorTest extends EntityTestCase { assertThrows( IllegalArgumentException.class, () -> - ofy().transact(() -> ofy().save().entity(Cursor.create(RDE_UPLOAD, time, domain)))); + tm().transact(() -> ofy().save().entity(Cursor.create(RDE_UPLOAD, time, domain)))); assertThat(thrown) .hasMessageThat() .contains("Class required for cursor does not match scope class"); diff --git a/core/src/test/java/google/registry/model/common/GaeUserIdConverterTest.java b/core/src/test/java/google/registry/model/common/GaeUserIdConverterTest.java index 8d5094702..802b9094a 100644 --- a/core/src/test/java/google/registry/model/common/GaeUserIdConverterTest.java +++ b/core/src/test/java/google/registry/model/common/GaeUserIdConverterTest.java @@ -16,6 +16,7 @@ package google.registry.model.common; import static com.google.common.truth.Truth.assertThat; import static google.registry.model.ofy.ObjectifyService.ofy; +import static google.registry.model.transaction.TransactionManagerFactory.tm; import google.registry.testing.AppEngineRule; import org.junit.After; @@ -46,7 +47,7 @@ public class GaeUserIdConverterTest { @Test public void testSuccess_inTransaction() { - ofy() + tm() .transactNew( () -> assertThat(GaeUserIdConverter.convertEmailAddressToGaeUserId("example@example.com")) diff --git a/core/src/test/java/google/registry/model/ofy/CommitLogMutationTest.java b/core/src/test/java/google/registry/model/ofy/CommitLogMutationTest.java index 1bf68f403..45ae24a8f 100644 --- a/core/src/test/java/google/registry/model/ofy/CommitLogMutationTest.java +++ b/core/src/test/java/google/registry/model/ofy/CommitLogMutationTest.java @@ -16,6 +16,7 @@ package google.registry.model.ofy; import static com.google.common.truth.Truth.assertThat; import static google.registry.model.ofy.ObjectifyService.ofy; +import static google.registry.model.transaction.TransactionManagerFactory.tm; import static google.registry.testing.DatastoreHelper.createTld; import com.google.appengine.api.datastore.Entity; @@ -69,7 +70,7 @@ public class CommitLogMutationTest { Entity rawEntity = convertToEntityInTxn(someObject); // Needs to be in a transaction so that registry-saving-to-entity will work. CommitLogMutation mutation = - ofy().transact(() -> CommitLogMutation.create(manifestKey, someObject)); + tm().transact(() -> CommitLogMutation.create(manifestKey, someObject)); assertThat(Key.create(mutation)) .isEqualTo(CommitLogMutation.createKey(manifestKey, Key.create(someObject))); assertThat(mutation.getEntity()).isEqualTo(rawEntity); @@ -89,6 +90,6 @@ public class CommitLogMutationTest { } private static Entity convertToEntityInTxn(final ImmutableObject object) { - return ofy().transact(() -> ofy().save().toEntity(object)); + return tm().transact(() -> ofy().save().toEntity(object)); } } diff --git a/core/src/test/java/google/registry/model/ofy/OfyCommitLogTest.java b/core/src/test/java/google/registry/model/ofy/OfyCommitLogTest.java index b92653f2b..5d4792972 100644 --- a/core/src/test/java/google/registry/model/ofy/OfyCommitLogTest.java +++ b/core/src/test/java/google/registry/model/ofy/OfyCommitLogTest.java @@ -20,6 +20,7 @@ import static com.googlecode.objectify.ObjectifyService.register; import static google.registry.model.common.EntityGroupRoot.getCrossTldKey; import static google.registry.model.ofy.CommitLogBucket.getBucketKey; import static google.registry.model.ofy.ObjectifyService.ofy; +import static google.registry.model.transaction.TransactionManagerFactory.tm; import static google.registry.testing.JUnitBackports.assertThrows; import com.google.common.collect.ImmutableSet; @@ -64,13 +65,13 @@ public class OfyCommitLogTest { @Test public void testTransact_doesNothing_noCommitLogIsSaved() { - ofy().transact(() -> {}); + tm().transact(() -> {}); assertThat(ofy().load().type(CommitLogManifest.class)).isEmpty(); } @Test public void testTransact_savesDataAndCommitLog() { - ofy().transact(() -> ofy().save().entity(Root.create(1, getCrossTldKey())).now()); + tm().transact(() -> ofy().save().entity(Root.create(1, getCrossTldKey())).now()); assertThat(ofy().load().key(Key.create(getCrossTldKey(), Root.class, 1)).now().value) .isEqualTo("value"); assertThat(ofy().load().type(CommitLogManifest.class)).hasSize(1); @@ -79,7 +80,7 @@ public class OfyCommitLogTest { @Test public void testTransact_saveWithoutBackup_noCommitLogIsSaved() { - ofy().transact(() -> ofy().saveWithoutBackup().entity(Root.create(1, getCrossTldKey())).now()); + tm().transact(() -> ofy().saveWithoutBackup().entity(Root.create(1, getCrossTldKey())).now()); assertThat(ofy().load().key(Key.create(getCrossTldKey(), Root.class, 1)).now().value) .isEqualTo("value"); assertThat(ofy().load().type(CommitLogManifest.class)).isEmpty(); @@ -88,8 +89,8 @@ public class OfyCommitLogTest { @Test public void testTransact_deleteWithoutBackup_noCommitLogIsSaved() { - ofy().transact(() -> ofy().saveWithoutBackup().entity(Root.create(1, getCrossTldKey())).now()); - ofy().transact(() -> ofy().deleteWithoutBackup().key(Key.create(Root.class, 1))); + tm().transact(() -> ofy().saveWithoutBackup().entity(Root.create(1, getCrossTldKey())).now()); + tm().transact(() -> ofy().deleteWithoutBackup().key(Key.create(Root.class, 1))); assertThat(ofy().load().key(Key.create(Root.class, 1)).now()).isNull(); assertThat(ofy().load().type(CommitLogManifest.class)).isEmpty(); assertThat(ofy().load().type(CommitLogMutation.class)).isEmpty(); @@ -97,12 +98,12 @@ public class OfyCommitLogTest { @Test public void testTransact_savesEntity_itsProtobufFormIsStoredInCommitLog() { - ofy().transact(() -> ofy().save().entity(Root.create(1, getCrossTldKey())).now()); + tm().transact(() -> ofy().save().entity(Root.create(1, getCrossTldKey())).now()); final byte[] entityProtoBytes = ofy().load().type(CommitLogMutation.class).first().now().entityProtoBytes; // This transaction is needed so that save().toEntity() can access ofy().getTransactionTime() // when it attempts to set the update timestamp. - ofy() + tm() .transact( () -> assertThat(entityProtoBytes) @@ -113,7 +114,7 @@ public class OfyCommitLogTest { @Test public void testTransact_savesEntity_mutationIsChildOfManifest() { - ofy().transact(() -> ofy().save().entity(Root.create(1, getCrossTldKey())).now()); + tm().transact(() -> ofy().save().entity(Root.create(1, getCrossTldKey())).now()); assertThat( ofy() .load() @@ -124,7 +125,7 @@ public class OfyCommitLogTest { @Test public void testTransactNew_savesDataAndCommitLog() { - ofy().transactNew(() -> ofy().save().entity(Root.create(1, getCrossTldKey())).now()); + tm().transactNew(() -> ofy().save().entity(Root.create(1, getCrossTldKey())).now()); assertThat(ofy().load().key(Key.create(getCrossTldKey(), Root.class, 1)).now().value) .isEqualTo("value"); assertThat(ofy().load().type(CommitLogManifest.class)).hasSize(1); @@ -133,7 +134,7 @@ public class OfyCommitLogTest { @Test public void testTransact_multipleSaves_logsMultipleMutations() { - ofy() + tm() .transact( () -> { ofy().save().entity(Root.create(1, getCrossTldKey())).now(); @@ -145,10 +146,10 @@ public class OfyCommitLogTest { @Test public void testTransact_deletion_deletesAndLogsWithoutMutation() { - ofy().transact(() -> ofy().saveWithoutBackup().entity(Root.create(1, getCrossTldKey())).now()); + tm().transact(() -> ofy().saveWithoutBackup().entity(Root.create(1, getCrossTldKey())).now()); clock.advanceOneMilli(); final Key otherTldKey = Key.create(getCrossTldKey(), Root.class, 1); - ofy().transact(() -> ofy().delete().key(otherTldKey)); + tm().transact(() -> ofy().delete().key(otherTldKey)); assertThat(ofy().load().key(otherTldKey).now()).isNull(); assertThat(ofy().load().type(CommitLogManifest.class)).hasSize(1); assertThat(ofy().load().type(CommitLogMutation.class)).isEmpty(); @@ -163,7 +164,7 @@ public class OfyCommitLogTest { IllegalArgumentException thrown = assertThrows( IllegalArgumentException.class, - () -> ofy().transactNew(() -> ofy().delete().entity(backupsArentAllowedOnMe))); + () -> tm().transactNew(() -> ofy().delete().entity(backupsArentAllowedOnMe))); assertThat(thrown).hasMessageThat().contains("Can't save/delete a @NotBackedUp"); } @@ -174,7 +175,7 @@ public class OfyCommitLogTest { IllegalArgumentException thrown = assertThrows( IllegalArgumentException.class, - () -> ofy().transactNew(() -> ofy().save().entity(backupsArentAllowedOnMe))); + () -> tm().transactNew(() -> ofy().save().entity(backupsArentAllowedOnMe))); assertThat(thrown).hasMessageThat().contains("Can't save/delete a @NotBackedUp"); } @@ -184,7 +185,7 @@ public class OfyCommitLogTest { IllegalArgumentException thrown = assertThrows( IllegalArgumentException.class, - () -> ofy().transactNew(() -> ofy().delete().key(virtualEntityKey))); + () -> tm().transactNew(() -> ofy().delete().key(virtualEntityKey))); assertThat(thrown).hasMessageThat().contains("Can't save/delete a @VirtualEntity"); } @@ -194,7 +195,7 @@ public class OfyCommitLogTest { IllegalArgumentException thrown = assertThrows( IllegalArgumentException.class, - () -> ofy().transactNew(() -> ofy().save().entity(virtualEntity))); + () -> tm().transactNew(() -> ofy().save().entity(virtualEntity))); assertThat(thrown).hasMessageThat().contains("Can't save/delete a @VirtualEntity"); } @@ -223,7 +224,7 @@ public class OfyCommitLogTest { assertThrows( IllegalArgumentException.class, () -> - ofy() + tm() .transact( () -> { ofy().save().entity(Root.create(1, getCrossTldKey())); @@ -238,7 +239,7 @@ public class OfyCommitLogTest { assertThrows( IllegalArgumentException.class, () -> - ofy() + tm() .transact( () -> { ofy().save().entity(Root.create(1, getCrossTldKey())); @@ -249,12 +250,12 @@ public class OfyCommitLogTest { @Test public void testSavingRootAndChild_updatesTimestampOnBackupGroupRoot() { - ofy().transact(() -> ofy().save().entity(Root.create(1, getCrossTldKey()))); + tm().transact(() -> ofy().save().entity(Root.create(1, getCrossTldKey()))); ofy().clearSessionCache(); assertThat(ofy().load().key(Key.create(getCrossTldKey(), Root.class, 1)).now() .getUpdateAutoTimestamp().getTimestamp()).isEqualTo(clock.nowUtc()); clock.advanceOneMilli(); - ofy() + tm() .transact( () -> { ofy().save().entity(Root.create(1, getCrossTldKey())); @@ -267,12 +268,12 @@ public class OfyCommitLogTest { @Test public void testSavingOnlyChild_updatesTimestampOnBackupGroupRoot() { - ofy().transact(() -> ofy().save().entity(Root.create(1, getCrossTldKey()))); + tm().transact(() -> ofy().save().entity(Root.create(1, getCrossTldKey()))); ofy().clearSessionCache(); assertThat(ofy().load().key(Key.create(getCrossTldKey(), Root.class, 1)).now() .getUpdateAutoTimestamp().getTimestamp()).isEqualTo(clock.nowUtc()); clock.advanceOneMilli(); - ofy().transact(() -> ofy().save().entity(new Child())); + tm().transact(() -> ofy().save().entity(new Child())); ofy().clearSessionCache(); assertThat(ofy().load().key(Key.create(getCrossTldKey(), Root.class, 1)).now() .getUpdateAutoTimestamp().getTimestamp()).isEqualTo(clock.nowUtc()); @@ -280,13 +281,13 @@ public class OfyCommitLogTest { @Test public void testDeletingChild_updatesTimestampOnBackupGroupRoot() { - ofy().transact(() -> ofy().save().entity(Root.create(1, getCrossTldKey()))); + tm().transact(() -> ofy().save().entity(Root.create(1, getCrossTldKey()))); ofy().clearSessionCache(); assertThat(ofy().load().key(Key.create(getCrossTldKey(), Root.class, 1)).now() .getUpdateAutoTimestamp().getTimestamp()).isEqualTo(clock.nowUtc()); clock.advanceOneMilli(); // The fact that the child was never persisted is irrelevant. - ofy().transact(() -> ofy().delete().entity(new Child())); + tm().transact(() -> ofy().delete().entity(new Child())); ofy().clearSessionCache(); assertThat(ofy().load().key(Key.create(getCrossTldKey(), Root.class, 1)).now() .getUpdateAutoTimestamp().getTimestamp()).isEqualTo(clock.nowUtc()); @@ -294,12 +295,12 @@ public class OfyCommitLogTest { @Test public void testReadingRoot_doesntUpdateTimestamp() { - ofy().transact(() -> ofy().save().entity(Root.create(1, getCrossTldKey()))); + tm().transact(() -> ofy().save().entity(Root.create(1, getCrossTldKey()))); ofy().clearSessionCache(); assertThat(ofy().load().key(Key.create(getCrossTldKey(), Root.class, 1)).now() .getUpdateAutoTimestamp().getTimestamp()).isEqualTo(clock.nowUtc()); clock.advanceOneMilli(); - ofy() + tm() .transact( () -> { // Don't remove this line, as without saving *something* the commit log code will @@ -314,12 +315,12 @@ public class OfyCommitLogTest { @Test public void testReadingChild_doesntUpdateTimestampOnBackupGroupRoot() { - ofy().transact(() -> ofy().save().entity(Root.create(1, getCrossTldKey()))); + tm().transact(() -> ofy().save().entity(Root.create(1, getCrossTldKey()))); ofy().clearSessionCache(); assertThat(ofy().load().key(Key.create(getCrossTldKey(), Root.class, 1)).now() .getUpdateAutoTimestamp().getTimestamp()).isEqualTo(clock.nowUtc()); clock.advanceOneMilli(); - ofy() + tm() .transact( () -> { // Don't remove this line, as without saving *something* the commit log code will @@ -335,7 +336,7 @@ public class OfyCommitLogTest { @Test public void testSavingAcrossBackupGroupRoots_updatesCorrectTimestamps() { // Create three roots. - ofy() + tm() .transact( () -> { ofy().save().entity(Root.create(1, getCrossTldKey())); @@ -349,7 +350,7 @@ public class OfyCommitLogTest { } clock.advanceOneMilli(); // Mutate one root, and a child of a second, ignoring the third. - ofy() + tm() .transact( () -> { ofy().save().entity(new Child()); // All Child objects are under Root(1). diff --git a/core/src/test/java/google/registry/model/ofy/OfyTest.java b/core/src/test/java/google/registry/model/ofy/OfyTest.java index 7cb2d4b97..f84224ca5 100644 --- a/core/src/test/java/google/registry/model/ofy/OfyTest.java +++ b/core/src/test/java/google/registry/model/ofy/OfyTest.java @@ -20,6 +20,7 @@ import static com.google.common.util.concurrent.Uninterruptibles.sleepUninterrup import static google.registry.model.common.EntityGroupRoot.getCrossTldKey; import static google.registry.model.ofy.ObjectifyService.ofy; import static google.registry.model.ofy.Ofy.getBaseEntityClassFromEntityOrKey; +import static google.registry.model.transaction.TransactionManagerFactory.tm; import static google.registry.testing.DatastoreHelper.createTld; import static google.registry.testing.DatastoreHelper.newContactResource; import static google.registry.testing.DatastoreHelper.persistActiveContact; @@ -35,8 +36,6 @@ import com.google.appengine.api.datastore.DatastoreTimeoutException; import com.google.appengine.api.datastore.Entity; import com.google.appengine.api.taskqueue.TransientFailureException; import com.googlecode.objectify.Key; -import com.googlecode.objectify.VoidWork; -import com.googlecode.objectify.Work; import com.googlecode.objectify.annotation.Id; import com.googlecode.objectify.annotation.OnLoad; import com.googlecode.objectify.annotation.OnSave; @@ -46,6 +45,7 @@ import google.registry.model.contact.ContactResource; import google.registry.model.domain.DomainBase; import google.registry.model.eppcommon.Trid; import google.registry.model.reporting.HistoryEntry; +import google.registry.model.transaction.TransactionManager.Work; import google.registry.testing.AppEngineRule; import google.registry.testing.DatastoreHelper; import google.registry.testing.FakeClock; @@ -114,7 +114,7 @@ public class OfyTest { assertThrows( IllegalArgumentException.class, () -> - ofy() + tm() .transact( () -> { ofy().save().entity(someObject); @@ -129,7 +129,7 @@ public class OfyTest { assertThrows( IllegalArgumentException.class, () -> - ofy() + tm() .transact( () -> { ofy().delete().entity(someObject); @@ -144,7 +144,7 @@ public class OfyTest { assertThrows( IllegalArgumentException.class, () -> - ofy() + tm() .transact( () -> { ofy().save().entity(someObject); @@ -159,7 +159,7 @@ public class OfyTest { assertThrows( IllegalArgumentException.class, () -> - ofy() + tm() .transact( () -> { ofy().delete().entity(someObject); @@ -172,7 +172,7 @@ public class OfyTest { public void testSavingKeyTwiceInOneCall() { assertThrows( IllegalArgumentException.class, - () -> ofy().transact(() -> ofy().save().entities(someObject, someObject))); + () -> tm().transact(() -> ofy().save().entities(someObject, someObject))); } /** Simple entity class with lifecycle callbacks. */ @@ -212,7 +212,7 @@ public class OfyTest { public void testLifecycleCallbacks_loadFromDatastore() { ofy().factory().register(LifecycleObject.class); final LifecycleObject object = new LifecycleObject(); - ofy().transact(() -> ofy().save().entity(object).now()); + tm().transact(() -> ofy().save().entity(object).now()); assertThat(object.onSaveCalled).isTrue(); ofy().clearSessionCache(); assertThat(ofy().load().entity(object).now().onLoadCalled).isTrue(); @@ -221,25 +221,25 @@ public class OfyTest { /** Avoid regressions of b/21309102 where transaction time did not change on each retry. */ @Test public void testTransact_getsNewTimestampOnEachTry() { - ofy().transact(new VoidWork() { + tm().transact(new Runnable() { DateTime firstAttemptTime; @Override - public void vrun() { + public void run() { if (firstAttemptTime == null) { // Sleep a bit to ensure that the next attempt is at a new millisecond. - firstAttemptTime = ofy().getTransactionTime(); + firstAttemptTime = tm().getTransactionTime(); sleepUninterruptibly(10, MILLISECONDS); throw new ConcurrentModificationException(); } - assertThat(ofy().getTransactionTime()).isGreaterThan(firstAttemptTime); + assertThat(tm().getTransactionTime()).isGreaterThan(firstAttemptTime); }}); } @Test public void testTransact_transientFailureException_retries() { - assertThat(ofy().transact(new Work() { + assertThat(tm().transact(new Work() { int count = 0; @@ -255,7 +255,7 @@ public class OfyTest { @Test public void testTransact_datastoreTimeoutException_noManifest_retries() { - assertThat(ofy().transact(new Work() { + assertThat(tm().transact(new Work() { int count = 0; @@ -273,7 +273,7 @@ public class OfyTest { @Test public void testTransact_datastoreTimeoutException_manifestNotWrittenToDatastore_retries() { - assertThat(ofy().transact(new Work() { + assertThat(tm().transact(new Work() { int count = 0; @@ -292,17 +292,18 @@ public class OfyTest { @Test public void testTransact_datastoreTimeoutException_manifestWrittenToDatastore_returnsSuccess() { // A work unit that throws if it is ever retried. - VoidWork work = new VoidWork() { + Work work = new Work() { boolean firstCallToVrun = true; @Override - public void vrun() { + public Void run() { if (firstCallToVrun) { firstCallToVrun = false; ofy().save().entity(someObject); - return; + return null; } fail("Shouldn't have retried."); + return null; }}; // A commit logged work that throws on the first attempt to get its result. CommitLoggedWork commitLoggedWork = new CommitLoggedWork(work, new SystemClock()) { @@ -322,7 +323,7 @@ public class OfyTest { } void doReadOnlyRetryTest(final RuntimeException e) { - assertThat(ofy().transactNewReadOnly(new Work() { + assertThat(tm().transactNewReadOnly(new Work() { int count = 0; diff --git a/core/src/test/java/google/registry/model/rde/RdeRevisionTest.java b/core/src/test/java/google/registry/model/rde/RdeRevisionTest.java index 924f02576..d0352aeab 100644 --- a/core/src/test/java/google/registry/model/rde/RdeRevisionTest.java +++ b/core/src/test/java/google/registry/model/rde/RdeRevisionTest.java @@ -19,6 +19,7 @@ import static google.registry.model.ofy.ObjectifyService.ofy; import static google.registry.model.rde.RdeMode.FULL; import static google.registry.model.rde.RdeRevision.getNextRevision; import static google.registry.model.rde.RdeRevision.saveRevision; +import static google.registry.model.transaction.TransactionManagerFactory.tm; import static google.registry.testing.JUnitBackports.assertThrows; import com.google.common.base.VerifyException; @@ -50,8 +51,8 @@ public class RdeRevisionTest { @Test public void testSaveRevision_objectDoesntExist_newRevisionIsZero_nextRevIsOne() { - ofy().transact(() -> saveRevision("despondency", DateTime.parse("1984-12-18TZ"), FULL, 0)); - ofy() + tm().transact(() -> saveRevision("despondency", DateTime.parse("1984-12-18TZ"), FULL, 0)); + tm() .transact( () -> assertThat(getNextRevision("despondency", DateTime.parse("1984-12-18TZ"), FULL)) @@ -64,7 +65,7 @@ public class RdeRevisionTest { assertThrows( VerifyException.class, () -> - ofy() + tm() .transact( () -> saveRevision("despondency", DateTime.parse("1984-12-18TZ"), FULL, 1))); @@ -78,7 +79,7 @@ public class RdeRevisionTest { assertThrows( VerifyException.class, () -> - ofy() + tm() .transact( () -> saveRevision("melancholy", DateTime.parse("1984-12-18TZ"), FULL, 0))); assertThat(thrown).hasMessageThat().contains("object already created"); @@ -87,8 +88,8 @@ public class RdeRevisionTest { @Test public void testSaveRevision_objectExistsAtZero_newRevisionIsOne_nextRevIsTwo() { save("melancholy", DateTime.parse("1984-12-18TZ"), FULL, 0); - ofy().transact(() -> saveRevision("melancholy", DateTime.parse("1984-12-18TZ"), FULL, 1)); - ofy() + tm().transact(() -> saveRevision("melancholy", DateTime.parse("1984-12-18TZ"), FULL, 1)); + tm() .transact( () -> assertThat(getNextRevision("melancholy", DateTime.parse("1984-12-18TZ"), FULL)) @@ -102,7 +103,7 @@ public class RdeRevisionTest { assertThrows( VerifyException.class, () -> - ofy() + tm() .transact( () -> saveRevision("melancholy", DateTime.parse("1984-12-18TZ"), FULL, 2))); assertThat(thrown).hasMessageThat().contains("should be at 1 "); @@ -114,7 +115,7 @@ public class RdeRevisionTest { assertThrows( IllegalArgumentException.class, () -> - ofy() + tm() .transact( () -> saveRevision("melancholy", DateTime.parse("1984-12-18TZ"), FULL, -1))); diff --git a/core/src/test/java/google/registry/model/registrar/RegistrarTest.java b/core/src/test/java/google/registry/model/registrar/RegistrarTest.java index b44a1285c..bc21dcc6c 100644 --- a/core/src/test/java/google/registry/model/registrar/RegistrarTest.java +++ b/core/src/test/java/google/registry/model/registrar/RegistrarTest.java @@ -18,6 +18,7 @@ import static com.google.common.base.Preconditions.checkState; import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth8.assertThat; import static google.registry.model.ofy.ObjectifyService.ofy; +import static google.registry.model.transaction.TransactionManagerFactory.tm; import static google.registry.testing.CertificateSamples.SAMPLE_CERT; import static google.registry.testing.CertificateSamples.SAMPLE_CERT2; import static google.registry.testing.CertificateSamples.SAMPLE_CERT2_HASH; @@ -567,7 +568,7 @@ public class RegistrarTest extends EntityTestCase { @Test public void testLoadByClientIdCached_isTransactionless() { - ofy() + tm() .transact( () -> { assertThat(Registrar.loadByClientIdCached("registrar")).isPresent(); diff --git a/core/src/test/java/google/registry/model/registry/label/PremiumListUtilsTest.java b/core/src/test/java/google/registry/model/registry/label/PremiumListUtilsTest.java index cc37d6a63..1505b7399 100644 --- a/core/src/test/java/google/registry/model/registry/label/PremiumListUtilsTest.java +++ b/core/src/test/java/google/registry/model/registry/label/PremiumListUtilsTest.java @@ -30,6 +30,7 @@ import static google.registry.model.registry.label.PremiumListUtils.deletePremiu import static google.registry.model.registry.label.PremiumListUtils.doesPremiumListExist; import static google.registry.model.registry.label.PremiumListUtils.getPremiumPrice; import static google.registry.model.registry.label.PremiumListUtils.savePremiumListAndEntries; +import static google.registry.model.transaction.TransactionManagerFactory.tm; import static google.registry.testing.DatastoreHelper.createTld; import static google.registry.testing.DatastoreHelper.loadPremiumListEntries; import static google.registry.testing.DatastoreHelper.persistPremiumList; @@ -197,7 +198,7 @@ public class PremiumListUtilsTest { @Test public void testGetPremiumPrice_bloomFilterFalsePositive() { // Remove one of the premium list entries from behind the Bloom filter's back. - ofy() + tm() .transactNew( () -> ofy() diff --git a/core/src/test/java/google/registry/model/smd/SignedMarkRevocationListTest.java b/core/src/test/java/google/registry/model/smd/SignedMarkRevocationListTest.java index 565221aca..17b01503e 100644 --- a/core/src/test/java/google/registry/model/smd/SignedMarkRevocationListTest.java +++ b/core/src/test/java/google/registry/model/smd/SignedMarkRevocationListTest.java @@ -17,6 +17,7 @@ package google.registry.model.smd; import static com.google.common.truth.Truth.assertThat; import static google.registry.model.ofy.ObjectifyService.ofy; import static google.registry.model.smd.SignedMarkRevocationList.SHARD_SIZE; +import static google.registry.model.transaction.TransactionManagerFactory.tm; import static google.registry.testing.JUnitBackports.assertThrows; import static google.registry.util.DateTimeUtils.START_OF_TIME; import static org.joda.time.Duration.standardDays; @@ -46,13 +47,13 @@ public class SignedMarkRevocationListTest { assertThrows( SignedMarkRevocationList.UnshardedSaveException.class, () -> - ofy() + tm() .transact( () -> { SignedMarkRevocationList smdrl = SignedMarkRevocationList.create( - ofy().getTransactionTime(), - ImmutableMap.of("a", ofy().getTransactionTime())); + tm().getTransactionTime(), + ImmutableMap.of("a", tm().getTransactionTime())); smdrl.id = 1; // Without an id this won't save anyways. ofy().saveWithoutBackup().entity(smdrl).now(); })); diff --git a/core/src/test/java/google/registry/model/tmch/ClaimsListShardTest.java b/core/src/test/java/google/registry/model/tmch/ClaimsListShardTest.java index 8ea80936b..4858db0f1 100644 --- a/core/src/test/java/google/registry/model/tmch/ClaimsListShardTest.java +++ b/core/src/test/java/google/registry/model/tmch/ClaimsListShardTest.java @@ -17,6 +17,7 @@ package google.registry.model.tmch; import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth8.assertThat; import static google.registry.model.ofy.ObjectifyService.ofy; +import static google.registry.model.transaction.TransactionManagerFactory.tm; import static google.registry.testing.JUnitBackports.assertThrows; import static google.registry.util.DateTimeUtils.START_OF_TIME; import static org.joda.time.DateTimeZone.UTC; @@ -51,12 +52,12 @@ public class ClaimsListShardTest { assertThrows( UnshardedSaveException.class, () -> - ofy() + tm() .transact( () -> { ClaimsListShard claimsList = ClaimsListShard.create( - ofy().getTransactionTime(), ImmutableMap.of("a", "b")); + tm().getTransactionTime(), ImmutableMap.of("a", "b")); claimsList.id = 1; // Without an id this won't save anyways. claimsList.parent = ClaimsListRevision.createKey(); ofy().saveWithoutBackup().entity(claimsList).now(); diff --git a/core/src/test/java/google/registry/model/translators/CommitLogRevisionsTranslatorFactoryTest.java b/core/src/test/java/google/registry/model/translators/CommitLogRevisionsTranslatorFactoryTest.java index b7e8bf120..7ff8b1ba2 100644 --- a/core/src/test/java/google/registry/model/translators/CommitLogRevisionsTranslatorFactoryTest.java +++ b/core/src/test/java/google/registry/model/translators/CommitLogRevisionsTranslatorFactoryTest.java @@ -16,6 +16,7 @@ package google.registry.model.translators; import static com.google.common.truth.Truth.assertThat; import static google.registry.model.ofy.ObjectifyService.ofy; +import static google.registry.model.transaction.TransactionManagerFactory.tm; import static org.joda.time.Duration.standardDays; import static org.joda.time.Duration.standardHours; @@ -66,7 +67,7 @@ public class CommitLogRevisionsTranslatorFactoryTest { } private void save(final TestObject object) { - ofy().transact(() -> ofy().save().entity(object)); + tm().transact(() -> ofy().save().entity(object)); } private TestObject reload() { @@ -150,7 +151,7 @@ public class CommitLogRevisionsTranslatorFactoryTest { save(new TestObject()); clock.advanceBy(standardDays(1)); com.google.appengine.api.datastore.Entity entity = - ofy().transactNewReadOnly(() -> ofy().save().toEntity(reload())); + tm().transactNewReadOnly(() -> ofy().save().toEntity(reload())); assertThat(entity.getProperties().keySet()).containsExactly("revisions.key", "revisions.value"); assertThat(entity.getProperties()).containsEntry( "revisions.key", ImmutableList.of(START_TIME.toDate(), START_TIME.plusDays(1).toDate())); @@ -167,7 +168,7 @@ public class CommitLogRevisionsTranslatorFactoryTest { @Test public void testLoad_missingRevisionRawProperties_createsEmptyObject() { com.google.appengine.api.datastore.Entity entity = - ofy().transactNewReadOnly(() -> ofy().save().toEntity(new TestObject())); + tm().transactNewReadOnly(() -> ofy().save().toEntity(new TestObject())); entity.removeProperty("revisions.key"); entity.removeProperty("revisions.value"); TestObject object = ofy().load().fromEntity(entity); diff --git a/core/src/test/java/google/registry/rde/PendingDepositCheckerTest.java b/core/src/test/java/google/registry/rde/PendingDepositCheckerTest.java index 174fc40a3..4c3729281 100644 --- a/core/src/test/java/google/registry/rde/PendingDepositCheckerTest.java +++ b/core/src/test/java/google/registry/rde/PendingDepositCheckerTest.java @@ -20,6 +20,7 @@ import static google.registry.model.common.Cursor.CursorType.RDE_STAGING; import static google.registry.model.ofy.ObjectifyService.ofy; import static google.registry.model.rde.RdeMode.FULL; import static google.registry.model.rde.RdeMode.THIN; +import static google.registry.model.transaction.TransactionManagerFactory.tm; import static google.registry.testing.DatastoreHelper.createTld; import static google.registry.testing.DatastoreHelper.persistResource; import static org.joda.time.DateTimeConstants.TUESDAY; @@ -163,7 +164,7 @@ public class PendingDepositCheckerTest { private static void setCursor( final Registry registry, final CursorType cursorType, final DateTime value) { - ofy().transact(() -> ofy().save().entity(Cursor.create(cursorType, value, registry))); + tm().transact(() -> ofy().save().entity(Cursor.create(cursorType, value, registry))); } private static void createTldWithEscrowEnabled(final String tld) { diff --git a/core/src/test/java/google/registry/rde/RdeStagingActionTest.java b/core/src/test/java/google/registry/rde/RdeStagingActionTest.java index 6f84e7465..33c02b4c6 100644 --- a/core/src/test/java/google/registry/rde/RdeStagingActionTest.java +++ b/core/src/test/java/google/registry/rde/RdeStagingActionTest.java @@ -19,6 +19,7 @@ import static com.google.common.truth.Truth.assertThat; import static google.registry.model.common.Cursor.CursorType.BRDA; import static google.registry.model.common.Cursor.CursorType.RDE_STAGING; import static google.registry.model.ofy.ObjectifyService.ofy; +import static google.registry.model.transaction.TransactionManagerFactory.tm; import static google.registry.rde.RdeFixtures.makeContactResource; import static google.registry.rde.RdeFixtures.makeDomainBase; import static google.registry.rde.RdeFixtures.makeHostResource; @@ -847,7 +848,7 @@ public class RdeStagingActionTest extends MapreduceTestCase { private void setCursor( final Registry registry, final CursorType cursorType, final DateTime value) { clock.advanceOneMilli(); - ofy().transact(() -> ofy().save().entity(Cursor.create(cursorType, value, registry)).now()); + tm().transact(() -> ofy().save().entity(Cursor.create(cursorType, value, registry)).now()); } public static T unmarshal(Class clazz, byte[] xml) throws XmlException { diff --git a/core/src/test/java/google/registry/rde/RdeUploadActionTest.java b/core/src/test/java/google/registry/rde/RdeUploadActionTest.java index 6b0cdd577..b5320bc7c 100644 --- a/core/src/test/java/google/registry/rde/RdeUploadActionTest.java +++ b/core/src/test/java/google/registry/rde/RdeUploadActionTest.java @@ -19,8 +19,8 @@ import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertWithMessage; import static google.registry.model.common.Cursor.CursorType.RDE_STAGING; import static google.registry.model.common.Cursor.CursorType.RDE_UPLOAD_SFTP; -import static google.registry.model.ofy.ObjectifyService.ofy; import static google.registry.model.rde.RdeMode.FULL; +import static google.registry.model.transaction.TransactionManagerFactory.tm; import static google.registry.testing.DatastoreHelper.createTld; import static google.registry.testing.DatastoreHelper.persistResource; import static google.registry.testing.DatastoreHelper.persistSimpleResource; @@ -194,7 +194,7 @@ public class RdeUploadActionTest { writeGcsFile(gcsService, LENGTH_R1_FILE, Long.toString(DEPOSIT_XML.size()).getBytes(UTF_8)); writeGcsFile(gcsService, REPORT_FILE, Ghostryde.encode(REPORT_XML.read(), encryptKey)); writeGcsFile(gcsService, REPORT_R1_FILE, Ghostryde.encode(REPORT_XML.read(), encryptKey)); - ofy() + tm() .transact( () -> { RdeRevision.saveRevision("lol", DateTime.parse("2010-10-17TZ"), FULL, 0); @@ -282,7 +282,7 @@ public class RdeUploadActionTest { @Test public void testRunWithLock_resend() throws Exception { - ofy().transact(() -> RdeRevision.saveRevision("tld", DateTime.parse("2010-10-17TZ"), FULL, 1)); + tm().transact(() -> RdeRevision.saveRevision("tld", DateTime.parse("2010-10-17TZ"), FULL, 1)); int port = sftpd.serve("user", "password", folder.getRoot()); URI uploadUrl = URI.create(String.format("sftp://user:password@localhost:%d/", port)); DateTime stagingCursor = DateTime.parse("2010-10-18TZ"); diff --git a/core/src/test/java/google/registry/testing/DatastoreHelper.java b/core/src/test/java/google/registry/testing/DatastoreHelper.java index 945656431..eb390807b 100644 --- a/core/src/test/java/google/registry/testing/DatastoreHelper.java +++ b/core/src/test/java/google/registry/testing/DatastoreHelper.java @@ -30,6 +30,7 @@ import static google.registry.model.ResourceTransferUtils.createTransferResponse import static google.registry.model.ofy.ObjectifyService.ofy; import static google.registry.model.registry.Registry.TldState.GENERAL_AVAILABILITY; import static google.registry.model.registry.label.PremiumListUtils.parentPremiumListEntriesOnRevision; +import static google.registry.model.transaction.TransactionManagerFactory.tm; import static google.registry.pricing.PricingEngineProxy.getDomainRenewCost; import static google.registry.util.CollectionUtils.difference; import static google.registry.util.CollectionUtils.union; @@ -288,7 +289,7 @@ public class DatastoreHelper { // Calls {@link LordnTaskUtils#enqueueDomainBaseTask} wrapped in an ofy transaction so that // the // transaction time is set correctly. - ofy().transactNew(() -> LordnTaskUtils.enqueueDomainBaseTask(persistedDomain)); + tm().transactNew(() -> LordnTaskUtils.enqueueDomainBaseTask(persistedDomain)); return persistedDomain; } @@ -864,7 +865,7 @@ public class DatastoreHelper { assertWithMessage("Attempting to persist a Builder is almost certainly an error in test code") .that(resource) .isNotInstanceOf(Buildable.Builder.class); - ofy().transact(() -> saveResource(resource, wantBackup)); + tm().transact(() -> saveResource(resource, wantBackup)); // Force the session cache to be cleared so that when we read the resource back, we read from // Datastore and not from the session cache. This is needed to trigger Objectify's load process // (unmarshalling entity protos to POJOs, nulling out empty collections, calling @OnLoad @@ -877,7 +878,7 @@ public class DatastoreHelper { public static R persistEppResourceInFirstBucket(final R resource) { final EppResourceIndex eppResourceIndex = EppResourceIndex.create(Key.create(EppResourceIndexBucket.class, 1), Key.create(resource)); - ofy() + tm() .transact( () -> { Saver saver = ofy().save(); @@ -900,7 +901,7 @@ public class DatastoreHelper { } // Persist domains ten at a time, to avoid exceeding the entity group limit. for (final List chunk : Iterables.partition(resources, 10)) { - ofy().transact(() -> chunk.forEach(resource -> saveResource(resource, wantBackup))); + tm().transact(() -> chunk.forEach(resource -> saveResource(resource, wantBackup))); } // Force the session to be cleared so that when we read it back, we read from Datastore // and not from the transaction's session cache. @@ -921,8 +922,8 @@ public class DatastoreHelper { * @see #persistResource(Object) */ public static R persistEppResource(final R resource) { - checkState(!ofy().inTransaction()); - ofy() + checkState(!tm().inTransaction()); + tm() .transact( () -> { ofy() @@ -932,7 +933,7 @@ public class DatastoreHelper { new HistoryEntry.Builder() .setParent(resource) .setType(getHistoryEntryType(resource)) - .setModificationTime(ofy().getTransactionTime()) + .setModificationTime(tm().getTransactionTime()) .build()); ofy().save().entity(ForeignKeyIndex.create(resource, resource.getDeletionTime())); }); @@ -1008,7 +1009,7 @@ public class DatastoreHelper { * ForeignKeyedEppResources. */ public static ImmutableList persistSimpleResources(final Iterable resources) { - ofy().transact(() -> ofy().saveWithoutBackup().entities(resources)); + tm().transact(() -> ofy().saveWithoutBackup().entities(resources)); // Force the session to be cleared so that when we read it back, we read from Datastore // and not from the transaction's session cache. ofy().clearSessionCache(); @@ -1024,7 +1025,7 @@ public class DatastoreHelper { /** Force the create and update timestamps to get written into the resource. **/ public static R cloneAndSetAutoTimestamps(final R resource) { - return ofy().transact(() -> ofy().load().fromEntity(ofy().save().toEntity(resource))); + return tm().transact(() -> ofy().load().fromEntity(ofy().save().toEntity(resource))); } /** Returns the entire map of {@link PremiumListEntry}s for the given {@link PremiumList}. */ diff --git a/core/src/test/java/google/registry/tmch/LordnTaskUtilsTest.java b/core/src/test/java/google/registry/tmch/LordnTaskUtilsTest.java index 167c6e7bf..4beb02615 100644 --- a/core/src/test/java/google/registry/tmch/LordnTaskUtilsTest.java +++ b/core/src/test/java/google/registry/tmch/LordnTaskUtilsTest.java @@ -16,6 +16,7 @@ package google.registry.tmch; import static com.google.common.truth.Truth.assertThat; import static google.registry.model.ofy.ObjectifyService.ofy; +import static google.registry.model.transaction.TransactionManagerFactory.tm; import static google.registry.testing.DatastoreHelper.createTld; import static google.registry.testing.DatastoreHelper.loadRegistrar; import static google.registry.testing.DatastoreHelper.persistActiveContact; @@ -95,7 +96,7 @@ public class LordnTaskUtilsTest { @Test public void test_oteRegistrarWithNullIanaId() { - ofy() + tm() .transact( () -> ofy() @@ -130,6 +131,6 @@ public class LordnTaskUtilsTest { public void test_enqueueDomainBaseTask_throwsNpeOnNullDomain() { assertThrows( NullPointerException.class, - () -> ofy().transactNew(() -> LordnTaskUtils.enqueueDomainBaseTask(null))); + () -> tm().transactNew(() -> LordnTaskUtils.enqueueDomainBaseTask(null))); } }