1
0
mirror of https://github.com/google/nomulus synced 2026-04-26 03:00:48 +00:00

Remove some unnecessary Ofy key creation (#1212)

This commit is contained in:
Lai Jiang
2021-06-24 17:35:39 -04:00
committed by GitHub
parent 546eba68bd
commit a3e8bf219f
18 changed files with 144 additions and 114 deletions

View File

@@ -15,6 +15,7 @@
package google.registry.flows;
import static com.google.common.base.Preconditions.checkState;
import static google.registry.model.IdService.allocateId;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import static google.registry.xml.ValidationMode.LENIENT;
import static google.registry.xml.ValidationMode.STRICT;
@@ -33,7 +34,6 @@ import google.registry.model.eppcommon.EppXmlTransformer;
import google.registry.model.eppinput.EppInput.WrongProtocolVersionException;
import google.registry.model.eppoutput.EppOutput;
import google.registry.model.host.InetAddressAdapter.IpVersionMismatchException;
import google.registry.model.ofy.ObjectifyService;
import google.registry.model.reporting.HistoryEntry;
import google.registry.model.translators.CurrencyUnitAdapter.UnknownCurrencyException;
import google.registry.xml.XmlException;
@@ -105,7 +105,7 @@ public final class FlowUtils {
public static <H extends HistoryEntry> Key<H> createHistoryKey(
EppResource parent, Class<H> clazz) {
return Key.create(Key.create(parent), clazz, ObjectifyService.allocateId());
return Key.create(Key.create(parent), clazz, allocateId());
}
/** Registrar is not logged in. */

View File

@@ -19,6 +19,7 @@ import static google.registry.flows.ResourceFlowUtils.verifyResourceDoesNotExist
import static google.registry.flows.contact.ContactFlowUtils.validateAsciiPostalInfo;
import static google.registry.flows.contact.ContactFlowUtils.validateContactAgainstPolicy;
import static google.registry.model.EppResourceUtils.createRepoId;
import static google.registry.model.IdService.allocateId;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import com.google.common.collect.ImmutableSet;
@@ -41,7 +42,6 @@ import google.registry.model.eppoutput.CreateData.ContactCreateData;
import google.registry.model.eppoutput.EppResponse;
import google.registry.model.index.EppResourceIndex;
import google.registry.model.index.ForeignKeyIndex;
import google.registry.model.ofy.ObjectifyService;
import google.registry.model.reporting.HistoryEntry;
import google.registry.model.reporting.IcannReportingTypes.ActivityReportField;
import javax.inject.Inject;
@@ -81,7 +81,7 @@ public final class ContactCreateFlow implements TransactionalFlow {
.setAuthInfo(command.getAuthInfo())
.setCreationClientId(clientId)
.setPersistedCurrentSponsorClientId(clientId)
.setRepoId(createRepoId(ObjectifyService.allocateId(), roidSuffix))
.setRepoId(createRepoId(allocateId(), roidSuffix))
.setFaxNumber(command.getFax())
.setVoiceNumber(command.getVoice())
.setDisclose(command.getDisclose())

View File

@@ -42,6 +42,7 @@ import static google.registry.flows.domain.DomainFlowUtils.verifyPremiumNameIsNo
import static google.registry.flows.domain.DomainFlowUtils.verifyRegistrarIsActive;
import static google.registry.flows.domain.DomainFlowUtils.verifyUnitIsYears;
import static google.registry.model.EppResourceUtils.createDomainRepoId;
import static google.registry.model.IdService.allocateId;
import static google.registry.model.eppcommon.StatusValue.SERVER_HOLD;
import static google.registry.model.registry.Registry.TldState.GENERAL_AVAILABILITY;
import static google.registry.model.registry.Registry.TldState.QUIET_PERIOD;
@@ -99,7 +100,6 @@ import google.registry.model.eppoutput.CreateData.DomainCreateData;
import google.registry.model.eppoutput.EppResponse;
import google.registry.model.index.EppResourceIndex;
import google.registry.model.index.ForeignKeyIndex;
import google.registry.model.ofy.ObjectifyService;
import google.registry.model.poll.PendingActionNotificationResponse.DomainPendingActionNotificationResponse;
import google.registry.model.poll.PollMessage;
import google.registry.model.poll.PollMessage.Autorenew;
@@ -302,12 +302,9 @@ public class DomainCreateFlow implements TransactionalFlow {
Optional<SecDnsCreateExtension> secDnsCreate =
validateSecDnsExtension(eppInput.getSingleExtension(SecDnsCreateExtension.class));
DateTime registrationExpirationTime = leapSafeAddYears(now, years);
String repoId = createDomainRepoId(ObjectifyService.allocateId(), registry.getTldStr());
String repoId = createDomainRepoId(allocateId(), registry.getTldStr());
Key<DomainHistory> domainHistoryKey =
Key.create(
Key.create(DomainBase.class, repoId),
DomainHistory.class,
ObjectifyService.allocateId());
Key.create(Key.create(DomainBase.class, repoId), DomainHistory.class, allocateId());
historyBuilder.setId(domainHistoryKey.getId());
// Bill for the create.
BillingEvent.OneTime createBillingEvent =

View File

@@ -21,6 +21,7 @@ import static google.registry.flows.host.HostFlowUtils.validateHostName;
import static google.registry.flows.host.HostFlowUtils.verifySuperordinateDomainNotInPendingDelete;
import static google.registry.flows.host.HostFlowUtils.verifySuperordinateDomainOwnership;
import static google.registry.model.EppResourceUtils.createRepoId;
import static google.registry.model.IdService.allocateId;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import static google.registry.util.CollectionUtils.isNullOrEmpty;
@@ -49,7 +50,6 @@ import google.registry.model.host.HostHistory;
import google.registry.model.host.HostResource;
import google.registry.model.index.EppResourceIndex;
import google.registry.model.index.ForeignKeyIndex;
import google.registry.model.ofy.ObjectifyService;
import google.registry.model.reporting.HistoryEntry;
import google.registry.model.reporting.IcannReportingTypes.ActivityReportField;
import java.util.Optional;
@@ -126,7 +126,7 @@ public final class HostCreateFlow implements TransactionalFlow {
.setPersistedCurrentSponsorClientId(clientId)
.setHostName(targetId)
.setInetAddresses(command.getInetAddresses())
.setRepoId(createRepoId(ObjectifyService.allocateId(), roidSuffix))
.setRepoId(createRepoId(allocateId(), roidSuffix))
.setSuperordinateDomain(superordinateDomain.map(DomainBase::createVKey).orElse(null))
.build();
historyBuilder.setType(HistoryEntry.Type.HOST_CREATE).setModificationTime(now).setHost(newHost);

View File

@@ -16,9 +16,10 @@ package google.registry.model;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import static google.registry.model.ofy.ObjectifyService.auditedOfy;
import static google.registry.model.IdService.allocateId;
import static google.registry.model.ModelUtils.getAllFields;
import google.registry.model.ofy.ObjectifyService;
import com.googlecode.objectify.annotation.Id;
import google.registry.util.TypeUtils.TypeInstantiator;
import java.lang.reflect.Field;
import java.util.Optional;
@@ -54,25 +55,18 @@ public interface Buildable {
/** Build the instance. */
public S build() {
try {
// If this object has a Long or long Objectify @Id field that is not set, set it now.
Field idField = null;
try {
idField =
ModelUtils.getAllFields(instance.getClass())
.get(
auditedOfy()
.factory()
.getMetadata(instance.getClass())
.getKeyMetadata()
.getIdFieldName());
} catch (Exception e) {
// Expected if the class is not registered with Objectify.
}
// If this object has a Long or long Objectify @Id field that is not set, set it now. For
// any entity it has one and only one @Id field in its class hierarchy.
Field idField =
getAllFields(instance.getClass()).values().stream()
.filter(field -> field.isAnnotationPresent(Id.class))
.findFirst()
.orElse(null);
if (idField != null
&& !idField.getType().equals(String.class)
&& Optional.ofNullable((Long) ModelUtils.getFieldValue(instance, idField))
.orElse(0L) == 0) {
ModelUtils.setFieldValue(instance, idField, ObjectifyService.allocateId());
ModelUtils.setFieldValue(instance, idField, allocateId());
}
return instance;
} finally {

View File

@@ -0,0 +1,61 @@
// Copyright 2021 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;
import static com.google.common.base.Preconditions.checkState;
import com.google.appengine.api.datastore.DatastoreServiceFactory;
import com.google.common.annotations.VisibleForTesting;
import google.registry.config.RegistryEnvironment;
import java.util.concurrent.atomic.AtomicLong;
/**
* Allocates a globally unique {@link Long} number to use as an Ofy {@code @Id}.
*
* <p>In non-test environments the Id is generated by Datastore, whereas in tests it's from an
* atomic long number that's incremented every time this method is called.
*/
public final class IdService {
/**
* A placeholder String passed into DatastoreService.allocateIds that ensures that all ids are
* initialized from the same id pool.
*/
private static final String APP_WIDE_ALLOCATION_KIND = "common";
/** Counts of used ids for use in unit tests. Outside tests this is never used. */
private static final AtomicLong nextTestId = new AtomicLong(1); // ids cannot be zero
/** Allocates an id. */
public static long allocateId() {
return RegistryEnvironment.UNITTEST.equals(RegistryEnvironment.get())
? nextTestId.getAndIncrement()
: DatastoreServiceFactory.getDatastoreService()
.allocateIds(APP_WIDE_ALLOCATION_KIND, 1)
.iterator()
.next()
.getId();
}
/** Resets the global test id counter (i.e. sets the next id to 1). */
@VisibleForTesting
public static void resetNextTestId() {
checkState(
RegistryEnvironment.UNITTEST.equals(RegistryEnvironment.get()),
"Can't call resetTestIdCounts() from RegistryEnvironment.%s",
RegistryEnvironment.get());
nextTestId.set(1); // ids cannot be zero
}
}

View File

@@ -14,11 +14,13 @@
package google.registry.model.common;
import com.google.apphosting.api.ApiProxy;
import com.googlecode.objectify.Key;
import com.googlecode.objectify.annotation.Entity;
import com.googlecode.objectify.annotation.Id;
import google.registry.model.BackupGroupRoot;
import google.registry.schema.replay.DatastoreOnlyEntity;
import javax.annotation.Nullable;
/**
* The root key for the entity group which is known as the cross-tld entity group for historical
@@ -42,7 +44,13 @@ public class EntityGroupRoot extends BackupGroupRoot implements DatastoreOnlyEnt
private String id;
/** The root key for cross-tld resources such as registrars. */
public static Key<EntityGroupRoot> getCrossTldKey() {
return Key.create(EntityGroupRoot.class, "cross-tld");
public static @Nullable Key<EntityGroupRoot> getCrossTldKey() {
// If we cannot get a current environment, calling Key.create() will fail. Instead we return a
// null in cases where this key is not actually needed (for example when loading an entity from
// SQL) to initialize an object, to avoid having to register a DatastoreEntityExtension in
// tests.
return ApiProxy.getCurrentEnvironment() == null
? null
: Key.create(EntityGroupRoot.class, "cross-tld");
}
}

View File

@@ -15,7 +15,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.IdService.allocateId;
import static google.registry.persistence.transaction.TransactionManagerFactory.ofyTm;
import com.google.appengine.api.users.User;

View File

@@ -15,6 +15,7 @@
package google.registry.model.domain;
import static com.google.common.base.Preconditions.checkArgument;
import static google.registry.model.IdService.allocateId;
import static google.registry.util.PreconditionsUtils.checkArgumentNotNull;
import com.google.common.annotations.VisibleForTesting;
@@ -22,7 +23,6 @@ import com.googlecode.objectify.annotation.Embed;
import google.registry.model.billing.BillingEvent;
import google.registry.model.billing.BillingEvent.Recurring;
import google.registry.model.domain.rgp.GracePeriodStatus;
import google.registry.model.ofy.ObjectifyService;
import google.registry.persistence.BillingVKey.BillingEventVKey;
import google.registry.persistence.BillingVKey.BillingRecurrenceVKey;
import google.registry.persistence.VKey;
@@ -68,7 +68,7 @@ public class GracePeriod extends GracePeriodBase implements DatastoreAndSqlEntit
(billingEventRecurring != null) == GracePeriodStatus.AUTO_RENEW.equals(type),
"Recurring billing events must be present on (and only on) autorenew grace periods");
GracePeriod instance = new GracePeriod();
instance.gracePeriodId = gracePeriodId == null ? ObjectifyService.allocateId() : gracePeriodId;
instance.gracePeriodId = gracePeriodId == null ? allocateId() : gracePeriodId;
instance.type = checkArgumentNotNull(type);
instance.domainRepoId = checkArgumentNotNull(domainRepoId);
instance.expirationTime = checkArgumentNotNull(expirationTime);
@@ -210,7 +210,7 @@ public class GracePeriod extends GracePeriodBase implements DatastoreAndSqlEntit
static GracePeriodHistory createFrom(long historyRevisionId, GracePeriod gracePeriod) {
GracePeriodHistory instance = new GracePeriodHistory();
instance.gracePeriodHistoryRevisionId = ObjectifyService.allocateId();
instance.gracePeriodHistoryRevisionId = allocateId();
instance.domainHistoryRevisionId = historyRevisionId;
instance.gracePeriodId = gracePeriod.gracePeriodId;
instance.type = gracePeriod.type;

View File

@@ -14,8 +14,9 @@
package google.registry.model.domain.secdns;
import static google.registry.model.IdService.allocateId;
import google.registry.model.domain.DomainHistory;
import google.registry.model.ofy.ObjectifyService;
import google.registry.schema.replay.SqlOnlyEntity;
import javax.persistence.Access;
import javax.persistence.AccessType;
@@ -48,7 +49,7 @@ public class DomainDsDataHistory extends DomainDsDataBase implements SqlOnlyEnti
instance.algorithm = dsData.getAlgorithm();
instance.digestType = dsData.getDigestType();
instance.digest = dsData.getDigest();
instance.dsDataHistoryRevisionId = ObjectifyService.allocateId();
instance.dsDataHistoryRevisionId = allocateId();
return instance;
}

View File

@@ -21,8 +21,6 @@ import static google.registry.util.TypeUtils.hasAnnotation;
import com.google.appengine.api.datastore.AsyncDatastoreService;
import com.google.appengine.api.datastore.DatastoreServiceConfig;
import com.google.appengine.api.datastore.DatastoreServiceFactory;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Streams;
@@ -48,7 +46,6 @@ import google.registry.model.translators.InetAddressTranslatorFactory;
import google.registry.model.translators.ReadableInstantUtcTranslatorFactory;
import google.registry.model.translators.UpdateAutoTimestampTranslatorFactory;
import google.registry.model.translators.VKeyTranslatorFactory;
import java.util.concurrent.atomic.AtomicLong;
/**
* An instance of Ofy, obtained via {@code #auditedOfy()}, should be used to access all persistable
@@ -57,12 +54,6 @@ import java.util.concurrent.atomic.AtomicLong;
*/
public class ObjectifyService {
/**
* A placeholder String passed into DatastoreService.allocateIds that ensures that all ids are
* initialized from the same id pool.
*/
public static final String APP_WIDE_ALLOCATION_KIND = "common";
/** A singleton instance of our Ofy wrapper. */
private static final Ofy OFY = new Ofy(null);
@@ -101,21 +92,24 @@ public class ObjectifyService {
private static void initOfyOnce() {
// Set an ObjectifyFactory that uses our extended ObjectifyImpl.
// The "false" argument means that we are not using the v5-style Objectify embedded entities.
com.googlecode.objectify.ObjectifyService.setFactory(new ObjectifyFactory(false) {
@Override
public Objectify begin() {
return new SessionKeyExposingObjectify(this);
}
com.googlecode.objectify.ObjectifyService.setFactory(
new ObjectifyFactory(false) {
@Override
public Objectify begin() {
return new SessionKeyExposingObjectify(this);
}
@Override
protected AsyncDatastoreService createRawAsyncDatastoreService(DatastoreServiceConfig cfg) {
// In the unit test environment, wrap the Datastore service in a proxy that can be used to
// examine the number of requests sent to Datastore.
AsyncDatastoreService service = super.createRawAsyncDatastoreService(cfg);
return RegistryEnvironment.get().equals(RegistryEnvironment.UNITTEST)
? new RequestCapturingAsyncDatastoreService(service)
: service;
}});
@Override
protected AsyncDatastoreService createRawAsyncDatastoreService(
DatastoreServiceConfig cfg) {
// In the unit test environment, wrap the Datastore service in a proxy that can be used
// to examine the number of requests sent to Datastore.
AsyncDatastoreService service = super.createRawAsyncDatastoreService(cfg);
return RegistryEnvironment.get().equals(RegistryEnvironment.UNITTEST)
? new RequestCapturingAsyncDatastoreService(service)
: service;
}
});
// Translators must be registered before any entities can be registered.
registerTranslators();
@@ -168,9 +162,11 @@ public class ObjectifyService {
} else if (clazz.isAnnotationPresent(EntitySubclass.class)) {
// Ensure that any @EntitySubclass classes have also had their parent @Entity registered,
// which Objectify nominally requires but doesn't enforce in 4.x (though it may in 5.x).
checkState(registered,
checkState(
registered,
"No base entity for kind '%s' registered yet, cannot register new @EntitySubclass %s",
kind, clazz.getCanonicalName());
kind,
clazz.getCanonicalName());
}
com.googlecode.objectify.ObjectifyService.register(clazz);
// Autogenerated ids make the commit log code very difficult since we won't always be able
@@ -186,27 +182,4 @@ public class ObjectifyService {
}
}
}
/** Counts of used ids for use in unit tests. Outside tests this is never used. */
private static final AtomicLong nextTestId = new AtomicLong(1); // ids cannot be zero
/** Allocates an id. */
public static long allocateId() {
return RegistryEnvironment.UNITTEST.equals(RegistryEnvironment.get())
? nextTestId.getAndIncrement()
: DatastoreServiceFactory.getDatastoreService()
.allocateIds(APP_WIDE_ALLOCATION_KIND, 1)
.iterator()
.next()
.getId();
}
/** Resets the global test id counter (i.e. sets the next id to 1). */
@VisibleForTesting
public static void resetNextTestId() {
checkState(RegistryEnvironment.UNITTEST.equals(RegistryEnvironment.get()),
"Can't call resetTestIdCounts() from RegistryEnvironment.%s",
RegistryEnvironment.get());
nextTestId.set(1); // ids cannot be zero
}
}

View File

@@ -19,7 +19,7 @@ import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.collect.ImmutableMap.toImmutableMap;
import static com.google.common.hash.Funnels.stringFunnel;
import static com.google.common.hash.Funnels.unencodedCharsFunnel;
import static google.registry.model.ofy.ObjectifyService.allocateId;
import static google.registry.model.IdService.allocateId;
import static google.registry.persistence.transaction.QueryComposer.Comparator.EQ;
import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm;
@@ -53,6 +53,7 @@ import javax.persistence.Column;
import javax.persistence.Index;
import javax.persistence.PostLoad;
import javax.persistence.PostPersist;
import javax.persistence.PostUpdate;
import javax.persistence.PrePersist;
import javax.persistence.PreRemove;
import javax.persistence.Table;

View File

@@ -17,7 +17,7 @@ package google.registry.model.tmch;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import static com.google.common.collect.ImmutableMap.toImmutableMap;
import static google.registry.model.ofy.ObjectifyService.allocateId;
import static google.registry.model.IdService.allocateId;
import static google.registry.model.ofy.ObjectifyService.auditedOfy;
import static google.registry.persistence.transaction.QueryComposer.Comparator.EQ;
import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm;
@@ -36,6 +36,7 @@ import google.registry.model.annotations.NotBackedUp;
import google.registry.model.annotations.NotBackedUp.Reason;
import google.registry.model.annotations.VirtualEntity;
import google.registry.model.common.CrossTldSingleton;
import google.registry.model.registry.label.ReservedList.ReservedListEntry;
import google.registry.schema.replay.DatastoreOnlyEntity;
import google.registry.schema.replay.NonReplicatedEntity;
import java.util.Map;
@@ -45,6 +46,7 @@ import javax.persistence.Column;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.PostPersist;
import javax.persistence.PostUpdate;
import javax.persistence.PreRemove;
import javax.persistence.Table;
import javax.persistence.Transient;