Remove ofy support from PollMessage (#1732)

Also deletes the autorenew poll message history revision id field in
Domain, which is only needed to recreate the ofy key for the poll
message. The column already contains null values in it, making it
impossible to depend on it. The column itself will be deleted from the
schema after this PR is deployed.

The logic to update autorenew recurrence end time is changed
accordingly: When a poll message already exists, we simply update the
endtime, but when it no longer exists, i. e. when it's deleted
speculatively after a transfer request, we recreate one using the
history entry id that resulted in its creation (e. g. cancelled or rejected
transfer).

This should fix b/240984498. Though the exact reason for that bug is
still unclear to me. Namely, it throws an NPE at this line during an
explicit domain transfer approval:

https://cs.opensource.google/nomulus/nomulus/+/master:core/src/main/java/google/registry/flows/domain/DomainFlowUtils.java;l=603;bpv=1;bpt=0;drc=ede919d7dcdb7f209b074563b3d449ebee19118a

The domain in question has a null autorenewPollMessageHistoryId, but
that in itself should not have caused an NPE because we are not
operating on the null pointer. On that line the only possible way to
throw an NPE is for the domain itself to be null, but if that were the
case, the NPE would have been thrown at line 599 where we called a
method on the domain object.

Regardless of the cause, with this PR we are using an explicitly
provided history id and checking for its nullness before using it. If a
similar issue arises again, we should have a better idea why.

Lastly, the way poll message id is constructed is largely simplified in
PollMessageExternalKeyConverter as a result of the removal ofy parent
keys in PollMessage. This does present a possibility of failure when
immediately before deployment, a registrar requests a poll message and
received the old id, but by the time the registrar acks the id, the new
version is deployed and therefore does not recognize the old key. The
likelihood of this happening should be slim, and we could have prevented
it by letting the converter recognize both the old and the new key.
However, we would like to eventually phase out the old key, and in
theory a registrar could ack a poll message at any time after it was
requested. So, there is not a safe time by which all the old ids are
acked, lest we develop some elaborate scheme to keep track of which
messages were sent with an old id when requested and which of these old
ids are acked. Only then can we be truly safe to phase out the old id.
The benefit does not seem to warrant the effort. If a registrar does
encounter a situation like this, they could open a support bug to have
us manually ack the poll message for them.
This commit is contained in:
Lai Jiang 2022-08-19 14:24:03 -04:00 committed by GitHub
parent aea98f4bc3
commit cfa5699cc3
46 changed files with 188 additions and 512 deletions

View file

@ -377,8 +377,7 @@ public final class DomainCreateFlow implements TransactionalFlow {
.setIdnTableName(validateDomainNameWithIdnTables(domainName)) .setIdnTableName(validateDomainNameWithIdnTables(domainName))
.setRegistrationExpirationTime(registrationExpirationTime) .setRegistrationExpirationTime(registrationExpirationTime)
.setAutorenewBillingEvent(autorenewBillingEvent.createVKey()) .setAutorenewBillingEvent(autorenewBillingEvent.createVKey())
.setAutorenewPollMessage( .setAutorenewPollMessage(autorenewPollMessage.createVKey())
autorenewPollMessage.createVKey(), autorenewPollMessage.getHistoryRevisionId())
.setLaunchNotice(hasClaimsNotice ? launchCreate.get().getNotice() : null) .setLaunchNotice(hasClaimsNotice ? launchCreate.get().getNotice() : null)
.setSmdId(signedMarkId) .setSmdId(signedMarkId)
.setDsData(secDnsCreate.map(SecDnsCreateExtension::getDsData).orElse(null)) .setDsData(secDnsCreate.map(SecDnsCreateExtension::getDsData).orElse(null))

View file

@ -263,7 +263,8 @@ public final class DomainDeleteFlow implements TransactionalFlow {
// the updated recurring billing event, we'll need it later and can't reload it. // the updated recurring billing event, we'll need it later and can't reload it.
Recurring existingRecurring = tm().loadByKey(existingDomain.getAutorenewBillingEvent()); Recurring existingRecurring = tm().loadByKey(existingDomain.getAutorenewBillingEvent());
BillingEvent.Recurring recurringBillingEvent = BillingEvent.Recurring recurringBillingEvent =
updateAutorenewRecurrenceEndTime(existingDomain, existingRecurring, now); updateAutorenewRecurrenceEndTime(
existingDomain, existingRecurring, now, domainHistory.getDomainHistoryId());
// If there's a pending transfer, the gaining client's autorenew billing // If there's a pending transfer, the gaining client's autorenew billing
// event and poll message will already have been deleted in // event and poll message will already have been deleted in
// ResourceDeleteFlow since it's listed in serverApproveEntities. // ResourceDeleteFlow since it's listed in serverApproveEntities.

View file

@ -591,7 +591,10 @@ public class DomainFlowUtils {
* <p>Returns the new autorenew recurring billing event. * <p>Returns the new autorenew recurring billing event.
*/ */
public static Recurring updateAutorenewRecurrenceEndTime( public static Recurring updateAutorenewRecurrenceEndTime(
Domain domain, Recurring existingRecurring, DateTime newEndTime) { Domain domain,
Recurring existingRecurring,
DateTime newEndTime,
@Nullable DomainHistoryId historyId) {
Optional<PollMessage.Autorenew> autorenewPollMessage = Optional<PollMessage.Autorenew> autorenewPollMessage =
tm().loadByKeyIfPresent(domain.getAutorenewPollMessage()); tm().loadByKeyIfPresent(domain.getAutorenewPollMessage());
@ -599,20 +602,25 @@ public class DomainFlowUtils {
// create a new one at the same id. This can happen if a transfer was requested on a domain // create a new one at the same id. This can happen if a transfer was requested on a domain
// where all autorenew poll messages had already been delivered (this would cause the poll // where all autorenew poll messages had already been delivered (this would cause the poll
// message to be deleted), and then subsequently the transfer was canceled, rejected, or deleted // message to be deleted), and then subsequently the transfer was canceled, rejected, or deleted
// (which would cause the poll message to be recreated here). // (which would cause the poll message to be recreated here). In the latter case, the history id
PollMessage.Autorenew updatedAutorenewPollMessage = // of the event that created the new poll message will also be used.
autorenewPollMessage.isPresent() PollMessage.Autorenew updatedAutorenewPollMessage;
? autorenewPollMessage.get().asBuilder().setAutorenewEndTime(newEndTime).build() if (autorenewPollMessage.isPresent()) {
: newAutorenewPollMessage(domain) updatedAutorenewPollMessage =
.setId((Long) domain.getAutorenewPollMessage().getSqlKey()) autorenewPollMessage.get().asBuilder().setAutorenewEndTime(newEndTime).build();
.setAutorenewEndTime(newEndTime) } else {
.setDomainHistoryId( checkNotNull(
new DomainHistoryId( historyId, "Cannot create a new autorenew poll message without a domain history id");
domain.getRepoId(), domain.getAutorenewPollMessageHistoryId())) updatedAutorenewPollMessage =
.build(); newAutorenewPollMessage(domain)
.setId((Long) domain.getAutorenewPollMessage().getSqlKey())
.setAutorenewEndTime(newEndTime)
.setDomainHistoryId(historyId)
.build();
}
// If the resultant autorenew poll message would have no poll messages to deliver, then just // If the resultant autorenew poll message would have no poll messages to deliver, then just
// delete it. Otherwise save it with the new end time. // delete it. Otherwise, save it with the new end time.
if (isAtOrAfter(updatedAutorenewPollMessage.getEventTime(), newEndTime)) { if (isAtOrAfter(updatedAutorenewPollMessage.getEventTime(), newEndTime)) {
autorenewPollMessage.ifPresent(autorenew -> tm().delete(autorenew)); autorenewPollMessage.ifPresent(autorenew -> tm().delete(autorenew));
} else { } else {

View file

@ -223,7 +223,11 @@ public final class DomainRenewFlow implements TransactionalFlow {
.build(); .build();
// End the old autorenew billing event and poll message now. This may delete the poll message. // End the old autorenew billing event and poll message now. This may delete the poll message.
Recurring existingRecurring = tm().loadByKey(existingDomain.getAutorenewBillingEvent()); Recurring existingRecurring = tm().loadByKey(existingDomain.getAutorenewBillingEvent());
updateAutorenewRecurrenceEndTime(existingDomain, existingRecurring, now); updateAutorenewRecurrenceEndTime(
existingDomain,
existingRecurring,
now,
new DomainHistoryId(domainHistoryKey.getParent().getName(), domainHistoryKey.getId()));
Domain newDomain = Domain newDomain =
existingDomain existingDomain
.asBuilder() .asBuilder()
@ -231,9 +235,7 @@ public final class DomainRenewFlow implements TransactionalFlow {
.setLastEppUpdateRegistrarId(registrarId) .setLastEppUpdateRegistrarId(registrarId)
.setRegistrationExpirationTime(newExpirationTime) .setRegistrationExpirationTime(newExpirationTime)
.setAutorenewBillingEvent(newAutorenewEvent.createVKey()) .setAutorenewBillingEvent(newAutorenewEvent.createVKey())
.setAutorenewPollMessage( .setAutorenewPollMessage(newAutorenewPollMessage.createVKey())
newAutorenewPollMessage.createVKey(),
newAutorenewPollMessage.getHistoryRevisionId())
.addGracePeriod( .addGracePeriod(
GracePeriod.forBillingEvent( GracePeriod.forBillingEvent(
GracePeriodStatus.RENEW, existingDomain.getRepoId(), explicitRenewEvent)) GracePeriodStatus.RENEW, existingDomain.getRepoId(), explicitRenewEvent))

View file

@ -251,8 +251,7 @@ public final class DomainRestoreRequestFlow implements TransactionalFlow {
.setGracePeriods(null) .setGracePeriods(null)
.setDeletePollMessage(null) .setDeletePollMessage(null)
.setAutorenewBillingEvent(autorenewEvent.createVKey()) .setAutorenewBillingEvent(autorenewEvent.createVKey())
.setAutorenewPollMessage( .setAutorenewPollMessage(autorenewPollMessage.createVKey())
autorenewPollMessage.createVKey(), autorenewPollMessage.getHistoryRevisionId())
// Clear the autorenew end time so if it had expired but is now explicitly being restored, // Clear the autorenew end time so if it had expired but is now explicitly being restored,
// it won't immediately be deleted again. // it won't immediately be deleted again.
.setAutorenewEndTime(Optional.empty()) .setAutorenewEndTime(Optional.empty())

View file

@ -194,7 +194,11 @@ public final class DomainTransferApproveFlow implements TransactionalFlow {
} }
// Close the old autorenew event and poll message at the transfer time (aka now). This may end // Close the old autorenew event and poll message at the transfer time (aka now). This may end
// up deleting the poll message. // up deleting the poll message.
updateAutorenewRecurrenceEndTime(existingDomain, existingRecurring, now); updateAutorenewRecurrenceEndTime(
existingDomain,
existingRecurring,
now,
new DomainHistoryId(domainHistoryKey.getParent().getName(), domainHistoryKey.getId()));
DateTime newExpirationTime = DateTime newExpirationTime =
computeExDateForApprovalTime(existingDomain, now, transferData.getTransferPeriod()); computeExDateForApprovalTime(existingDomain, now, transferData.getTransferPeriod());
// Create a new autorenew event starting at the expiration time. // Create a new autorenew event starting at the expiration time.
@ -240,9 +244,7 @@ public final class DomainTransferApproveFlow implements TransactionalFlow {
.build()) .build())
.setRegistrationExpirationTime(newExpirationTime) .setRegistrationExpirationTime(newExpirationTime)
.setAutorenewBillingEvent(autorenewEvent.createVKey()) .setAutorenewBillingEvent(autorenewEvent.createVKey())
.setAutorenewPollMessage( .setAutorenewPollMessage(gainingClientAutorenewPollMessage.createVKey())
gainingClientAutorenewPollMessage.createVKey(),
gainingClientAutorenewPollMessage.getHistoryRevisionId())
// Remove all the old grace periods and add a new one for the transfer. // Remove all the old grace periods and add a new one for the transfer.
.setGracePeriods( .setGracePeriods(
billingEvent billingEvent

View file

@ -116,7 +116,8 @@ public final class DomainTransferCancelFlow implements TransactionalFlow {
// Reopen the autorenew event and poll message that we closed for the implicit transfer. This // Reopen the autorenew event and poll message that we closed for the implicit transfer. This
// may recreate the autorenew poll message if it was deleted when the transfer request was made. // may recreate the autorenew poll message if it was deleted when the transfer request was made.
Recurring existingRecurring = tm().loadByKey(existingDomain.getAutorenewBillingEvent()); Recurring existingRecurring = tm().loadByKey(existingDomain.getAutorenewBillingEvent());
updateAutorenewRecurrenceEndTime(existingDomain, existingRecurring, END_OF_TIME); updateAutorenewRecurrenceEndTime(
existingDomain, existingRecurring, END_OF_TIME, domainHistory.getDomainHistoryId());
// Delete the billing event and poll messages that were written in case the transfer would have // Delete the billing event and poll messages that were written in case the transfer would have
// been implicitly server approved. // been implicitly server approved.
tm().delete(existingDomain.getTransferData().getServerApproveEntities()); tm().delete(existingDomain.getTransferData().getServerApproveEntities());

View file

@ -117,7 +117,8 @@ public final class DomainTransferRejectFlow implements TransactionalFlow {
// Reopen the autorenew event and poll message that we closed for the implicit transfer. This // Reopen the autorenew event and poll message that we closed for the implicit transfer. This
// may end up recreating the poll message if it was deleted upon the transfer request. // may end up recreating the poll message if it was deleted upon the transfer request.
Recurring existingRecurring = tm().loadByKey(existingDomain.getAutorenewBillingEvent()); Recurring existingRecurring = tm().loadByKey(existingDomain.getAutorenewBillingEvent());
updateAutorenewRecurrenceEndTime(existingDomain, existingRecurring, END_OF_TIME); updateAutorenewRecurrenceEndTime(
existingDomain, existingRecurring, END_OF_TIME, domainHistory.getDomainHistoryId());
// Delete the billing event and poll messages that were written in case the transfer would have // Delete the billing event and poll messages that were written in case the transfer would have
// been implicitly server approved. // been implicitly server approved.
tm().delete(existingDomain.getTransferData().getServerApproveEntities()); tm().delete(existingDomain.getTransferData().getServerApproveEntities());

View file

@ -57,6 +57,7 @@ import google.registry.model.billing.BillingEvent.Recurring;
import google.registry.model.domain.Domain; import google.registry.model.domain.Domain;
import google.registry.model.domain.DomainCommand.Transfer; import google.registry.model.domain.DomainCommand.Transfer;
import google.registry.model.domain.DomainHistory; import google.registry.model.domain.DomainHistory;
import google.registry.model.domain.DomainHistory.DomainHistoryId;
import google.registry.model.domain.Period; import google.registry.model.domain.Period;
import google.registry.model.domain.fee.FeeTransferCommandExtension; import google.registry.model.domain.fee.FeeTransferCommandExtension;
import google.registry.model.domain.fee.FeeTransformResponseExtension; import google.registry.model.domain.fee.FeeTransformResponseExtension;
@ -260,7 +261,11 @@ public final class DomainTransferRequestFlow implements TransactionalFlow {
// the poll message if it has no events left. Note that if the automatic transfer succeeds, then // the poll message if it has no events left. Note that if the automatic transfer succeeds, then
// cloneProjectedAtTime() will replace these old autorenew entities with the server approve ones // cloneProjectedAtTime() will replace these old autorenew entities with the server approve ones
// that we've created in this flow and stored in pendingTransferData. // that we've created in this flow and stored in pendingTransferData.
updateAutorenewRecurrenceEndTime(existingDomain, existingRecurring, automaticTransferTime); updateAutorenewRecurrenceEndTime(
existingDomain,
existingRecurring,
automaticTransferTime,
new DomainHistoryId(domainHistoryKey.getParent().getName(), domainHistoryKey.getId()));
Domain newDomain = Domain newDomain =
existingDomain existingDomain
.asBuilder() .asBuilder()

View file

@ -28,7 +28,6 @@ import google.registry.model.host.HostHistory;
import google.registry.model.index.EppResourceIndex; import google.registry.model.index.EppResourceIndex;
import google.registry.model.index.EppResourceIndexBucket; import google.registry.model.index.EppResourceIndexBucket;
import google.registry.model.index.ForeignKeyIndex; import google.registry.model.index.ForeignKeyIndex;
import google.registry.model.poll.PollMessage;
import google.registry.model.rde.RdeRevision; import google.registry.model.rde.RdeRevision;
import google.registry.model.registrar.Registrar; import google.registry.model.registrar.Registrar;
import google.registry.model.reporting.HistoryEntry; import google.registry.model.reporting.HistoryEntry;
@ -58,9 +57,6 @@ public final class EntityClasses {
Host.class, Host.class,
HostHistory.class, HostHistory.class,
Lock.class, Lock.class,
PollMessage.class,
PollMessage.Autorenew.class,
PollMessage.OneTime.class,
RdeRevision.class, RdeRevision.class,
Registrar.class, Registrar.class,
ServerSecret.class); ServerSecret.class);

View file

@ -90,13 +90,13 @@ public class Domain extends DomainBase implements ForeignKeyedEppResource {
@Access(AccessType.PROPERTY) @Access(AccessType.PROPERTY)
@Column(name = "host_repo_id") @Column(name = "host_repo_id")
public Set<VKey<Host>> getNsHosts() { public Set<VKey<Host>> getNsHosts() {
return super.nsHosts; return nsHosts;
} }
/** /**
* Returns the set of {@link GracePeriod} associated with the domain. * Returns the set of {@link GracePeriod} associated with the domain.
* *
* <p>This is the getter method specific for Hibernate to access the field so it is set to * <p>This is the getter method specific for Hibernate to access the field, so it is set to
* private. The caller can use the public {@link #getGracePeriods()} to get the grace periods. * private. The caller can use the public {@link #getGracePeriods()} to get the grace periods.
* *
* <p>Note that we need to set `insertable = false, updatable = false` for @JoinColumn, otherwise * <p>Note that we need to set `insertable = false, updatable = false` for @JoinColumn, otherwise
@ -104,10 +104,7 @@ public class Domain extends DomainBase implements ForeignKeyedEppResource {
* deleting the whole entry from the table when the {@link GracePeriod} is removed from the set. * deleting the whole entry from the table when the {@link GracePeriod} is removed from the set.
*/ */
@Access(AccessType.PROPERTY) @Access(AccessType.PROPERTY)
@OneToMany( @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, orphanRemoval = true)
cascade = {CascadeType.ALL},
fetch = FetchType.EAGER,
orphanRemoval = true)
@JoinColumn( @JoinColumn(
name = "domainRepoId", name = "domainRepoId",
referencedColumnName = "repoId", referencedColumnName = "repoId",
@ -121,7 +118,7 @@ public class Domain extends DomainBase implements ForeignKeyedEppResource {
/** /**
* Returns the set of {@link DelegationSignerData} associated with the domain. * Returns the set of {@link DelegationSignerData} associated with the domain.
* *
* <p>This is the getter method specific for Hibernate to access the field so it is set to * <p>This is the getter method specific for Hibernate to access the field, so it is set to
* private. The caller can use the public {@link #getDsData()} to get the DS data. * private. The caller can use the public {@link #getDsData()} to get the DS data.
* *
* <p>Note that we need to set `insertable = false, updatable = false` for @JoinColumn, otherwise * <p>Note that we need to set `insertable = false, updatable = false` for @JoinColumn, otherwise
@ -130,10 +127,7 @@ public class Domain extends DomainBase implements ForeignKeyedEppResource {
* the set. * the set.
*/ */
@Access(AccessType.PROPERTY) @Access(AccessType.PROPERTY)
@OneToMany( @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, orphanRemoval = true)
cascade = {CascadeType.ALL},
fetch = FetchType.EAGER,
orphanRemoval = true)
@JoinColumn( @JoinColumn(
name = "domainRepoId", name = "domainRepoId",
referencedColumnName = "repoId", referencedColumnName = "repoId",
@ -182,10 +176,9 @@ public class Domain extends DomainBase implements ForeignKeyedEppResource {
} }
public Builder copyFrom(DomainBase domainBase) { public Builder copyFrom(DomainBase domainBase) {
this.getInstance().copyUpdateTimestamp(domainBase); getInstance().copyUpdateTimestamp(domainBase);
return this.setAuthInfo(domainBase.getAuthInfo()) return setAuthInfo(domainBase.getAuthInfo())
.setAutorenewPollMessage( .setAutorenewPollMessage(domainBase.getAutorenewPollMessage())
domainBase.getAutorenewPollMessage(), domainBase.getAutorenewPollMessageHistoryId())
.setAutorenewBillingEvent(domainBase.getAutorenewBillingEvent()) .setAutorenewBillingEvent(domainBase.getAutorenewBillingEvent())
.setAutorenewEndTime(domainBase.getAutorenewEndTime()) .setAutorenewEndTime(domainBase.getAutorenewEndTime())
.setContacts(domainBase.getContacts()) .setContacts(domainBase.getContacts())

View file

@ -216,13 +216,6 @@ public class DomainBase extends EppResource
@Column(name = "autorenew_poll_message_id") @Column(name = "autorenew_poll_message_id")
VKey<PollMessage.Autorenew> autorenewPollMessage; VKey<PollMessage.Autorenew> autorenewPollMessage;
/**
* History record for the autorenew poll message.
*
* <p>Here so we can restore the original ofy key from sql.
*/
@Ignore Long autorenewPollMessageHistoryId;
/** The unexpired grace periods for this domain (some of which may not be active yet). */ /** The unexpired grace periods for this domain (some of which may not be active yet). */
@Transient Set<GracePeriod> gracePeriods; @Transient Set<GracePeriod> gracePeriods;
@ -322,10 +315,6 @@ public class DomainBase extends EppResource
return autorenewPollMessage; return autorenewPollMessage;
} }
public Long getAutorenewPollMessageHistoryId() {
return autorenewPollMessageHistoryId;
}
public ImmutableSet<GracePeriod> getGracePeriods() { public ImmutableSet<GracePeriod> getGracePeriods() {
return nullToEmptyImmutableCopy(gracePeriods); return nullToEmptyImmutableCopy(gracePeriods);
} }
@ -509,9 +498,7 @@ public class DomainBase extends EppResource
// Set the speculatively-written new autorenew events as the domain's autorenew // Set the speculatively-written new autorenew events as the domain's autorenew
// events. // events.
.setAutorenewBillingEvent(transferData.getServerApproveAutorenewEvent()) .setAutorenewBillingEvent(transferData.getServerApproveAutorenewEvent())
.setAutorenewPollMessage( .setAutorenewPollMessage(transferData.getServerApproveAutorenewPollMessage());
transferData.getServerApproveAutorenewPollMessage(),
transferData.getServerApproveAutorenewPollMessageHistoryId());
if (transferData.getTransferPeriod().getValue() == 1) { if (transferData.getTransferPeriod().getValue() == 1) {
// Set the grace period using a key to the prescheduled transfer billing event. Not using // Set the grace period using a key to the prescheduled transfer billing event. Not using
// GracePeriod.forBillingEvent() here in order to avoid the actual Datastore fetch. // GracePeriod.forBillingEvent() here in order to avoid the actual Datastore fetch.
@ -886,11 +873,8 @@ public class DomainBase extends EppResource
return thisCastToDerived(); return thisCastToDerived();
} }
public B setAutorenewPollMessage( public B setAutorenewPollMessage(@Nullable VKey<PollMessage.Autorenew> autorenewPollMessage) {
@Nullable VKey<PollMessage.Autorenew> autorenewPollMessage,
@Nullable Long autorenewPollMessageHistoryId) {
getInstance().autorenewPollMessage = autorenewPollMessage; getInstance().autorenewPollMessage = autorenewPollMessage;
getInstance().autorenewPollMessageHistoryId = autorenewPollMessageHistoryId;
return thisCastToDerived(); return thisCastToDerived();
} }

View file

@ -20,18 +20,12 @@ import static google.registry.util.DateTimeUtils.END_OF_TIME;
import static google.registry.util.PreconditionsUtils.checkArgumentNotNull; import static google.registry.util.PreconditionsUtils.checkArgumentNotNull;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.googlecode.objectify.Key;
import com.googlecode.objectify.annotation.Entity;
import com.googlecode.objectify.annotation.EntitySubclass;
import com.googlecode.objectify.annotation.Id;
import com.googlecode.objectify.annotation.Ignore;
import com.googlecode.objectify.annotation.Index;
import google.registry.model.Buildable; import google.registry.model.Buildable;
import google.registry.model.EppResource; import google.registry.model.EppResource;
import google.registry.model.ImmutableObject; import google.registry.model.ImmutableObject;
import google.registry.model.UnsafeSerializable; import google.registry.model.UnsafeSerializable;
import google.registry.model.annotations.ExternalMessagingName; import google.registry.model.annotations.ExternalMessagingName;
import google.registry.model.annotations.ReportedOn; import google.registry.model.annotations.OfyIdAllocation;
import google.registry.model.contact.ContactHistory; import google.registry.model.contact.ContactHistory;
import google.registry.model.contact.ContactHistory.ContactHistoryId; import google.registry.model.contact.ContactHistory.ContactHistoryId;
import google.registry.model.contact.ContactResource; import google.registry.model.contact.ContactResource;
@ -55,16 +49,19 @@ import google.registry.persistence.VKey;
import google.registry.persistence.WithLongVKey; import google.registry.persistence.WithLongVKey;
import google.registry.util.NullIgnoringCollectionBuilder; import google.registry.util.NullIgnoringCollectionBuilder;
import java.util.Optional; import java.util.Optional;
import javax.annotation.Nullable;
import javax.persistence.AttributeOverride; import javax.persistence.AttributeOverride;
import javax.persistence.AttributeOverrides; import javax.persistence.AttributeOverrides;
import javax.persistence.Column; import javax.persistence.Column;
import javax.persistence.DiscriminatorColumn; import javax.persistence.DiscriminatorColumn;
import javax.persistence.DiscriminatorValue; import javax.persistence.DiscriminatorValue;
import javax.persistence.Embedded; import javax.persistence.Embedded;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Index;
import javax.persistence.Inheritance; import javax.persistence.Inheritance;
import javax.persistence.InheritanceType; import javax.persistence.InheritanceType;
import javax.persistence.PostLoad; import javax.persistence.PostLoad;
import javax.persistence.Table;
import org.joda.time.DateTime; import org.joda.time.DateTime;
/** /**
@ -76,10 +73,10 @@ import org.joda.time.DateTime;
* retained for historical purposes, poll messages are truly deleted once they have been delivered * retained for historical purposes, poll messages are truly deleted once they have been delivered
* and ACKed. * and ACKed.
* *
* <p>Poll messages are parented off of the {@link HistoryEntry} that resulted in their creation. * <p>Poll messages have a reference to the revision id of the {@link HistoryEntry} that resulted in
* This means that poll messages are contained in the Datastore entity group of the parent {@link * their creation or re-creation, in case of transfer cancellation/rejection. The revision ids are
* EppResource} (which can be a domain, contact, or host). It is thus possible to perform a strongly * not used directly by the Java code, but their presence in the database makes it easier to
* consistent query to find all poll messages associated with a given EPP resource. * diagnose potential issues related to poll messages.
* *
* <p>Poll messages are identified externally by registrars using the format defined in {@link * <p>Poll messages are identified externally by registrars using the format defined in {@link
* PollMessageExternalKeyConverter}. * PollMessageExternalKeyConverter}.
@ -88,16 +85,10 @@ import org.joda.time.DateTime;
* Command</a> * Command</a>
*/ */
@Entity @Entity
@ReportedOn
@ExternalMessagingName("message") @ExternalMessagingName("message")
@javax.persistence.Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE) @Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "type") @DiscriminatorColumn(name = "type")
@javax.persistence.Table( @Table(indexes = {@Index(columnList = "registrar_id"), @Index(columnList = "eventTime")})
indexes = {
@javax.persistence.Index(columnList = "registrar_id"),
@javax.persistence.Index(columnList = "eventTime")
})
public abstract class PollMessage extends ImmutableObject public abstract class PollMessage extends ImmutableObject
implements Buildable, TransferServerApproveEntity, UnsafeSerializable { implements Buildable, TransferServerApproveEntity, UnsafeSerializable {
@ -108,9 +99,9 @@ public abstract class PollMessage extends ImmutableObject
HOST(3L, Host.class); HOST(3L, Host.class);
private final long id; private final long id;
private final Class<?> clazz; private final Class<? extends EppResource> clazz;
Type(long id, Class<?> clazz) { Type(long id, Class<? extends EppResource> clazz) {
this.id = id; this.id = id;
this.clazz = clazz; this.clazz = clazz;
} }
@ -124,58 +115,40 @@ public abstract class PollMessage extends ImmutableObject
} }
/** Returns the class of the underlying resource for the poll message type. */ /** Returns the class of the underlying resource for the poll message type. */
public Class<?> getResourceClass() { public Class<? extends EppResource> getResourceClass() {
return clazz; return clazz;
} }
/**
* Returns the type specified by the identifer, {@code Optional.empty()} if the id is out of
* range.
*/
public static Optional<Type> fromId(long id) {
for (Type val : values()) {
if (val.id == id) {
return Optional.of(val);
}
}
return Optional.empty();
}
} }
/** Entity id. */ /** Entity id. */
@Id @Id
@javax.persistence.Id @OfyIdAllocation
@Column(name = "poll_message_id") @Column(name = "poll_message_id")
Long id; Long id;
/** The registrar that this poll message will be delivered to. */ /** The registrar that this poll message will be delivered to. */
@Index
@Column(name = "registrar_id", nullable = false) @Column(name = "registrar_id", nullable = false)
String clientId; String clientId;
/** The time when the poll message should be delivered. May be in the future. */ /** The time when the poll message should be delivered. May be in the future. */
@Index
@Column(nullable = false) @Column(nullable = false)
DateTime eventTime; DateTime eventTime;
/** Human readable message that will be returned with this poll message. */ /** Human-readable message that will be returned with this poll message. */
@Column(name = "message") @Column(name = "message")
String msg; String msg;
// TODO(b/456803336): Replace these fields with {Domain,Contact,Host}HistoryId objects. String domainRepoId;
@Ignore String domainRepoId; String contactRepoId;
@Ignore String contactRepoId; String hostRepoId;
@Ignore String hostRepoId; Long domainHistoryRevisionId;
@Ignore Long domainHistoryRevisionId; Long contactHistoryRevisionId;
@Ignore Long contactHistoryRevisionId; Long hostHistoryRevisionId;
@Ignore Long hostHistoryRevisionId;
public Long getId() { public Long getId() {
return id; return id;
@ -228,32 +201,22 @@ public abstract class PollMessage extends ImmutableObject
* the resource. * the resource.
*/ */
public String getResourceName() { public String getResourceName() {
return domainRepoId != null return domainRepoId != null ? domainRepoId : contactRepoId != null ? contactRepoId : hostRepoId;
? domainRepoId
: (contactRepoId != null ? contactRepoId : hostRepoId);
} }
/** Gets the underlying history revision id, regardless of the type of the resource. */ /** Gets the underlying history revision id, regardless of the type of the resource. */
public Long getHistoryRevisionId() { public Long getHistoryRevisionId() {
return domainHistoryRevisionId != null return domainHistoryRevisionId != null
? domainHistoryRevisionId ? domainHistoryRevisionId
: (contactHistoryRevisionId != null ? contactHistoryRevisionId : hostHistoryRevisionId); : contactHistoryRevisionId != null ? contactHistoryRevisionId : hostHistoryRevisionId;
} }
public Type getType() { public Type getType() {
return domainRepoId != null ? Type.DOMAIN : (contactRepoId != null ? Type.CONTACT : Type.HOST); return domainRepoId != null ? Type.DOMAIN : contactRepoId != null ? Type.CONTACT : Type.HOST;
} }
public abstract ImmutableList<ResponseData> getResponseData(); public abstract ImmutableList<ResponseData> getResponseData();
@Override
public abstract VKey<? extends PollMessage> createVKey();
/** Static VKey factory method for use by VKeyTranslatorFactory. */
public static VKey<PollMessage> createVKey(Key<PollMessage> key) {
return VKey.create(PollMessage.class, key.getId(), key);
}
/** Override Buildable.asBuilder() to give this method stronger typing. */ /** Override Buildable.asBuilder() to give this method stronger typing. */
@Override @Override
public abstract Builder<?, ?> asBuilder(); public abstract Builder<?, ?> asBuilder();
@ -318,9 +281,11 @@ public abstract class PollMessage extends ImmutableObject
// Set the appropriate field based on the history entry type. // Set the appropriate field based on the history entry type.
if (history instanceof DomainHistory) { if (history instanceof DomainHistory) {
return setDomainHistoryId(((DomainHistory) history).getDomainHistoryId()); return setDomainHistoryId(((DomainHistory) history).getDomainHistoryId());
} else if (history instanceof ContactHistory) { }
if (history instanceof ContactHistory) {
return setContactHistoryId(((ContactHistory) history).getContactHistoryId()); return setContactHistoryId(((ContactHistory) history).getContactHistoryId());
} else if (history instanceof HostHistory) { }
if (history instanceof HostHistory) {
return setHostHistoryId(((HostHistory) history).getHostHistoryId()); return setHostHistoryId(((HostHistory) history).getHostHistoryId());
} }
return thisCastToDerived(); return thisCastToDerived();
@ -330,7 +295,7 @@ public abstract class PollMessage extends ImmutableObject
* Given an array containing pairs of objects, verifies that both members of exactly one of the * Given an array containing pairs of objects, verifies that both members of exactly one of the
* pairs is non-null. * pairs is non-null.
*/ */
private boolean exactlyOnePairNonNull(Object... pairs) { private static boolean exactlyOnePairNonNull(Object... pairs) {
int count = 0; int count = 0;
checkArgument(pairs.length % 2 == 0, "Odd number of arguments provided."); checkArgument(pairs.length % 2 == 0, "Odd number of arguments provided.");
for (int i = 0; i < pairs.length; i += 2) { for (int i = 0; i < pairs.length; i += 2) {
@ -360,9 +325,9 @@ public abstract class PollMessage extends ImmutableObject
instance.contactHistoryRevisionId, instance.contactHistoryRevisionId,
instance.hostRepoId, instance.hostRepoId,
instance.hostHistoryRevisionId), instance.hostHistoryRevisionId),
"the repo id and history revision id must be defined for exactly one of domain, " "The repo id and history revision id must be defined for exactly one of domain, "
+ "contact or host: " + "contact or host: %s",
+ instance); instance);
return super.build(); return super.build();
} }
} }
@ -372,13 +337,11 @@ public abstract class PollMessage extends ImmutableObject
* *
* <p>One-time poll messages are deleted from Datastore once they have been delivered and ACKed. * <p>One-time poll messages are deleted from Datastore once they have been delivered and ACKed.
*/ */
@EntitySubclass(index = false) @Entity
@javax.persistence.Entity
@DiscriminatorValue("ONE_TIME") @DiscriminatorValue("ONE_TIME")
@WithLongVKey(compositeKey = true) @WithLongVKey(compositeKey = true)
public static class OneTime extends PollMessage { public static class OneTime extends PollMessage {
@Ignore
@Embedded @Embedded
@AttributeOverrides({ @AttributeOverrides({
@AttributeOverride( @AttributeOverride(
@ -399,7 +362,6 @@ public abstract class PollMessage extends ImmutableObject
}) })
PendingActionNotificationResponse pendingActionNotificationResponse; PendingActionNotificationResponse pendingActionNotificationResponse;
@Ignore
@Embedded @Embedded
@AttributeOverrides({ @AttributeOverrides({
@AttributeOverride( @AttributeOverride(
@ -420,35 +382,21 @@ public abstract class PollMessage extends ImmutableObject
}) })
TransferResponse transferResponse; TransferResponse transferResponse;
@Ignore
@Column(name = "transfer_response_domain_name") @Column(name = "transfer_response_domain_name")
String fullyQualifiedDomainName; String fullyQualifiedDomainName;
@Ignore
@Column(name = "transfer_response_domain_expiration_time") @Column(name = "transfer_response_domain_expiration_time")
DateTime extendedRegistrationExpirationTime; DateTime extendedRegistrationExpirationTime;
@Ignore
@Column(name = "transfer_response_contact_id") @Column(name = "transfer_response_contact_id")
String contactId; String contactId;
@Ignore
@Column(name = "transfer_response_host_id") @Column(name = "transfer_response_host_id")
String hostId; String hostId;
@Override @Override
public VKey<OneTime> createVKey() { public VKey<OneTime> createVKey() {
return VKey.create(OneTime.class, getId(), Key.create(this)); return VKey.createSql(OneTime.class, getId());
}
/** Converts an unspecialized VKey&lt;PollMessage&gt; to a VKey of the derived class. */
public static @Nullable VKey<OneTime> convertVKey(@Nullable VKey<? extends PollMessage> key) {
if (key == null) {
return null;
}
Key<OneTime> ofyKey =
Key.create(key.getOfyKey().getParent(), OneTime.class, key.getOfyKey().getId());
return VKey.create(OneTime.class, key.getSqlKey(), ofyKey);
} }
@Override @Override
@ -525,8 +473,7 @@ public abstract class PollMessage extends ImmutableObject
/** A builder for {@link OneTime} since it is immutable. */ /** A builder for {@link OneTime} since it is immutable. */
public static class Builder extends PollMessage.Builder<OneTime, Builder> { public static class Builder extends PollMessage.Builder<OneTime, Builder> {
public Builder() { public Builder() {}
}
private Builder(OneTime instance) { private Builder(OneTime instance) {
super(instance); super(instance);
@ -587,14 +534,13 @@ public abstract class PollMessage extends ImmutableObject
} }
/** /**
* An auto-renew poll message which recurs annually. * An autorenew poll message which recurs annually.
* *
* <p>Auto-renew poll messages are not deleted until the registration of their parent domain has * <p>Auto-renew poll messages are not deleted until the registration of their parent domain has
* been canceled, because there will always be a speculative renewal for next year until that * been canceled, because there will always be a speculative renewal for next year until that
* happens. * happens.
*/ */
@EntitySubclass(index = false) @Entity
@javax.persistence.Entity
@DiscriminatorValue("AUTORENEW") @DiscriminatorValue("AUTORENEW")
@WithLongVKey(compositeKey = true) @WithLongVKey(compositeKey = true)
public static class Autorenew extends PollMessage { public static class Autorenew extends PollMessage {
@ -604,7 +550,6 @@ public abstract class PollMessage extends ImmutableObject
String targetId; String targetId;
/** The autorenew recurs annually between {@link #eventTime} and this time. */ /** The autorenew recurs annually between {@link #eventTime} and this time. */
@Index
DateTime autorenewEndTime; DateTime autorenewEndTime;
public String getTargetId() { public String getTargetId() {
@ -617,25 +562,14 @@ public abstract class PollMessage extends ImmutableObject
@Override @Override
public VKey<Autorenew> createVKey() { public VKey<Autorenew> createVKey() {
return VKey.create(Autorenew.class, getId(), Key.create(this)); return VKey.createSql(Autorenew.class, getId());
}
/** Converts an unspecialized VKey&lt;PollMessage&gt; to a VKey of the derived class. */
public static @Nullable VKey<Autorenew> convertVKey(VKey<? extends PollMessage> key) {
if (key == null) {
return null;
}
Key<Autorenew> ofyKey =
Key.create(key.getOfyKey().getParent(), Autorenew.class, key.getOfyKey().getId());
return VKey.create(Autorenew.class, key.getSqlKey(), ofyKey);
} }
@Override @Override
public ImmutableList<ResponseData> getResponseData() { public ImmutableList<ResponseData> getResponseData() {
// Note that the event time is when the auto-renew occured, so the expiration time in the // Note that the event time is when the autorenew occurred, so the expiration time in the
// response should be 1 year past that, since it denotes the new expiration time. // response should be 1 year past that, since it denotes the new expiration time.
return ImmutableList.of( return ImmutableList.of(DomainRenewData.create(getTargetId(), getEventTime().plusYears(1)));
DomainRenewData.create(getTargetId(), getEventTime().plusYears(1)));
} }
@Override @Override

View file

@ -14,48 +14,38 @@
package google.registry.model.poll; package google.registry.model.poll;
import com.google.common.base.Splitter; import com.google.common.base.Splitter;
import com.googlecode.objectify.Key;
import google.registry.model.reporting.HistoryEntry;
import google.registry.persistence.VKey; import google.registry.persistence.VKey;
import java.util.List; import java.util.List;
/** /**
* A converter between external key strings for {@link PollMessage}s (i.e. what registrars use to * A converter between external key strings for {@link PollMessage}s (i.e. what registrars use to
* identify and ACK them) and Datastore keys to the resource. * identify and ACK them) and {@link VKey}s to the resource.
* *
* <p>The format of the key string is A-B-C-D-E-F as follows: * <p>The format of the key string is A-B as follows:
* *
* <pre> * <pre>
* A = EppResource.typeId (decimal) * A = PollMessage.id (decimal)
* B = EppResource.repoId prefix (STRING) * B = PollMessage.eventTime (decimal, year only)
* C = EppResource.repoId suffix (STRING)
* D = HistoryEntry.id (decimal)
* E = PollMessage.id (decimal)
* F = PollMessage.eventTime (decimal, year only)
* </pre> * </pre>
* *
* <p>A typical poll message ID might thus look like: 1-FE0F22-TLD-10071463070-10072612074-2018 * <p>A typical poll message ID might thus look like: 10072612074-2018
*/ */
public class PollMessageExternalKeyConverter { public final class PollMessageExternalKeyConverter {
/** An exception thrown when an external key cannot be parsed. */ /** An exception thrown when an external key cannot be parsed. */
public static class PollMessageExternalKeyParseException extends RuntimeException {} public static class PollMessageExternalKeyParseException extends RuntimeException {
private static final long serialVersionUID = 9026397649048831777L;
}
/** Returns an external poll message ID for the given poll message. */ /** Returns an external poll message ID for the given poll message. */
public static String makePollMessageExternalId(PollMessage pollMessage) { public static String makePollMessageExternalId(PollMessage pollMessage) {
return String.format( return String.format("%d-%d", pollMessage.getId(), pollMessage.getEventTime().getYear());
"%d-%s-%d-%d-%d",
pollMessage.getType().getId(),
pollMessage.getResourceName(),
pollMessage.getHistoryRevisionId(),
pollMessage.getId(),
pollMessage.getEventTime().getYear());
} }
/** /**
* Returns an Objectify Key to a PollMessage corresponding with the external ID. * Returns a {@link VKey} to a {@link PollMessage} corresponding with the external ID.
* *
* <p>Note that the year field that is included at the end of the poll message isn't actually used * <p>Note that the year field that is included at the end of the poll message isn't actually used
* for anything; it exists solely to create unique externally visible IDs for autorenews. We thus * for anything; it exists solely to create unique externally visible IDs for autorenews. We thus
@ -66,26 +56,13 @@ public class PollMessageExternalKeyConverter {
*/ */
public static VKey<PollMessage> parsePollMessageExternalId(String externalKey) { public static VKey<PollMessage> parsePollMessageExternalId(String externalKey) {
List<String> idComponents = Splitter.on('-').splitToList(externalKey); List<String> idComponents = Splitter.on('-').splitToList(externalKey);
if (idComponents.size() != 6) { if (idComponents.size() != 2) {
throw new PollMessageExternalKeyParseException(); throw new PollMessageExternalKeyParseException();
} }
try { try {
Class<?> resourceClazz = Long id = Long.parseLong(idComponents.get(0));
PollMessage.Type.fromId(Long.parseLong(idComponents.get(0))) return VKey.createSql(PollMessage.class, id);
.orElseThrow(() -> new PollMessageExternalKeyParseException()) // Note that idComponents.get(1) is entirely ignored; we never use the year field internally.
.getResourceClass();
return VKey.from(
Key.create(
Key.create(
Key.create(
null,
resourceClazz,
String.format("%s-%s", idComponents.get(1), idComponents.get(2))),
HistoryEntry.class,
Long.parseLong(idComponents.get(3))),
PollMessage.class,
Long.parseLong(idComponents.get(4))));
// Note that idComponents.get(5) is entirely ignored; we never use the year field internally.
} catch (NumberFormatException e) { } catch (NumberFormatException e) {
throw new PollMessageExternalKeyParseException(); throw new PollMessageExternalKeyParseException();
} }

View file

@ -54,7 +54,7 @@ import org.joda.time.DateTime;
* <p>This removes years off a domain's registration period. Note that the expiration time cannot be * <p>This removes years off a domain's registration period. Note that the expiration time cannot be
* set to prior than the present. Reversal of the charges for these years (if desired) must happen * set to prior than the present. Reversal of the charges for these years (if desired) must happen
* out of band, as they may already have been billed out and thus cannot and won't be reversed in * out of band, as they may already have been billed out and thus cannot and won't be reversed in
* Datastore. * the database.
*/ */
@Parameters(separators = " =", commandDescription = "Unrenew a domain.") @Parameters(separators = " =", commandDescription = "Unrenew a domain.")
@NonFinalForTesting @NonFinalForTesting
@ -217,7 +217,8 @@ class UnrenewDomainCommand extends ConfirmingCommand implements CommandWithRemot
.build(); .build();
// End the old autorenew billing event and poll message now. // End the old autorenew billing event and poll message now.
Recurring existingRecurring = tm().loadByKey(domain.getAutorenewBillingEvent()); Recurring existingRecurring = tm().loadByKey(domain.getAutorenewBillingEvent());
updateAutorenewRecurrenceEndTime(domain, existingRecurring, now); updateAutorenewRecurrenceEndTime(
domain, existingRecurring, now, domainHistory.getDomainHistoryId());
Domain newDomain = Domain newDomain =
domain domain
.asBuilder() .asBuilder()
@ -225,9 +226,7 @@ class UnrenewDomainCommand extends ConfirmingCommand implements CommandWithRemot
.setLastEppUpdateTime(now) .setLastEppUpdateTime(now)
.setLastEppUpdateRegistrarId(domain.getCurrentSponsorRegistrarId()) .setLastEppUpdateRegistrarId(domain.getCurrentSponsorRegistrarId())
.setAutorenewBillingEvent(newAutorenewEvent.createVKey()) .setAutorenewBillingEvent(newAutorenewEvent.createVKey())
.setAutorenewPollMessage( .setAutorenewPollMessage(newAutorenewPollMessage.createVKey())
newAutorenewPollMessage.createVKey(),
newAutorenewPollMessage.getHistoryRevisionId())
.build(); .build();
// In order to do it'll need to write out a new HistoryEntry (likely of type SYNTHETIC), a new // In order to do it'll need to write out a new HistoryEntry (likely of type SYNTHETIC), a new
// autorenew billing event and poll message, and a new one time poll message at the present time // autorenew billing event and poll message, and a new one time poll message at the present time

View file

@ -179,8 +179,7 @@ class DeleteExpiredDomainsActionTest {
.asBuilder() .asBuilder()
.setAutorenewEndTime(Optional.of(clock.nowUtc().minusDays(10))) .setAutorenewEndTime(Optional.of(clock.nowUtc().minusDays(10)))
.setAutorenewBillingEvent(autorenewBillingEvent.createVKey()) .setAutorenewBillingEvent(autorenewBillingEvent.createVKey())
.setAutorenewPollMessage( .setAutorenewPollMessage(autorenewPollMessage.createVKey())
autorenewPollMessage.createVKey(), autorenewPollMessage.getHistoryRevisionId())
.build()); .build());
return pendingExpirationDomain; return pendingExpirationDomain;

View file

@ -95,7 +95,7 @@ class EppLifecycleContactTest extends EppTestCase {
.hasCommandName("PollRequest") .hasCommandName("PollRequest")
.and() .and()
.hasStatus(SUCCESS_WITH_ACK_MESSAGE); .hasStatus(SUCCESS_WITH_ACK_MESSAGE);
assertThatCommand("poll_ack.xml", ImmutableMap.of("ID", "2-1-ROID-3-6-2000")) assertThatCommand("poll_ack.xml", ImmutableMap.of("ID", "6-2000"))
.atTime("2000-06-08T22:02:00Z") .atTime("2000-06-08T22:02:00Z")
.hasResponse("poll_ack_response_empty.xml"); .hasResponse("poll_ack_response_empty.xml");
assertThat(getRecordedEppMetric()) assertThat(getRecordedEppMetric())

View file

@ -747,11 +747,11 @@ class EppLifecycleDomainTest extends EppTestCase {
.hasResponse( .hasResponse(
"poll_response_autorenew.xml", "poll_response_autorenew.xml",
ImmutableMap.of( ImmutableMap.of(
"ID", "1-B-EXAMPLE-12-15-2002", "ID", "15-2002",
"QDATE", "2002-06-01T00:04:00Z", "QDATE", "2002-06-01T00:04:00Z",
"DOMAIN", "fakesite.example", "DOMAIN", "fakesite.example",
"EXDATE", "2003-06-01T00:04:00Z")); "EXDATE", "2003-06-01T00:04:00Z"));
assertThatCommand("poll_ack.xml", ImmutableMap.of("ID", "1-B-EXAMPLE-12-15-2002")) assertThatCommand("poll_ack.xml", ImmutableMap.of("ID", "15-2002"))
.atTime("2002-07-01T00:02:00Z") .atTime("2002-07-01T00:02:00Z")
.hasResponse("poll_ack_response_empty.xml"); .hasResponse("poll_ack_response_empty.xml");
@ -765,13 +765,13 @@ class EppLifecycleDomainTest extends EppTestCase {
.hasResponse( .hasResponse(
"poll_response_autorenew.xml", "poll_response_autorenew.xml",
ImmutableMap.of( ImmutableMap.of(
"ID", "1-B-EXAMPLE-12-15-2003", // Note -- Year is different from previous ID. "ID", "15-2003", // Note -- Year is different from previous ID.
"QDATE", "2003-06-01T00:04:00Z", "QDATE", "2003-06-01T00:04:00Z",
"DOMAIN", "fakesite.example", "DOMAIN", "fakesite.example",
"EXDATE", "2004-06-01T00:04:00Z")); "EXDATE", "2004-06-01T00:04:00Z"));
// Ack the second poll message and verify that none remain. // Ack the second poll message and verify that none remain.
assertThatCommand("poll_ack.xml", ImmutableMap.of("ID", "1-B-EXAMPLE-12-15-2003")) assertThatCommand("poll_ack.xml", ImmutableMap.of("ID", "15-2003"))
.atTime("2003-07-01T00:05:05Z") .atTime("2003-07-01T00:05:05Z")
.hasResponse("poll_ack_response_empty.xml"); .hasResponse("poll_ack_response_empty.xml");
assertThatCommand("poll.xml") assertThatCommand("poll.xml")
@ -801,7 +801,7 @@ class EppLifecycleDomainTest extends EppTestCase {
// As the losing registrar, read the request poll message, and then ack it. // As the losing registrar, read the request poll message, and then ack it.
assertThatLoginSucceeds("NewRegistrar", "foo-BAR2"); assertThatLoginSucceeds("NewRegistrar", "foo-BAR2");
String messageId = "1-B-EXAMPLE-18-24-2001"; String messageId = "24-2001";
assertThatCommand("poll.xml") assertThatCommand("poll.xml")
.atTime("2001-01-01T00:01:00Z") .atTime("2001-01-01T00:01:00Z")
.hasResponse("poll_response_domain_transfer_request.xml", ImmutableMap.of("ID", messageId)); .hasResponse("poll_response_domain_transfer_request.xml", ImmutableMap.of("ID", messageId));
@ -810,7 +810,7 @@ class EppLifecycleDomainTest extends EppTestCase {
.hasResponse("poll_ack_response_empty.xml"); .hasResponse("poll_ack_response_empty.xml");
// Five days in the future, expect a server approval poll message to the loser, and ack it. // Five days in the future, expect a server approval poll message to the loser, and ack it.
messageId = "1-B-EXAMPLE-18-23-2001"; messageId = "23-2001";
assertThatCommand("poll.xml") assertThatCommand("poll.xml")
.atTime("2001-01-06T00:01:00Z") .atTime("2001-01-06T00:01:00Z")
.hasResponse( .hasResponse(
@ -822,7 +822,7 @@ class EppLifecycleDomainTest extends EppTestCase {
assertThatLogoutSucceeds(); assertThatLogoutSucceeds();
// Also expect a server approval poll message to the winner, with the transfer request trid. // Also expect a server approval poll message to the winner, with the transfer request trid.
messageId = "1-B-EXAMPLE-18-22-2001"; messageId = "22-2001";
assertThatLoginSucceeds("TheRegistrar", "password2"); assertThatLoginSucceeds("TheRegistrar", "password2");
assertThatCommand("poll.xml") assertThatCommand("poll.xml")
.atTime("2001-01-06T00:02:00Z") .atTime("2001-01-06T00:02:00Z")

View file

@ -147,8 +147,7 @@ class DomainDeleteFlowTest extends ResourceFlowTestCase<DomainDeleteFlow, Domain
domain domain
.asBuilder() .asBuilder()
.setAutorenewBillingEvent(autorenewBillingEvent.createVKey()) .setAutorenewBillingEvent(autorenewBillingEvent.createVKey())
.setAutorenewPollMessage( .setAutorenewPollMessage(autorenewPollMessage.createVKey())
autorenewPollMessage.createVKey(), autorenewPollMessage.getHistoryRevisionId())
.build()); .build());
assertTransactionalFlow(true); assertTransactionalFlow(true);
@ -214,8 +213,7 @@ class DomainDeleteFlowTest extends ResourceFlowTestCase<DomainDeleteFlow, Domain
"TheRegistrar", "TheRegistrar",
autorenewBillingEvent.createVKey()))) autorenewBillingEvent.createVKey())))
.setAutorenewBillingEvent(autorenewBillingEvent.createVKey()) .setAutorenewBillingEvent(autorenewBillingEvent.createVKey())
.setAutorenewPollMessage( .setAutorenewPollMessage(autorenewPollMessage.createVKey())
autorenewPollMessage.createVKey(), autorenewPollMessage.getHistoryRevisionId())
.build()); .build());
assertTransactionalFlow(true); assertTransactionalFlow(true);
} }

View file

@ -181,9 +181,7 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, Domain>
.setRegistrationExpirationTime(expirationTime) .setRegistrationExpirationTime(expirationTime)
.setStatusValues(ImmutableSet.copyOf(statusValues)) .setStatusValues(ImmutableSet.copyOf(statusValues))
.setAutorenewBillingEvent(autorenewEvent.createVKey()) .setAutorenewBillingEvent(autorenewEvent.createVKey())
.setAutorenewPollMessage( .setAutorenewPollMessage(autorenewPollMessage.createVKey())
autorenewPollMessage.createVKey(),
autorenewPollMessage.getHistoryRevisionId())
.build(); .build();
persistResources( persistResources(
ImmutableSet.of( ImmutableSet.of(

View file

@ -162,7 +162,7 @@ class DomainTransferCancelFlowTest
.setEventTime(originalExpirationTime) .setEventTime(originalExpirationTime)
.setAutorenewEndTime(END_OF_TIME) .setAutorenewEndTime(END_OF_TIME)
.setMsg("Domain was auto-renewed.") .setMsg("Domain was auto-renewed.")
.setHistoryEntry(getOnlyHistoryEntryOfType(domain, DOMAIN_CREATE)) .setHistoryEntry(getOnlyHistoryEntryOfType(domain, DOMAIN_TRANSFER_CANCEL))
.build(), .build(),
new PollMessage.OneTime.Builder() new PollMessage.OneTime.Builder()
.setRegistrarId("TheRegistrar") .setRegistrarId("TheRegistrar")

View file

@ -47,7 +47,7 @@ class PollAckFlowTest extends FlowTestCase<PollAckFlow> {
@BeforeEach @BeforeEach
void setUp() { void setUp() {
setEppInput("poll_ack.xml", ImmutableMap.of("MSGID", "1-3-EXAMPLE-4-3-2011")); setEppInput("poll_ack.xml", ImmutableMap.of("MSGID", "3-2011"));
clock.setTo(DateTime.parse("2011-01-02T01:01:01Z")); clock.setTo(DateTime.parse("2011-01-02T01:01:01Z"));
setRegistrarIdForFlow("NewRegistrar"); setRegistrarIdForFlow("NewRegistrar");
createTld("example"); createTld("example");
@ -87,7 +87,7 @@ class PollAckFlowTest extends FlowTestCase<PollAckFlow> {
@Test @Test
void testSuccess_contactPollMessage() throws Exception { void testSuccess_contactPollMessage() throws Exception {
setEppInput("poll_ack.xml", ImmutableMap.of("MSGID", "2-2-ROID-4-3-2011")); setEppInput("poll_ack.xml", ImmutableMap.of("MSGID", "3-2011"));
persistResource( persistResource(
new PollMessage.OneTime.Builder() new PollMessage.OneTime.Builder()
.setId(MESSAGE_ID) .setId(MESSAGE_ID)
@ -102,7 +102,7 @@ class PollAckFlowTest extends FlowTestCase<PollAckFlow> {
@Test @Test
void testFailure_contactPollMessage_withIncorrectYearField() throws Exception { void testFailure_contactPollMessage_withIncorrectYearField() throws Exception {
setEppInput("poll_ack.xml", ImmutableMap.of("MSGID", "2-2-ROID-4-3-1999")); setEppInput("poll_ack.xml", ImmutableMap.of("MSGID", "3-1999"));
persistResource( persistResource(
new PollMessage.OneTime.Builder() new PollMessage.OneTime.Builder()
.setId(MESSAGE_ID) .setId(MESSAGE_ID)
@ -124,7 +124,7 @@ class PollAckFlowTest extends FlowTestCase<PollAckFlow> {
@Test @Test
void testSuccess_recentActiveAutorenew() throws Exception { void testSuccess_recentActiveAutorenew() throws Exception {
setEppInput("poll_ack.xml", ImmutableMap.of("MSGID", "1-3-EXAMPLE-4-3-2010")); setEppInput("poll_ack.xml", ImmutableMap.of("MSGID", "3-2010"));
persistAutorenewPollMessage(clock.nowUtc().minusMonths(6), END_OF_TIME); persistAutorenewPollMessage(clock.nowUtc().minusMonths(6), END_OF_TIME);
assertTransactionalFlow(true); assertTransactionalFlow(true);
runFlowAssertResponse(loadFile("poll_ack_response_empty.xml")); runFlowAssertResponse(loadFile("poll_ack_response_empty.xml"));
@ -132,7 +132,7 @@ class PollAckFlowTest extends FlowTestCase<PollAckFlow> {
@Test @Test
void testSuccess_oldActiveAutorenew() throws Exception { void testSuccess_oldActiveAutorenew() throws Exception {
setEppInput("poll_ack.xml", ImmutableMap.of("MSGID", "1-3-EXAMPLE-4-3-2009")); setEppInput("poll_ack.xml", ImmutableMap.of("MSGID", "3-2009"));
persistAutorenewPollMessage(clock.nowUtc().minusYears(2), END_OF_TIME); persistAutorenewPollMessage(clock.nowUtc().minusYears(2), END_OF_TIME);
// Create three other messages to be queued for retrieval to get our count right, since the poll // Create three other messages to be queued for retrieval to get our count right, since the poll
// ack response wants there to be 4 messages in the queue when the ack comes back. // ack response wants there to be 4 messages in the queue when the ack comes back.
@ -141,14 +141,12 @@ class PollAckFlowTest extends FlowTestCase<PollAckFlow> {
} }
assertTransactionalFlow(true); assertTransactionalFlow(true);
runFlowAssertResponse( runFlowAssertResponse(
loadFile( loadFile("poll_ack_response.xml", ImmutableMap.of("MSGID", "3-2009", "COUNT", "4")));
"poll_ack_response.xml",
ImmutableMap.of("MSGID", "1-3-EXAMPLE-4-3-2009", "COUNT", "4")));
} }
@Test @Test
void testSuccess_oldInactiveAutorenew() throws Exception { void testSuccess_oldInactiveAutorenew() throws Exception {
setEppInput("poll_ack.xml", ImmutableMap.of("MSGID", "1-3-EXAMPLE-4-3-2010")); setEppInput("poll_ack.xml", ImmutableMap.of("MSGID", "3-2010"));
persistAutorenewPollMessage(clock.nowUtc().minusMonths(6), clock.nowUtc()); persistAutorenewPollMessage(clock.nowUtc().minusMonths(6), clock.nowUtc());
assertTransactionalFlow(true); assertTransactionalFlow(true);
runFlowAssertResponse(loadFile("poll_ack_response_empty.xml")); runFlowAssertResponse(loadFile("poll_ack_response_empty.xml"));
@ -162,35 +160,33 @@ class PollAckFlowTest extends FlowTestCase<PollAckFlow> {
} }
assertTransactionalFlow(true); assertTransactionalFlow(true);
runFlowAssertResponse( runFlowAssertResponse(
loadFile( loadFile("poll_ack_response.xml", ImmutableMap.of("MSGID", "3-2011", "COUNT", "4")));
"poll_ack_response.xml",
ImmutableMap.of("MSGID", "1-3-EXAMPLE-4-3-2011", "COUNT", "4")));
} }
@Test @Test
void testFailure_noSuchMessage() throws Exception { void testFailure_noSuchMessage() throws Exception {
assertTransactionalFlow(true); assertTransactionalFlow(true);
Exception e = assertThrows(MessageDoesNotExistException.class, this::runFlow); Exception e = assertThrows(MessageDoesNotExistException.class, this::runFlow);
assertThat(e).hasMessageThat().contains(String.format("(1-3-EXAMPLE-4-%d-2011)", MESSAGE_ID)); assertThat(e).hasMessageThat().contains(String.format("(%d-2011)", MESSAGE_ID));
} }
@Test @Test
void testFailure_invalidId_tooFewComponents() throws Exception { void testFailure_invalidId_tooFewComponents() throws Exception {
setEppInput("poll_ack.xml", ImmutableMap.of("MSGID", "1-2-3")); setEppInput("poll_ack.xml", ImmutableMap.of("MSGID", "1"));
assertTransactionalFlow(true); assertTransactionalFlow(true);
assertThrows(InvalidMessageIdException.class, this::runFlow); assertThrows(InvalidMessageIdException.class, this::runFlow);
} }
@Test @Test
void testFailure_invalidId_tooManyComponents() throws Exception { void testFailure_invalidId_tooManyComponents() throws Exception {
setEppInput("poll_ack.xml", ImmutableMap.of("MSGID", "2-2-ROID-4-3-1999-2007")); setEppInput("poll_ack.xml", ImmutableMap.of("MSGID", "2-2-1999-2007"));
assertTransactionalFlow(true); assertTransactionalFlow(true);
assertThrows(InvalidMessageIdException.class, this::runFlow); assertThrows(InvalidMessageIdException.class, this::runFlow);
} }
@Test @Test
void testFailure_contactPollMessage_withMissingYearField() throws Exception { void testFailure_contactPollMessage_withMissingYearField() throws Exception {
setEppInput("poll_ack.xml", ImmutableMap.of("MSGID", "2-2-ROID-4-3")); setEppInput("poll_ack.xml", ImmutableMap.of("MSGID", "3"));
persistResource( persistResource(
new PollMessage.OneTime.Builder() new PollMessage.OneTime.Builder()
.setId(MESSAGE_ID) .setId(MESSAGE_ID)
@ -210,13 +206,6 @@ class PollAckFlowTest extends FlowTestCase<PollAckFlow> {
assertThrows(InvalidMessageIdException.class, this::runFlow); assertThrows(InvalidMessageIdException.class, this::runFlow);
} }
@Test
void testFailure_invalidEppResourceClassId() throws Exception {
setEppInput("poll_ack.xml", ImmutableMap.of("MSGID", "999-1-1-1"));
assertTransactionalFlow(true);
assertThrows(InvalidMessageIdException.class, this::runFlow);
}
@Test @Test
void testFailure_missingId() throws Exception { void testFailure_missingId() throws Exception {
setEppInput("poll_ack_missing_id.xml"); setEppInput("poll_ack_missing_id.xml");
@ -250,6 +239,6 @@ class PollAckFlowTest extends FlowTestCase<PollAckFlow> {
.build()); .build());
assertTransactionalFlow(true); assertTransactionalFlow(true);
Exception e = assertThrows(MessageDoesNotExistException.class, this::runFlow); Exception e = assertThrows(MessageDoesNotExistException.class, this::runFlow);
assertThat(e).hasMessageThat().contains(String.format("(1-3-EXAMPLE-4-%d-2011)", MESSAGE_ID)); assertThat(e).hasMessageThat().contains(String.format("(%d-2011)", MESSAGE_ID));
} }
} }

View file

@ -27,7 +27,6 @@ import google.registry.model.index.EppResourceIndexBucket;
import google.registry.model.index.ForeignKeyIndex.ForeignKeyContactIndex; import google.registry.model.index.ForeignKeyIndex.ForeignKeyContactIndex;
import google.registry.model.index.ForeignKeyIndex.ForeignKeyDomainIndex; import google.registry.model.index.ForeignKeyIndex.ForeignKeyDomainIndex;
import google.registry.model.index.ForeignKeyIndex.ForeignKeyHostIndex; import google.registry.model.index.ForeignKeyIndex.ForeignKeyHostIndex;
import google.registry.model.poll.PollMessage;
import google.registry.model.rde.RdeRevision; import google.registry.model.rde.RdeRevision;
import google.registry.model.registrar.Registrar; import google.registry.model.registrar.Registrar;
import google.registry.model.reporting.HistoryEntry; import google.registry.model.reporting.HistoryEntry;
@ -63,7 +62,6 @@ public class ClassPathManagerTest {
assertThat(ClassPathManager.getClass("Lock")).isEqualTo(Lock.class); assertThat(ClassPathManager.getClass("Lock")).isEqualTo(Lock.class);
assertThat(ClassPathManager.getClass("Domain")).isEqualTo(Domain.class); assertThat(ClassPathManager.getClass("Domain")).isEqualTo(Domain.class);
assertThat(ClassPathManager.getClass("HistoryEntry")).isEqualTo(HistoryEntry.class); assertThat(ClassPathManager.getClass("HistoryEntry")).isEqualTo(HistoryEntry.class);
assertThat(ClassPathManager.getClass("PollMessage")).isEqualTo(PollMessage.class);
assertThat(ClassPathManager.getClass("ForeignKeyHostIndex")) assertThat(ClassPathManager.getClass("ForeignKeyHostIndex"))
.isEqualTo(ForeignKeyHostIndex.class); .isEqualTo(ForeignKeyHostIndex.class);
assertThat(ClassPathManager.getClass("ServerSecret")).isEqualTo(ServerSecret.class); assertThat(ClassPathManager.getClass("ServerSecret")).isEqualTo(ServerSecret.class);
@ -117,7 +115,6 @@ public class ClassPathManagerTest {
assertThat(ClassPathManager.getClassName(Lock.class)).isEqualTo("Lock"); assertThat(ClassPathManager.getClassName(Lock.class)).isEqualTo("Lock");
assertThat(ClassPathManager.getClassName(Domain.class)).isEqualTo("Domain"); assertThat(ClassPathManager.getClassName(Domain.class)).isEqualTo("Domain");
assertThat(ClassPathManager.getClassName(HistoryEntry.class)).isEqualTo("HistoryEntry"); assertThat(ClassPathManager.getClassName(HistoryEntry.class)).isEqualTo("HistoryEntry");
assertThat(ClassPathManager.getClassName(PollMessage.class)).isEqualTo("PollMessage");
assertThat(ClassPathManager.getClassName(ForeignKeyHostIndex.class)) assertThat(ClassPathManager.getClassName(ForeignKeyHostIndex.class))
.isEqualTo("ForeignKeyHostIndex"); .isEqualTo("ForeignKeyHostIndex");
assertThat(ClassPathManager.getClassName(ServerSecret.class)).isEqualTo("ServerSecret"); assertThat(ClassPathManager.getClassName(ServerSecret.class)).isEqualTo("ServerSecret");

View file

@ -15,7 +15,6 @@
package google.registry.model.domain; package google.registry.model.domain;
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
import static google.registry.flows.domain.DomainTransferUtils.createPendingTransferData;
import static google.registry.model.ImmutableObjectSubject.assertAboutImmutableObjects; import static google.registry.model.ImmutableObjectSubject.assertAboutImmutableObjects;
import static google.registry.model.domain.token.AllocationToken.TokenStatus.NOT_STARTED; import static google.registry.model.domain.token.AllocationToken.TokenStatus.NOT_STARTED;
import static google.registry.model.domain.token.AllocationToken.TokenType.UNLIMITED_USE; import static google.registry.model.domain.token.AllocationToken.TokenType.UNLIMITED_USE;
@ -40,11 +39,8 @@ import com.googlecode.objectify.Key;
import google.registry.model.billing.BillingEvent; import google.registry.model.billing.BillingEvent;
import google.registry.model.billing.BillingEvent.Flag; import google.registry.model.billing.BillingEvent.Flag;
import google.registry.model.billing.BillingEvent.Reason; import google.registry.model.billing.BillingEvent.Reason;
import google.registry.model.billing.BillingEvent.Recurring;
import google.registry.model.common.EntityGroupRoot;
import google.registry.model.contact.ContactResource; import google.registry.model.contact.ContactResource;
import google.registry.model.domain.DesignatedContact.Type; import google.registry.model.domain.DesignatedContact.Type;
import google.registry.model.domain.Period.Unit;
import google.registry.model.domain.launch.LaunchNotice; import google.registry.model.domain.launch.LaunchNotice;
import google.registry.model.domain.rgp.GracePeriodStatus; import google.registry.model.domain.rgp.GracePeriodStatus;
import google.registry.model.domain.secdns.DelegationSignerData; import google.registry.model.domain.secdns.DelegationSignerData;
@ -52,7 +48,6 @@ import google.registry.model.domain.token.AllocationToken;
import google.registry.model.domain.token.AllocationToken.TokenStatus; import google.registry.model.domain.token.AllocationToken.TokenStatus;
import google.registry.model.eppcommon.AuthInfo.PasswordAuth; import google.registry.model.eppcommon.AuthInfo.PasswordAuth;
import google.registry.model.eppcommon.StatusValue; import google.registry.model.eppcommon.StatusValue;
import google.registry.model.eppcommon.Trid;
import google.registry.model.host.Host; import google.registry.model.host.Host;
import google.registry.model.poll.PollMessage; import google.registry.model.poll.PollMessage;
import google.registry.model.reporting.HistoryEntry; import google.registry.model.reporting.HistoryEntry;
@ -503,8 +498,7 @@ public class DomainSqlTest {
domain domain
.asBuilder() .asBuilder()
.setAutorenewBillingEvent(billEvent.createVKey()) .setAutorenewBillingEvent(billEvent.createVKey())
.setAutorenewPollMessage( .setAutorenewPollMessage(autorenewPollMessage.createVKey())
autorenewPollMessage.createVKey(), autorenewPollMessage.getHistoryRevisionId())
.setDeletePollMessage(deletePollMessage.createVKey()) .setDeletePollMessage(deletePollMessage.createVKey())
.setTransferData(transferData) .setTransferData(transferData)
.setGracePeriods(gracePeriods) .setGracePeriods(gracePeriods)
@ -549,147 +543,10 @@ public class DomainSqlTest {
assertThat(persisted.getGracePeriods()).isEqualTo(gracePeriods); assertThat(persisted.getGracePeriods()).isEqualTo(gracePeriods);
} }
@Test
void persistDomainWithLegacyVKeys() {
createTld("com");
historyEntry =
new DomainHistory.Builder()
.setId(100L)
.setType(HistoryEntry.Type.DOMAIN_CREATE)
.setPeriod(Period.create(1, Period.Unit.YEARS))
.setModificationTime(DateTime.now(UTC))
.setDomainRepoId("4-COM")
.setRegistrarId("registrar1")
// These are non-null, but I don't think some tests set them.
.setReason("felt like it")
.setRequestedByRegistrar(false)
.setXmlBytes(new byte[0])
.build();
BillingEvent.Recurring billEvent =
new BillingEvent.Recurring.Builder()
.setId(200L)
.setReason(Reason.RENEW)
.setFlags(ImmutableSet.of(Flag.AUTO_RENEW))
.setTargetId("example.com")
.setRegistrarId("registrar1")
.setEventTime(DateTime.now(UTC).plusYears(1))
.setRecurrenceEndTime(END_OF_TIME)
.setDomainHistory(historyEntry)
.build();
PollMessage.Autorenew autorenewPollMessage =
new PollMessage.Autorenew.Builder()
.setId(300L)
.setRegistrarId("registrar1")
.setEventTime(DateTime.now(UTC).plusYears(1))
.setHistoryEntry(historyEntry)
.build();
PollMessage.OneTime deletePollMessage =
new PollMessage.OneTime.Builder()
.setId(400L)
.setRegistrarId("registrar1")
.setEventTime(DateTime.now(UTC).plusYears(1))
.setHistoryEntry(historyEntry)
.build();
BillingEvent.OneTime oneTimeBillingEvent =
new BillingEvent.OneTime.Builder()
.setId(500L)
// Use SERVER_STATUS so we don't have to add a period.
.setReason(Reason.SERVER_STATUS)
.setTargetId("example.com")
.setRegistrarId("registrar1")
.setBillingTime(DateTime.now(UTC))
.setCost(Money.of(USD, 100))
.setEventTime(DateTime.now(UTC).plusYears(1))
.setDomainHistory(historyEntry)
.build();
DomainTransferData transferData =
createPendingTransferData(
domain.getRepoId(),
historyEntry.getId(),
new DomainTransferData.Builder()
.setTransferRequestTrid(Trid.create("foo", "bar"))
.setTransferRequestTime(fakeClock.nowUtc())
.setGainingRegistrarId("registrar2")
.setLosingRegistrarId("registrar1")
.setPendingTransferExpirationTime(fakeClock.nowUtc().plusDays(1)),
ImmutableSet.of(oneTimeBillingEvent, billEvent, autorenewPollMessage),
Period.create(0, Unit.YEARS));
gracePeriods =
ImmutableSet.of(
GracePeriod.create(
GracePeriodStatus.ADD,
"4-COM",
END_OF_TIME,
"registrar1",
oneTimeBillingEvent.createVKey()),
GracePeriod.createForRecurring(
GracePeriodStatus.AUTO_RENEW,
"4-COM",
END_OF_TIME,
"registrar1",
billEvent.createVKey()));
domain =
domain
.asBuilder()
.setAutorenewBillingEvent(Recurring.createVKey(billEvent.getId()))
.setAutorenewPollMessage(
createLegacyVKey(PollMessage.Autorenew.class, autorenewPollMessage.getId()),
autorenewPollMessage.getHistoryRevisionId())
.setDeletePollMessage(
createLegacyVKey(PollMessage.OneTime.class, deletePollMessage.getId()))
.setTransferData(transferData)
.setGracePeriods(gracePeriods)
.build();
historyEntry = historyEntry.asBuilder().setDomain(domain).build();
insertInDb(
contact,
contact2,
host,
historyEntry,
autorenewPollMessage,
billEvent,
deletePollMessage,
oneTimeBillingEvent,
domain);
// Store the existing BillingRecurrence VKey. This happens after the event has been persisted.
Domain persisted = loadByKey(domain.createVKey());
// Verify that the domain data has been persisted.
// dsData still isn't persisted. gracePeriods appears to have the same values but for some
// reason is showing up as different.
assertEqualDomainExcept(persisted, "creationTime", "dsData", "gracePeriods");
// Verify that the DomainBase object from the history record sets the fields correctly.
DomainHistory persistedHistoryEntry = loadByKey(historyEntry.createVKey());
assertThat(persistedHistoryEntry.getDomainBase().get().getAutorenewPollMessage())
.isEqualTo(domain.getAutorenewPollMessage());
assertThat(persistedHistoryEntry.getDomainBase().get().getAutorenewBillingEvent())
.isEqualTo(domain.getAutorenewBillingEvent());
assertThat(persistedHistoryEntry.getDomainBase().get().getDeletePollMessage())
.isEqualTo(domain.getDeletePollMessage());
DomainTransferData persistedTransferData =
persistedHistoryEntry.getDomainBase().get().getTransferData();
DomainTransferData originalTransferData = domain.getTransferData();
assertThat(persistedTransferData.getServerApproveBillingEvent())
.isEqualTo(originalTransferData.getServerApproveBillingEvent());
assertThat(persistedTransferData.getServerApproveAutorenewEvent())
.isEqualTo(originalTransferData.getServerApproveAutorenewEvent());
assertThat(persistedTransferData.getServerApproveAutorenewPollMessage())
.isEqualTo(originalTransferData.getServerApproveAutorenewPollMessage());
assertThat(domain.getGracePeriods()).isEqualTo(gracePeriods);
}
private <T> VKey<T> createKey(Class<T> clazz, String name) { private <T> VKey<T> createKey(Class<T> clazz, String name) {
return VKey.create(clazz, name, Key.create(clazz, name)); return VKey.create(clazz, name, Key.create(clazz, name));
} }
private <T> VKey<T> createLegacyVKey(Class<T> clazz, long id) {
return VKey.create(
clazz, id, Key.create(Key.create(EntityGroupRoot.class, "per-tld"), clazz, id));
}
private void assertEqualDomainExcept(Domain thatDomain, String... excepts) { private void assertEqualDomainExcept(Domain thatDomain, String... excepts) {
ImmutableList<String> moreExcepts = ImmutableList<String> moreExcepts =
new ImmutableList.Builder<String>() new ImmutableList.Builder<String>()

View file

@ -41,7 +41,6 @@ import com.google.common.collect.ImmutableSortedMap;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
import com.google.common.collect.Ordering; import com.google.common.collect.Ordering;
import com.google.common.collect.Streams; import com.google.common.collect.Streams;
import com.googlecode.objectify.Key;
import google.registry.model.ImmutableObject; import google.registry.model.ImmutableObject;
import google.registry.model.ImmutableObjectSubject; import google.registry.model.ImmutableObjectSubject;
import google.registry.model.billing.BillingEvent; import google.registry.model.billing.BillingEvent;
@ -114,7 +113,7 @@ public class DomainTest {
oneTimeBillKey = oneTimeBillKey =
persistResource( persistResource(
new BillingEvent.OneTime.Builder() new BillingEvent.OneTime.Builder()
// Use SERVER_STATUS so we don't have to add a period. // Use SERVER_STATUS, so we don't have to add a period.
.setReason(Reason.SERVER_STATUS) .setReason(Reason.SERVER_STATUS)
.setTargetId(domain.getDomainName()) .setTargetId(domain.getDomainName())
.setRegistrarId(domain.getCurrentSponsorRegistrarId()) .setRegistrarId(domain.getCurrentSponsorRegistrarId())
@ -140,7 +139,7 @@ public class DomainTest {
BillingEvent.OneTime oneTimeBill = BillingEvent.OneTime oneTimeBill =
new BillingEvent.OneTime.Builder() new BillingEvent.OneTime.Builder()
.setId(500L) .setId(500L)
// Use SERVER_STATUS so we don't have to add a period. // Use SERVER_STATUS, so we don't have to add a period.
.setReason(Reason.SERVER_STATUS) .setReason(Reason.SERVER_STATUS)
.setTargetId("example.com") .setTargetId("example.com")
.setRegistrarId("registrar1") .setRegistrarId("registrar1")
@ -163,10 +162,8 @@ public class DomainTest {
.build(); .build();
insertInDb(historyEntry, oneTimeBill, recurringBill); insertInDb(historyEntry, oneTimeBill, recurringBill);
recurringBillKey = recurringBill.createVKey(); recurringBillKey = recurringBill.createVKey();
VKey<PollMessage.Autorenew> autorenewPollKey = VKey<PollMessage.Autorenew> autorenewPollKey = VKey.createSql(PollMessage.Autorenew.class, 3L);
VKey.from(Key.create(Key.create(domainHistory), PollMessage.Autorenew.class, 3)); VKey<PollMessage.OneTime> onetimePollKey = VKey.createSql(PollMessage.OneTime.class, 1L);
VKey<PollMessage.OneTime> onetimePollKey =
VKey.from(Key.create(Key.create(domainHistory), PollMessage.OneTime.class, 1));
// Set up a new persisted domain entity. // Set up a new persisted domain entity.
domain = domain =
persistResource( persistResource(
@ -215,7 +212,7 @@ public class DomainTest {
.build()) .build())
.setDeletePollMessage(onetimePollKey) .setDeletePollMessage(onetimePollKey)
.setAutorenewBillingEvent(recurringBillKey) .setAutorenewBillingEvent(recurringBillKey)
.setAutorenewPollMessage(autorenewPollKey, historyEntry.getId()) .setAutorenewPollMessage(autorenewPollKey)
.setSmdId("smdid") .setSmdId("smdid")
.addGracePeriod( .addGracePeriod(
GracePeriod.create( GracePeriod.create(
@ -849,7 +846,7 @@ public class DomainTest {
@Test @Test
void testClone_transferDuringAutorenew() { void testClone_transferDuringAutorenew() {
// When the domain is an an autorenew grace period, we should not extend the registration // When the domain is an autorenew grace period, we should not extend the registration
// expiration by a further year--it should just be whatever the autorenew was // expiration by a further year--it should just be whatever the autorenew was
DateTime now = DateTime.now(UTC); DateTime now = DateTime.now(UTC);
DateTime transferExpirationTime = now.minusDays(1); DateTime transferExpirationTime = now.minusDays(1);

View file

@ -46,7 +46,7 @@ public class PollMessageExternalKeyConverterTest {
public final AppEngineExtension appEngine = AppEngineExtension.builder().withCloudSql().build(); public final AppEngineExtension appEngine = AppEngineExtension.builder().withCloudSql().build();
private HistoryEntry historyEntry; private HistoryEntry historyEntry;
private FakeClock clock = new FakeClock(DateTime.parse("2007-07-07T01:01:01Z")); private final FakeClock clock = new FakeClock(DateTime.parse("2007-07-07T01:01:01Z"));
@BeforeEach @BeforeEach
void beforeEach() { void beforeEach() {
@ -77,8 +77,8 @@ public class PollMessageExternalKeyConverterTest {
.setMsg("Test poll message") .setMsg("Test poll message")
.setHistoryEntry(historyEntry) .setHistoryEntry(historyEntry)
.build()); .build());
assertThat(makePollMessageExternalId(pollMessage)).isEqualTo("1-2-FOOBAR-4-5-2007"); assertThat(makePollMessageExternalId(pollMessage)).isEqualTo("5-2007");
assertVKeysEqual(parsePollMessageExternalId("1-2-FOOBAR-4-5-2007"), pollMessage.createVKey()); assertVKeysEqual(parsePollMessageExternalId("5-2007"), pollMessage.createVKey());
} }
@Test @Test
@ -94,8 +94,8 @@ public class PollMessageExternalKeyConverterTest {
.setMsg("Test poll message") .setMsg("Test poll message")
.setHistoryEntry(historyEntry) .setHistoryEntry(historyEntry)
.build()); .build());
assertThat(makePollMessageExternalId(pollMessage)).isEqualTo("2-5-ROID-6-7-2007"); assertThat(makePollMessageExternalId(pollMessage)).isEqualTo("7-2007");
assertVKeysEqual(parsePollMessageExternalId("2-5-ROID-6-7-2007"), pollMessage.createVKey()); assertVKeysEqual(parsePollMessageExternalId("7-2007"), pollMessage.createVKey());
} }
@Test @Test
@ -111,46 +111,25 @@ public class PollMessageExternalKeyConverterTest {
.setMsg("Test poll message") .setMsg("Test poll message")
.setHistoryEntry(historyEntry) .setHistoryEntry(historyEntry)
.build()); .build());
assertThat(makePollMessageExternalId(pollMessage)).isEqualTo("3-5-ROID-6-7-2007"); assertThat(makePollMessageExternalId(pollMessage)).isEqualTo("7-2007");
assertVKeysEqual(parsePollMessageExternalId("3-5-ROID-6-7-2007"), pollMessage.createVKey()); assertVKeysEqual(parsePollMessageExternalId("7-2007"), pollMessage.createVKey());
}
@Test
void testFailure_missingYearField() {
assertThrows(
PollMessageExternalKeyParseException.class,
() -> parsePollMessageExternalId("1-2-FOOBAR-4-5"));
}
@Test
void testFailure_invalidEppResourceTypeId() {
// Populate the testdata correctly as for 1-2-FOOBAR-4-5 so we know that the only thing that
// is wrong here is the EppResourceTypeId.
testSuccess_domain();
assertThrows(
PollMessageExternalKeyParseException.class,
() -> parsePollMessageExternalId("4-2-FOOBAR-4-5-2007"));
} }
@Test @Test
void testFailure_tooFewComponentParts() { void testFailure_tooFewComponentParts() {
assertThrows( assertThrows(PollMessageExternalKeyParseException.class, () -> parsePollMessageExternalId("1"));
PollMessageExternalKeyParseException.class,
() -> parsePollMessageExternalId("1-3-EXAMPLE"));
} }
@Test @Test
void testFailure_tooManyComponentParts() { void testFailure_tooManyComponentParts() {
assertThrows( assertThrows(
PollMessageExternalKeyParseException.class, PollMessageExternalKeyParseException.class, () -> parsePollMessageExternalId("1-3-2009"));
() -> parsePollMessageExternalId("1-3-EXAMPLE-4-5-2007-2009"));
} }
@Test @Test
void testFailure_nonNumericIds() { void testFailure_nonNumericIds() {
assertThrows( assertThrows(
PollMessageExternalKeyParseException.class, PollMessageExternalKeyParseException.class, () -> parsePollMessageExternalId("A-2007"));
() -> parsePollMessageExternalId("A-B-FOOBAR-D-E-F"));
} }
// We may have VKeys of slightly varying types, e.g. VKey<PollMessage> (superclass) and // We may have VKeys of slightly varying types, e.g. VKey<PollMessage> (superclass) and

View file

@ -18,16 +18,13 @@ import static com.google.common.truth.Truth.assertThat;
import static org.joda.time.DateTimeZone.UTC; import static org.joda.time.DateTimeZone.UTC;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.googlecode.objectify.Key;
import google.registry.model.billing.BillingEvent; import google.registry.model.billing.BillingEvent;
import google.registry.model.billing.BillingEvent.Cancellation; import google.registry.model.billing.BillingEvent.Cancellation;
import google.registry.model.billing.BillingEvent.OneTime; import google.registry.model.billing.BillingEvent.OneTime;
import google.registry.model.billing.BillingEvent.Recurring; import google.registry.model.billing.BillingEvent.Recurring;
import google.registry.model.domain.Domain;
import google.registry.model.domain.Period; import google.registry.model.domain.Period;
import google.registry.model.eppcommon.Trid; import google.registry.model.eppcommon.Trid;
import google.registry.model.poll.PollMessage; import google.registry.model.poll.PollMessage;
import google.registry.model.reporting.HistoryEntry;
import google.registry.persistence.VKey; import google.registry.persistence.VKey;
import google.registry.testing.AppEngineExtension; import google.registry.testing.AppEngineExtension;
import org.joda.time.DateTime; import org.joda.time.DateTime;
@ -51,21 +48,11 @@ public class TransferDataTest {
@BeforeEach @BeforeEach
void beforeEach() { void beforeEach() {
Key<HistoryEntry> historyEntryKey =
Key.create(Key.create(Domain.class, "4-TLD"), HistoryEntry.class, 1356L);
transferBillingEventKey = OneTime.createVKey(12345L); transferBillingEventKey = OneTime.createVKey(12345L);
otherServerApproveBillingEventKey = Cancellation.createVKey(2468L); otherServerApproveBillingEventKey = Cancellation.createVKey(2468L);
recurringBillingEventKey = Recurring.createVKey(13579L); recurringBillingEventKey = Recurring.createVKey(13579L);
autorenewPollMessageKey = autorenewPollMessageKey = VKey.createSql(PollMessage.Autorenew.class, 67890L);
VKey.create( otherServerApprovePollMessageKey = VKey.createSql(PollMessage.OneTime.class, 314159L);
PollMessage.Autorenew.class,
67890L,
Key.create(historyEntryKey, PollMessage.Autorenew.class, 67890L));
otherServerApprovePollMessageKey =
VKey.create(
PollMessage.OneTime.class,
314159L,
Key.create(historyEntryKey, PollMessage.OneTime.class, 314159L));
} }
@Test @Test

View file

@ -334,8 +334,7 @@ public class DomainToXjcConverterTest {
.setMsg("Domain was auto-renewed.") .setMsg("Domain was auto-renewed.")
.setHistoryEntry(domainHistory) .setHistoryEntry(domainHistory)
.build()) .build())
.createVKey(), .createVKey())
domainHistory.getId())
.setTransferData( .setTransferData(
new DomainTransferData.Builder() new DomainTransferData.Builder()
.setGainingRegistrarId("NewRegistrar") .setGainingRegistrarId("NewRegistrar")

View file

@ -175,8 +175,7 @@ final class RdeFixtures {
.setMsg("Domain was auto-renewed.") .setMsg("Domain was auto-renewed.")
.setHistoryEntry(historyEntry) .setHistoryEntry(historyEntry)
.build()) .build())
.createVKey(), .createVKey())
historyEntry.getId())
.setTransferData( .setTransferData(
new DomainTransferData.Builder() new DomainTransferData.Builder()
.setGainingRegistrarId("gaining") .setGainingRegistrarId("gaining")

View file

@ -667,8 +667,7 @@ public class DatabaseHelper {
domain domain
.asBuilder() .asBuilder()
.setAutorenewBillingEvent(autorenewEvent.createVKey()) .setAutorenewBillingEvent(autorenewEvent.createVKey())
.setAutorenewPollMessage( .setAutorenewPollMessage(autorenewPollMessage.createVKey())
autorenewPollMessage.createVKey(), autorenewPollMessage.getHistoryRevisionId())
.build()); .build());
} }

View file

@ -77,10 +77,10 @@ public class AckPollMessagesCommandTest extends CommandTestCase<AckPollMessagesC
assertThat(loadByKeysIfPresent(ImmutableList.of(pm1, pm2, pm3, pm4)).values()) assertThat(loadByKeysIfPresent(ImmutableList.of(pm1, pm2, pm3, pm4)).values())
.containsExactly(futurePollMessage); .containsExactly(futurePollMessage);
assertInStdout( assertInStdout(
"1-FSDGS-TLD-2406-624-2013,2013-05-01T22:33:44.000Z,ninelives", "624-2013,2013-05-01T22:33:44.000Z,ninelives",
"1-FSDGS-TLD-2406-316-2014,2014-01-01T22:33:44.000Z,foobar", "316-2014,2014-01-01T22:33:44.000Z,foobar",
"1-FSDGS-TLD-2406-791-2015,2015-01-08T22:33:44.000Z,ginger"); "791-2015,2015-01-08T22:33:44.000Z,ginger");
assertNotInStdout("1-FSDGS-TLD-2406-123-2015,2015-09-01T22:33:44.000Z,notme"); assertNotInStdout("123-2015,2015-09-01T22:33:44.000Z,notme");
} }
@Test @Test
@ -105,9 +105,9 @@ public class AckPollMessagesCommandTest extends CommandTestCase<AckPollMessagesC
assertThat(loadByKeysIfPresent(ImmutableList.of(pm1, pm2, pm3)).values()) assertThat(loadByKeysIfPresent(ImmutableList.of(pm1, pm2, pm3)).values())
.containsExactly(resaved); .containsExactly(resaved);
assertInStdout( assertInStdout(
"1-FSDGS-TLD-2406-625-2011,2011-04-15T22:33:44.000Z,autorenew", "625-2011,2011-04-15T22:33:44.000Z,autorenew",
"1-FSDGS-TLD-2406-624-2013,2013-05-01T22:33:44.000Z,ninelives", "624-2013,2013-05-01T22:33:44.000Z,ninelives",
"1-FSDGS-TLD-2406-316-2014,2014-01-01T22:33:44.000Z,foobar"); "316-2014,2014-01-01T22:33:44.000Z,foobar");
} }
@Test @Test
@ -130,9 +130,9 @@ public class AckPollMessagesCommandTest extends CommandTestCase<AckPollMessagesC
runCommand("-c", "TheRegistrar"); runCommand("-c", "TheRegistrar");
assertThat(loadByKeysIfPresent(ImmutableList.of(pm1, pm2, pm3))).isEmpty(); assertThat(loadByKeysIfPresent(ImmutableList.of(pm1, pm2, pm3))).isEmpty();
assertInStdout( assertInStdout(
"1-FSDGS-TLD-2406-625-2011,2011-04-15T22:33:44.000Z,autorenew", "625-2011,2011-04-15T22:33:44.000Z,autorenew",
"1-FSDGS-TLD-2406-624-2013,2013-05-01T22:33:44.000Z,ninelives", "624-2013,2013-05-01T22:33:44.000Z,ninelives",
"1-FSDGS-TLD-2406-316-2014,2014-01-01T22:33:44.000Z,foobar"); "316-2014,2014-01-01T22:33:44.000Z,foobar");
} }
@Test @Test

View file

@ -115,7 +115,7 @@ class EppLifecycleToolsTest extends EppTestCase {
.atTime("2001-06-08T00:00:00Z") .atTime("2001-06-08T00:00:00Z")
.hasResponse("poll_response_unrenew.xml"); .hasResponse("poll_response_unrenew.xml");
assertThatCommand("poll_ack.xml", ImmutableMap.of("ID", "1-7-TLD-20-21-2001")) assertThatCommand("poll_ack.xml", ImmutableMap.of("ID", "21-2001"))
.atTime("2001-06-08T00:00:01Z") .atTime("2001-06-08T00:00:01Z")
.hasResponse("poll_ack_response_empty.xml"); .hasResponse("poll_ack_response_empty.xml");
@ -136,7 +136,7 @@ class EppLifecycleToolsTest extends EppTestCase {
.hasResponse( .hasResponse(
"poll_response_autorenew.xml", "poll_response_autorenew.xml",
ImmutableMap.of( ImmutableMap.of(
"ID", "1-7-TLD-20-23-2003", "ID", "23-2003",
"QDATE", "2003-06-01T00:02:00Z", "QDATE", "2003-06-01T00:02:00Z",
"DOMAIN", "example.tld", "DOMAIN", "example.tld",
"EXDATE", "2004-06-01T00:02:00Z")); "EXDATE", "2004-06-01T00:02:00Z"));

View file

@ -155,7 +155,6 @@ public class UnrenewDomainCommandTest extends CommandTestCase<UnrenewDomainComma
.build())); .build()));
// Check that fields on domain were updated correctly. // Check that fields on domain were updated correctly.
assertThat(domain.getAutorenewPollMessageHistoryId()).isEqualTo(synthetic.getId());
assertThat(domain.getRegistrationExpirationTime()).isEqualTo(newExpirationTime); assertThat(domain.getRegistrationExpirationTime()).isEqualTo(newExpirationTime);
assertThat(domain.getLastEppUpdateTime()).isEqualTo(unrenewTime); assertThat(domain.getLastEppUpdateTime()).isEqualTo(unrenewTime);
assertThat(domain.getLastEppUpdateRegistrarId()).isEqualTo("TheRegistrar"); assertThat(domain.getLastEppUpdateRegistrarId()).isEqualTo("TheRegistrar");

View file

@ -3,7 +3,7 @@
<result code="1301"> <result code="1301">
<msg>Command completed successfully; ack to dequeue</msg> <msg>Command completed successfully; ack to dequeue</msg>
</result> </result>
<msgQ count="1" id="1-3-EXAMPLE-5-6-2011"> <msgQ count="1" id="6-2011">
<qDate>2011-01-02T01:01:01Z</qDate> <qDate>2011-01-02T01:01:01Z</qDate>
<msg>Domain test.example was deleted by registry administrator with final deletion effective: 2011-01-02T00:56:01.008Z</msg> <msg>Domain test.example was deleted by registry administrator with final deletion effective: 2011-01-02T00:56:01.008Z</msg>
</msgQ> </msgQ>

View file

@ -3,7 +3,7 @@
<result code="1301"> <result code="1301">
<msg>Command completed successfully; ack to dequeue</msg> <msg>Command completed successfully; ack to dequeue</msg>
</result> </result>
<msgQ count="1" id="1-3-EXAMPLE-5-6-2011"> <msgQ count="1" id="6-2011">
<qDate>2011-01-01T01:01:01Z</qDate> <qDate>2011-01-01T01:01:01Z</qDate>
<msg>Domain was auto-renewed.</msg> <msg>Domain was auto-renewed.</msg>
</msgQ> </msgQ>

View file

@ -3,7 +3,7 @@
<result code="1301"> <result code="1301">
<msg>Command completed successfully; ack to dequeue</msg> <msg>Command completed successfully; ack to dequeue</msg>
</result> </result>
<msgQ count="1" id="2-2-ROID-5-6-2011"> <msgQ count="1" id="6-2011">
<qDate>2011-01-01T01:01:01Z</qDate> <qDate>2011-01-01T01:01:01Z</qDate>
<msg>Deleted contact jd1234</msg> <msg>Deleted contact jd1234</msg>
</msgQ> </msgQ>

View file

@ -3,7 +3,7 @@
<result code="1301"> <result code="1301">
<msg>Command completed successfully; ack to dequeue</msg> <msg>Command completed successfully; ack to dequeue</msg>
</result> </result>
<msgQ count="1" id="2-2-ROID-5-3-2010"> <msgQ count="1" id="3-2010">
<qDate>2010-12-28T01:01:01Z</qDate> <qDate>2010-12-28T01:01:01Z</qDate>
<msg>Transfer requested.</msg> <msg>Transfer requested.</msg>
</msgQ> </msgQ>

View file

@ -3,7 +3,7 @@
<result code="1301"> <result code="1301">
<msg>Command completed successfully; ack to dequeue</msg> <msg>Command completed successfully; ack to dequeue</msg>
</result> </result>
<msgQ count="1" id="1-3-EXAMPLE-5-6-2011"> <msgQ count="1" id="6-2011">
<qDate>2011-01-01T01:01:01Z</qDate> <qDate>2011-01-01T01:01:01Z</qDate>
<msg>Domain deleted.</msg> <msg>Domain deleted.</msg>
</msgQ> </msgQ>

View file

@ -3,7 +3,7 @@
<result code="1301"> <result code="1301">
<msg>Command completed successfully; ack to dequeue</msg> <msg>Command completed successfully; ack to dequeue</msg>
</result> </result>
<msgQ count="1" id="1-3-EXAMPLE-5-6-2011"> <msgQ count="1" id="6-2011">
<qDate>2011-01-01T01:01:01Z</qDate> <qDate>2011-01-01T01:01:01Z</qDate>
<msg>Transfer approved.</msg> <msg>Transfer approved.</msg>
</msgQ> </msgQ>

View file

@ -3,7 +3,7 @@
<result code="1301"> <result code="1301">
<msg>Command completed successfully; ack to dequeue</msg> <msg>Command completed successfully; ack to dequeue</msg>
</result> </result>
<msgQ count="1" id="1-3-EXAMPLE-5-6-2011"> <msgQ count="1" id="6-2011">
<qDate>2011-01-01T01:01:01Z</qDate> <qDate>2011-01-01T01:01:01Z</qDate>
<msg>Transfer approved.</msg> <msg>Transfer approved.</msg>
</msgQ> </msgQ>

View file

@ -3,7 +3,7 @@
<result code="1301"> <result code="1301">
<msg>Command completed successfully; ack to dequeue</msg> <msg>Command completed successfully; ack to dequeue</msg>
</result> </result>
<msgQ count="1" id="3-4-ROID-5-6-2011"> <msgQ count="1" id="6-2011">
<qDate>2011-01-01T01:01:01Z</qDate> <qDate>2011-01-01T01:01:01Z</qDate>
<msg>Deleted host ns1.test.example</msg> <msg>Deleted host ns1.test.example</msg>
</msgQ> </msgQ>

View file

@ -3,7 +3,7 @@
<result code="1301"> <result code="1301">
<msg>Command completed successfully; ack to dequeue</msg> <msg>Command completed successfully; ack to dequeue</msg>
</result> </result>
<msgQ count="1" id="2-1-ROID-3-6-2000"> <msgQ count="1" id="6-2000">
<qDate>2000-06-08T22:00:00Z</qDate> <qDate>2000-06-08T22:00:00Z</qDate>
<msg>Transfer requested.</msg> <msg>Transfer requested.</msg>
</msgQ> </msgQ>

View file

@ -3,7 +3,7 @@
<result code="1301"> <result code="1301">
<msg>Command completed successfully; ack to dequeue</msg> <msg>Command completed successfully; ack to dequeue</msg>
</result> </result>
<msgQ count="1" id="1-7-TLD-14-16-2000"> <msgQ count="1" id="16-2000">
<qDate>2000-06-02T13:00:00Z</qDate> <qDate>2000-06-02T13:00:00Z</qDate>
<msg>The registry administrator has added the status(es) [serverHold]. <msg>The registry administrator has added the status(es) [serverHold].
</msg> </msg>

View file

@ -3,7 +3,7 @@
<result code="1301"> <result code="1301">
<msg>Command completed successfully; ack to dequeue</msg> <msg>Command completed successfully; ack to dequeue</msg>
</result> </result>
<msgQ count="1" id="1-7-TLD-20-21-2001"> <msgQ count="1" id="21-2001">
<qDate>2001-06-07T00:00:00Z</qDate> <qDate>2001-06-07T00:00:00Z</qDate>
<msg>Domain example.tld was unrenewed by 3 years; now expires at 2003-06-01T00:02:00.000Z.</msg> <msg>Domain example.tld was unrenewed by 3 years; now expires at 2003-06-01T00:02:00.000Z.</msg>
</msgQ> </msgQ>

View file

@ -359,26 +359,6 @@ class google.registry.model.index.ForeignKeyIndex$ForeignKeyHostIndex {
google.registry.persistence.VKey<E> topReference; google.registry.persistence.VKey<E> topReference;
org.joda.time.DateTime deletionTime; org.joda.time.DateTime deletionTime;
} }
class google.registry.model.poll.PollMessage {
@Id java.lang.Long id;
java.lang.String clientId;
java.lang.String msg;
org.joda.time.DateTime eventTime;
}
class google.registry.model.poll.PollMessage$Autorenew {
@Id java.lang.Long id;
java.lang.String clientId;
java.lang.String msg;
java.lang.String targetId;
org.joda.time.DateTime autorenewEndTime;
org.joda.time.DateTime eventTime;
}
class google.registry.model.poll.PollMessage$OneTime {
@Id java.lang.Long id;
java.lang.String clientId;
java.lang.String msg;
org.joda.time.DateTime eventTime;
}
class google.registry.model.rde.RdeRevision { class google.registry.model.rde.RdeRevision {
@Id java.lang.String id; @Id java.lang.String id;
int revision; int revision;

View file

@ -270,7 +270,6 @@
billing_recurrence_id int8, billing_recurrence_id int8,
autorenew_end_time timestamptz, autorenew_end_time timestamptz,
autorenew_poll_message_id int8, autorenew_poll_message_id int8,
autorenew_poll_message_history_id int8,
billing_contact text, billing_contact text,
current_package_token text, current_package_token text,
deletion_poll_message_id int8, deletion_poll_message_id int8,
@ -340,7 +339,6 @@
billing_recurrence_id int8, billing_recurrence_id int8,
autorenew_end_time timestamptz, autorenew_end_time timestamptz,
autorenew_poll_message_id int8, autorenew_poll_message_id int8,
autorenew_poll_message_history_id int8,
billing_contact text, billing_contact text,
current_package_token text, current_package_token text,
deletion_poll_message_id int8, deletion_poll_message_id int8,