From a6aa944c6cdf65c973a507fdd7115b4c0bd156e7 Mon Sep 17 00:00:00 2001 From: Ben McIlwain Date: Thu, 30 Dec 2021 12:53:39 -0500 Subject: [PATCH] Make premium list saving run as a single transaction (#1480) * Make premium list saving run as a single transaction This fixes the bug where the new revision is saved, but then execution gets halted for some reason (e.g. request timeout) before the entries finish saving, which leaves the DB in a bad state with a new top revision containing zero entries, thus making everything standard. --- .../model/tld/label/PremiumListDao.java | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/core/src/main/java/google/registry/model/tld/label/PremiumListDao.java b/core/src/main/java/google/registry/model/tld/label/PremiumListDao.java index 9cacb7ed8..cfbecbf88 100644 --- a/core/src/main/java/google/registry/model/tld/label/PremiumListDao.java +++ b/core/src/main/java/google/registry/model/tld/label/PremiumListDao.java @@ -19,6 +19,7 @@ import static google.registry.config.RegistryConfig.getDomainLabelListCacheDurat import static google.registry.config.RegistryConfig.getSingletonCachePersistDuration; import static google.registry.config.RegistryConfig.getStaticPremiumListMaxCachedEntries; import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm; +import static google.registry.util.CollectionUtils.isNullOrEmpty; import com.google.auto.value.AutoValue; import com.google.common.annotations.VisibleForTesting; @@ -156,24 +157,22 @@ public class PremiumListDao { return save(PremiumListUtils.parseToPremiumList(name, currencyUnit, inputData)); } + /** Saves the given premium list (and its premium list entries) to Cloud SQL. */ public static PremiumList save(PremiumList premiumList) { - jpaTm().transact(() -> jpaTm().insert(premiumList)); - premiumListCache.invalidate(premiumList.getName()); jpaTm() .transact( () -> { - if (premiumList.getLabelsToPrices() != null) { - Optional savedPremiumList = - PremiumListDao.getLatestRevision(premiumList.getName()); + jpaTm().insert(premiumList); + jpaTm().getEntityManager().flush(); // This populates the revisionId. + long revisionId = premiumList.getRevisionId(); + + if (!isNullOrEmpty(premiumList.getLabelsToPrices())) { ImmutableSet.Builder entries = new ImmutableSet.Builder<>(); premiumList.getLabelsToPrices().entrySet().stream() .forEach( entry -> entries.add( - PremiumEntry.create( - savedPremiumList.get().getRevisionId(), - entry.getValue(), - entry.getKey()))); + PremiumEntry.create(revisionId, entry.getValue(), entry.getKey()))); jpaTm().insertAll(entries.build()); } });