diff --git a/docs/code-structure.md b/docs/code-structure.md index 8196c035e..6de055532 100644 --- a/docs/code-structure.md +++ b/docs/code-structure.md @@ -1,3 +1,58 @@ # Code structure -An overall look at the structure of the Domain Registry code. +This document contains information on the overall structure of the code, and how +particularly important pieces of the system are implemented. + +## Dagger dependency injection + +## Bazel build system + +## Flows + +## Commit logs and backups + +## Cursors + +## Mapreduces + +## Actions and servlets + +## Foreign key indexes + +## Point-in-time accuracy + +## Guava + +## EPP resource hierarchy + +## Poll messages + +Poll messages are the mechanism by which EPP handles asynchronous communication +between the registry and registrars. Refer to +[RFC 5730 Section 2.9.2.3](https://tools.ietf.org/html/rfc5730#section-2.9.2.3) +for their protocol specification. + +Poll messages are stored by the system as entities in Datastore. All poll +messages have an event time at which they become active; any poll request before +that time will not return the poll message. For example, every domain when +created speculatively enqueues a poll message for the automatic renewal of the +domain a year later. This poll message won't be delivered until that year +elapses, and if some change to the domain occurs prior to that point, such as it +being deleted, then the speculative poll message will be deleted and thus never +delivered. Other poll messages are effective immediately, e.g. the poll message +generated for the owning registrar when another registrar requests the transfer +of a domain. These messages are written out with an event time of when they were +created, and will thus be delivered whenever the registrar next polls for +messages. + +`PollMessage` is the abstract base class for the two different types of poll +messages that extend it: + +* **`Autorenew`** - A poll message corresponding to an automatic renewal of + a domain. It recurs annually. +* **`OneTime`** - A one-time poll message used for everything else. + +Queries for poll messages by the registrar are handled in `PollRequestFlow`, and +poll messages are ACKed (and thus deleted) in `PollAckFlow`. + +## Security diff --git a/java/google/registry/flows/poll/PollAckFlow.java b/java/google/registry/flows/poll/PollAckFlow.java index 2038a8ebe..5080671ae 100644 --- a/java/google/registry/flows/poll/PollAckFlow.java +++ b/java/google/registry/flows/poll/PollAckFlow.java @@ -35,12 +35,18 @@ import google.registry.flows.TransactionalFlow; import google.registry.model.eppoutput.EppOutput; import google.registry.model.poll.MessageQueueInfo; import google.registry.model.poll.PollMessage; +import google.registry.model.poll.PollMessageExternalKeyConverter; import google.registry.model.poll.PollMessageExternalKeyConverter.PollMessageExternalKeyParseException; import javax.inject.Inject; import org.joda.time.DateTime; /** - * An EPP flow for acknowledging poll messages. + * An EPP flow for acknowledging {@link PollMessage}s. + * + *

Registrars refer to poll messages using an externally visible id generated by + * {@link PollMessageExternalKeyConverter}. One-time poll messages are deleted from Datastore once + * they are ACKed, whereas autorenew poll messages are simply marked as read, and won't be delivered + * again until the next year of their recurrence. * * @error {@link PollAckFlow.InvalidMessageIdException} * @error {@link PollAckFlow.MessageDoesNotExistException} diff --git a/java/google/registry/flows/poll/PollRequestFlow.java b/java/google/registry/flows/poll/PollRequestFlow.java index 03ea8946e..a1e38ba1f 100644 --- a/java/google/registry/flows/poll/PollRequestFlow.java +++ b/java/google/registry/flows/poll/PollRequestFlow.java @@ -28,10 +28,17 @@ import google.registry.flows.LoggedInFlow; import google.registry.model.eppoutput.EppOutput; import google.registry.model.poll.MessageQueueInfo; import google.registry.model.poll.PollMessage; +import google.registry.model.poll.PollMessageExternalKeyConverter; import javax.inject.Inject; /** - * An EPP flow for requesting poll messages. + * An EPP flow for requesting {@link PollMessage}s. + * + *

This flow uses an eventually consistent Datastore query to return the oldest poll message for + * the registrar, as well as the total number of pending messages. Note that poll messages whose + * event time is in the future (i.e. they are speculative and could still be changed or rescinded) + * are ignored. The externally visible id for the poll message that the registrar sees is generated + * by {@link PollMessageExternalKeyConverter}. * * @error {@link PollRequestFlow.UnexpectedMessageIdException} */ diff --git a/java/google/registry/model/poll/PollMessage.java b/java/google/registry/model/poll/PollMessage.java index ebfe7895d..9ed27be2d 100644 --- a/java/google/registry/model/poll/PollMessage.java +++ b/java/google/registry/model/poll/PollMessage.java @@ -50,11 +50,30 @@ import google.registry.model.transfer.TransferResponse.DomainTransferResponse; import java.util.List; import org.joda.time.DateTime; -/** A poll message that is pending for a registrar. */ +/** + * A poll message that is pending for a registrar. + * + *

Poll messages are not delivered until their {@link #eventTime} has passed. Poll messages can + * be speculatively enqueued for future delivery, and then modified or deleted before that date has + * passed. Unlike most other entities in Datastore, which are marked as deleted but otherwise + * retained for historical purposes, poll messages are truly deleted once they have been delivered + * and ACKed. + * + *

Poll messages are parented off of the {@link HistoryEntry} that resulted in their creation. + * This means that poll messages are contained in the Datastore entity group of the parent {@link + * EppResource} (which can be a domain, application, contact, or host). It is thus possible to + * perform a strongly consistent query to find all poll messages associated with a given EPP + * resource. + * + *

Poll messages are identified externally by registrars using the format defined in {@link + * PollMessageExternalKeyConverter}. + * + * @see "https://tools.ietf.org/html/rfc5730#section-2.9.2.3" + */ @Entity @ExternalMessagingName("message") -public abstract class PollMessage - extends ImmutableObject implements Buildable, TransferServerApproveEntity { +public abstract class PollMessage extends ImmutableObject + implements Buildable, TransferServerApproveEntity { public static final Converter, String> EXTERNAL_KEY_CONVERTER = @@ -158,7 +177,11 @@ public abstract class PollMessage } } - /** A one-time poll message. */ + /** + * A one-time poll message. + * + *

One-time poll messages are deleted from Datastore once they have been delivered and ACKed. + */ @EntitySubclass(index = false) public static class OneTime extends PollMessage { @@ -252,7 +275,13 @@ public abstract class PollMessage } } - /** An autorenew poll message which recurs annually. */ + /** + * An auto-renew poll message which recurs annually. + * + *

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 + * happens. + */ @EntitySubclass(index = false) public static class Autorenew extends PollMessage { diff --git a/java/google/registry/model/poll/PollMessageExternalKeyConverter.java b/java/google/registry/model/poll/PollMessageExternalKeyConverter.java index 8dced7be9..033e8c245 100644 --- a/java/google/registry/model/poll/PollMessageExternalKeyConverter.java +++ b/java/google/registry/model/poll/PollMessageExternalKeyConverter.java @@ -28,7 +28,8 @@ import google.registry.model.reporting.HistoryEntry; import java.util.List; /** - * A converter between external key strings for PollMessages and Objectify Keys to the resource. + * 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. * *

The format of the key string is A-B-C-D-E as follows: *