Create *InfoData objects instead of reusing *Resource objects

This is probably best from a code-cleanliness perspective anyways,
but the rationale is that tightly coupling the resources to the
info responses was a straightjacket that required all status
values and fields to be directly available on the resource. With
this change, I already was able to get rid of the preMarshal()
hackery, and I will be able to get rid of cloneWithLinkedStatus()
and most of the contents of cloneProjectedAtTime() for non-domains.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=144252924
This commit is contained in:
cgoldfeder 2017-01-11 14:49:10 -08:00 committed by Ben McIlwain
parent 96a71ded91
commit b0bcc1bb3d
22 changed files with 586 additions and 230 deletions

View file

@ -20,8 +20,11 @@ import static google.registry.flows.ResourceFlowUtils.verifyExistence;
import static google.registry.flows.ResourceFlowUtils.verifyOptionalAuthInfo;
import static google.registry.flows.ResourceFlowUtils.verifyResourceOwnership;
import static google.registry.flows.domain.DomainFlowUtils.addSecDnsExtensionIfPresent;
import static google.registry.flows.domain.DomainFlowUtils.loadForeignKeyedDesignatedContacts;
import static google.registry.flows.domain.DomainFlowUtils.prefetchReferencedResources;
import static google.registry.flows.domain.DomainFlowUtils.verifyApplicationDomainMatchesTargetId;
import static google.registry.model.EppResourceUtils.loadDomainApplication;
import static google.registry.model.ofy.ObjectifyService.ofy;
import com.google.common.base.Optional;
import com.google.common.collect.ImmutableList;
@ -35,6 +38,7 @@ import google.registry.flows.FlowModule.ClientId;
import google.registry.flows.FlowModule.TargetId;
import google.registry.model.domain.DomainApplication;
import google.registry.model.domain.DomainCommand.Info;
import google.registry.model.domain.DomainInfoData;
import google.registry.model.domain.launch.LaunchInfoExtension;
import google.registry.model.domain.launch.LaunchInfoResponseExtension;
import google.registry.model.eppcommon.AuthInfo;
@ -95,8 +99,23 @@ public final class DomainApplicationInfoFlow implements Flow {
}
// We don't support authInfo for applications, so if it's another registrar always fail.
verifyResourceOwnership(clientId, application);
application = getResourceInfo(application);
prefetchReferencedResources(application);
return responseBuilder
.setResData(getResourceInfo(application))
.setResData(DomainInfoData.newBuilder()
.setFullyQualifiedDomainName(application.getFullyQualifiedDomainName())
.setRepoId(application.getRepoId())
.setStatusValues(application.getStatusValues())
.setRegistrant(ofy().load().key(application.getRegistrant()).now().getContactId())
.setContacts(loadForeignKeyedDesignatedContacts(application.getContacts()))
.setNameservers(application.loadNameserverFullyQualifiedHostNames())
.setCurrentSponsorClientId(application.getCurrentSponsorClientId())
.setCreationClientId(application.getCreationClientId())
.setCreationTime(application.getCreationTime())
.setLastEppUpdateClientId(application.getLastEppUpdateClientId())
.setLastEppUpdateTime(application.getLastEppUpdateTime())
.setAuthInfo(application.getAuthInfo())
.build())
.setExtensions(getDomainResponseExtensions(application, launchInfo, now))
.build();
}

View file

@ -70,6 +70,7 @@ import google.registry.model.domain.DomainCommand.CreateOrUpdate;
import google.registry.model.domain.DomainCommand.InvalidReferencesException;
import google.registry.model.domain.DomainCommand.Update;
import google.registry.model.domain.DomainResource;
import google.registry.model.domain.ForeignKeyedDesignatedContact;
import google.registry.model.domain.LrpTokenEntity;
import google.registry.model.domain.Period;
import google.registry.model.domain.fee.Credit;
@ -896,6 +897,23 @@ public class DomainFlowUtils {
.build();
}
/** Bulk-load all referenced resources on a domain so they are in the session cache. */
static void prefetchReferencedResources(DomainBase domain) {
// Calling values() on the result blocks until loading is done.
ofy().load().values(union(domain.getNameservers(), domain.getReferencedContacts())).values();
}
static ImmutableSet<ForeignKeyedDesignatedContact> loadForeignKeyedDesignatedContacts(
ImmutableSet<DesignatedContact> contacts) {
ImmutableSet.Builder<ForeignKeyedDesignatedContact> builder = new ImmutableSet.Builder<>();
for (DesignatedContact contact : contacts) {
builder.add(ForeignKeyedDesignatedContact.create(
contact.getType(),
ofy().load().key(contact.getContactKey()).now().getContactId()));
}
return builder.build();
}
/** Resource linked to this domain does not exist. */
static class LinkedResourcesDoNotExistException extends ObjectDoesNotExistException {
public LinkedResourcesDoNotExistException(Class<?> type, ImmutableSet<String> resourceIds) {

View file

@ -19,6 +19,9 @@ import static google.registry.flows.ResourceFlowUtils.loadAndVerifyExistence;
import static google.registry.flows.ResourceFlowUtils.verifyOptionalAuthInfo;
import static google.registry.flows.domain.DomainFlowUtils.addSecDnsExtensionIfPresent;
import static google.registry.flows.domain.DomainFlowUtils.handleFeeRequest;
import static google.registry.flows.domain.DomainFlowUtils.loadForeignKeyedDesignatedContacts;
import static google.registry.flows.domain.DomainFlowUtils.prefetchReferencedResources;
import static google.registry.model.ofy.ObjectifyService.ofy;
import com.google.common.base.Optional;
import com.google.common.collect.ImmutableList;
@ -35,6 +38,7 @@ import google.registry.flows.custom.DomainInfoFlowCustomLogic.BeforeResponsePara
import google.registry.flows.custom.DomainInfoFlowCustomLogic.BeforeResponseReturnData;
import google.registry.model.domain.DomainCommand.Info;
import google.registry.model.domain.DomainCommand.Info.HostsRequest;
import google.registry.model.domain.DomainInfoData;
import google.registry.model.domain.DomainResource;
import google.registry.model.domain.DomainResource.Builder;
import google.registry.model.domain.fee06.FeeInfoCommandExtensionV06;
@ -97,8 +101,26 @@ public final class DomainInfoFlow implements Flow {
.setResData(getResourceInfo(domain))
.setResponseExtensions(getDomainResponseExtensions(domain, now))
.build());
domain = responseData.resData();
prefetchReferencedResources(domain);
return responseBuilder
.setResData(responseData.resData())
.setResData(DomainInfoData.newBuilder()
.setFullyQualifiedDomainName(domain.getFullyQualifiedDomainName())
.setRepoId(domain.getRepoId())
.setStatusValues(domain.getStatusValues())
.setRegistrant(ofy().load().key(domain.getRegistrant()).now().getContactId())
.setContacts(loadForeignKeyedDesignatedContacts(domain.getContacts()))
.setNameservers(domain.loadNameserverFullyQualifiedHostNames())
.setSubordinateHosts(domain.getSubordinateHosts())
.setCurrentSponsorClientId(domain.getCurrentSponsorClientId())
.setCreationClientId(domain.getCreationClientId())
.setCreationTime(domain.getCreationTime())
.setLastEppUpdateClientId(domain.getLastEppUpdateClientId())
.setLastEppUpdateTime(domain.getLastEppUpdateTime())
.setRegistrationExpirationTime(domain.getRegistrationExpirationTime())
.setLastTransferTime(domain.getLastTransferTime())
.setAuthInfo(domain.getAuthInfo())
.build())
.setExtensions(responseData.responseExtensions())
.build();
}