mirror of
https://github.com/google/nomulus
synced 2026-09-19 14:34:18 +00:00
Update RegistrarSettingsAction and RegistrarContact to SQL calls (#1042)
* Update RegistrarSettingsAction and RegistrarContact to SQL calls Relevant potentially-unclear changes: - Making sure the last update time is always correct and up to date in the auto timestamp object - Reloading the domain upon return when updating in a new transaction to make sure that we use the properly-updated last update time (SQL returns the correct result if retrieved within the same txn but DS does not)
This commit is contained in:
@@ -58,7 +58,8 @@ public class UpdateAutoTimestamp extends ImmutableObject {
|
||||
@PreUpdate
|
||||
void setTimestamp() {
|
||||
if (autoUpdateEnabled() || lastUpdateTime == null) {
|
||||
lastUpdateTime = DateTimeUtils.toZonedDateTime(jpaTm().getTransactionTime());
|
||||
timestamp = jpaTm().getTransactionTime();
|
||||
lastUpdateTime = DateTimeUtils.toZonedDateTime(timestamp);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -16,8 +16,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.persistence.transaction.TransactionManagerFactory.tm;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.ofyTm;
|
||||
|
||||
import com.google.appengine.api.users.User;
|
||||
import com.google.common.base.Splitter;
|
||||
@@ -56,13 +55,22 @@ public class GaeUserIdConverter extends ImmutableObject {
|
||||
try {
|
||||
// Perform these operations in a transactionless context to avoid enlisting in some outer
|
||||
// transaction (if any).
|
||||
tm().doTransactionless(() -> ofy().saveWithoutBackup().entity(gaeUserIdConverter).now());
|
||||
ofyTm()
|
||||
.doTransactionless(
|
||||
() -> {
|
||||
ofyTm().putWithoutBackup(gaeUserIdConverter);
|
||||
return null;
|
||||
});
|
||||
|
||||
// The read must be done in its own transaction to avoid reading from the session cache.
|
||||
return tm()
|
||||
.transactNew(() -> ofy().load().entity(gaeUserIdConverter).safe().user.getUserId());
|
||||
return ofyTm().transactNew(() -> ofyTm().loadByEntity(gaeUserIdConverter).user.getUserId());
|
||||
} finally {
|
||||
tm().doTransactionless(() -> ofy().deleteWithoutBackup().entity(gaeUserIdConverter).now());
|
||||
ofyTm()
|
||||
.doTransactionless(
|
||||
() -> {
|
||||
ofyTm().deleteWithoutBackup(gaeUserIdConverter);
|
||||
return null;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ import static com.google.common.io.BaseEncoding.base64;
|
||||
import static google.registry.model.common.EntityGroupRoot.getCrossTldKey;
|
||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||
import static google.registry.model.registrar.Registrar.checkValidEmail;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||
import static google.registry.util.CollectionUtils.nullToEmptyImmutableSortedCopy;
|
||||
import static google.registry.util.PasswordUtils.SALT_SUPPLIER;
|
||||
@@ -200,17 +201,34 @@ public class RegistrarContact extends ImmutableObject
|
||||
* relevant Registrar entity with the {@link Registrar#contactsRequireSyncing} field set to true.
|
||||
*/
|
||||
public static void updateContacts(
|
||||
final Registrar registrar, final Set<RegistrarContact> contacts) {
|
||||
final Registrar registrar, final ImmutableSet<RegistrarContact> contacts) {
|
||||
tm().transact(
|
||||
() -> {
|
||||
ofy()
|
||||
.delete()
|
||||
.keys(
|
||||
difference(
|
||||
ImmutableSet.copyOf(
|
||||
ofy().load().type(RegistrarContact.class).ancestor(registrar).keys()),
|
||||
contacts.stream().map(Key::create).collect(toImmutableSet())));
|
||||
ofy().save().entities(contacts);
|
||||
if (tm().isOfy()) {
|
||||
ImmutableSet<Key<RegistrarContact>> existingKeys =
|
||||
ImmutableSet.copyOf(
|
||||
ofy().load().type(RegistrarContact.class).ancestor(registrar).keys());
|
||||
tm().delete(
|
||||
difference(
|
||||
existingKeys,
|
||||
contacts.stream().map(Key::create).collect(toImmutableSet()))
|
||||
.stream()
|
||||
.map(key -> VKey.createOfy(RegistrarContact.class, key))
|
||||
.collect(toImmutableSet()));
|
||||
} else {
|
||||
ImmutableSet<String> emailAddressesToKeep =
|
||||
contacts.stream()
|
||||
.map(RegistrarContact::getEmailAddress)
|
||||
.collect(toImmutableSet());
|
||||
jpaTm()
|
||||
.query(
|
||||
"DELETE FROM RegistrarPoc WHERE registrarId = :registrarId AND "
|
||||
+ "emailAddress NOT IN :emailAddressesToKeep")
|
||||
.setParameter("registrarId", registrar.getClientId())
|
||||
.setParameter("emailAddressesToKeep", emailAddressesToKeep)
|
||||
.executeUpdate();
|
||||
}
|
||||
tm().putAll(contacts);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
+2
-4
@@ -19,7 +19,6 @@ import static com.google.common.base.Preconditions.checkState;
|
||||
import static com.google.common.collect.ImmutableList.toImmutableList;
|
||||
import static com.google.common.collect.ImmutableMap.toImmutableMap;
|
||||
import static google.registry.model.common.GaeUserIdConverter.convertEmailAddressToGaeUserId;
|
||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||
import static google.registry.ui.server.SoyTemplateUtils.CSS_RENAMING_MAP_SUPPLIER;
|
||||
import static javax.servlet.http.HttpServletResponse.SC_FORBIDDEN;
|
||||
@@ -234,14 +233,13 @@ public final class ConsoleRegistrarCreatorAction extends HtmlAction {
|
||||
.setEmailAddress(consoleUserEmail.get())
|
||||
.setGaeUserId(gaeUserId)
|
||||
.build();
|
||||
tm()
|
||||
.transact(
|
||||
tm().transact(
|
||||
() -> {
|
||||
checkState(
|
||||
!Registrar.loadByClientId(registrar.getClientId()).isPresent(),
|
||||
"Registrar with client ID %s already exists",
|
||||
registrar.getClientId());
|
||||
ofy().save().entities(registrar, contact);
|
||||
tm().putAll(registrar, contact);
|
||||
});
|
||||
data.put("password", password);
|
||||
data.put("passcode", phonePasscode);
|
||||
|
||||
+16
-11
@@ -20,7 +20,7 @@ import static com.google.common.collect.ImmutableSet.toImmutableSet;
|
||||
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.persistence.transaction.TransactionManagerFactory.jpaTm;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||
import static google.registry.security.JsonResponseHelper.Status.ERROR;
|
||||
import static google.registry.security.JsonResponseHelper.Status.SUCCESS;
|
||||
@@ -170,24 +170,28 @@ public class RegistrarSettingsAction implements Runnable, JsonActionRunner.JsonA
|
||||
}
|
||||
|
||||
private RegistrarResult read(String clientId) {
|
||||
return RegistrarResult.create("Success", loadRegistrarUnchecked(clientId));
|
||||
}
|
||||
|
||||
private Registrar loadRegistrarUnchecked(String registrarId) {
|
||||
try {
|
||||
return RegistrarResult.create("Success", registrarAccessor.getRegistrar(clientId));
|
||||
return registrarAccessor.getRegistrar(registrarId);
|
||||
} catch (RegistrarAccessDeniedException e) {
|
||||
throw new ForbiddenException(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
private RegistrarResult update(final Map<String, ?> args, String clientId) {
|
||||
return tm().transact(
|
||||
tm().transact(
|
||||
() -> {
|
||||
// We load the registrar here rather than outside of the transaction - to make
|
||||
// sure we have the latest version. This one is loaded inside the transaction, so it's
|
||||
// guaranteed to not change before we update it.
|
||||
Registrar registrar;
|
||||
try {
|
||||
registrar = registrarAccessor.getRegistrar(clientId);
|
||||
} catch (RegistrarAccessDeniedException e) {
|
||||
throw new ForbiddenException(e.getMessage(), e);
|
||||
Registrar registrar = loadRegistrarUnchecked(clientId);
|
||||
// Detach the registrar to avoid Hibernate object-updates, since we wish to email
|
||||
// out the diffs between the existing and updated registrar objects
|
||||
if (!tm().isOfy()) {
|
||||
jpaTm().getEntityManager().detach(registrar);
|
||||
}
|
||||
// Verify that the registrar hasn't been changed.
|
||||
// To do that - we find the latest update time (or null if the registrar has been
|
||||
@@ -233,14 +237,15 @@ public class RegistrarSettingsAction implements Runnable, JsonActionRunner.JsonA
|
||||
|
||||
// Save the updated registrar
|
||||
if (!updatedRegistrar.equals(registrar)) {
|
||||
ofy().save().entity(updatedRegistrar);
|
||||
tm().put(updatedRegistrar);
|
||||
}
|
||||
|
||||
// Email and return update.
|
||||
// Email the updates
|
||||
sendExternalUpdatesIfNecessary(
|
||||
registrar, contacts, updatedRegistrar, updatedContacts);
|
||||
return RegistrarResult.create("Saved " + clientId, updatedRegistrar);
|
||||
});
|
||||
// Reload the result outside of the transaction to get the most recent version
|
||||
return RegistrarResult.create("Saved " + clientId, loadRegistrarUnchecked(clientId));
|
||||
}
|
||||
|
||||
private Map<String, Object> expandRegistrarWithContacts(
|
||||
|
||||
Reference in New Issue
Block a user