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 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:
*