Convert poll-message-related classes to use SQL as well (#1050)

* Convert poll-message-related classes to use SQL as well

Two relatively complex parts. The first is that we needed a small
refactor on the AckPollMessagesCommand because we could theoretically be
acking more poll messages than the Datastore transaction size boundary.
This means that the normal flow of "gather the poll messages from the DB
into one collection, then act on it" needs to be changed to a more
functional flow.

The second is that acking the poll message (deleting it in most cases)
reduces the number of remaining poll messages in SQL but not in
Datastore, since in Datastore the deletion does not take effect until
after the transaction is over.
This commit is contained in:
gbrodman 2021-04-02 19:57:26 -04:00 committed by GitHub
parent 75e74f013d
commit 7c3ef52026
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 322 additions and 166 deletions

View file

@ -32,14 +32,16 @@ import google.registry.flows.poll.PollAckFlow.NotAuthorizedToAckMessageException
import google.registry.model.contact.ContactResource;
import google.registry.model.domain.DomainBase;
import google.registry.model.poll.PollMessage;
import google.registry.testing.DualDatabaseTest;
import google.registry.testing.ReplayExtension;
import google.registry.testing.TestOfyAndSql;
import org.joda.time.DateTime;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
/** Unit tests for {@link PollAckFlow}. */
@DualDatabaseTest
class PollAckFlowTest extends FlowTestCase<PollAckFlow> {
@Order(value = Order.DEFAULT - 2)
@ -89,13 +91,13 @@ class PollAckFlowTest extends FlowTestCase<PollAckFlow> {
.build());
}
@Test
@TestOfyAndSql
void testDryRun() throws Exception {
persistOneTimePollMessage(MESSAGE_ID);
dryRunFlowAssertResponse(loadFile("poll_ack_response_empty.xml"));
}
@Test
@TestOfyAndSql
void testSuccess_contactPollMessage() throws Exception {
setEppInput("poll_ack.xml", ImmutableMap.of("MSGID", "2-2-ROID-4-3-2011"));
persistResource(
@ -110,7 +112,7 @@ class PollAckFlowTest extends FlowTestCase<PollAckFlow> {
runFlowAssertResponse(loadFile("poll_ack_response_empty.xml"));
}
@Test
@TestOfyAndSql
void testFailure_contactPollMessage_withIncorrectYearField() throws Exception {
setEppInput("poll_ack.xml", ImmutableMap.of("MSGID", "2-2-ROID-4-3-1999"));
persistResource(
@ -125,14 +127,14 @@ class PollAckFlowTest extends FlowTestCase<PollAckFlow> {
assertThrows(MessageDoesNotExistException.class, this::runFlow);
}
@Test
@TestOfyAndSql
void testSuccess_messageOnContactResource() throws Exception {
persistOneTimePollMessage(MESSAGE_ID);
assertTransactionalFlow(true);
runFlowAssertResponse(loadFile("poll_ack_response_empty.xml"));
}
@Test
@TestOfyAndSql
void testSuccess_recentActiveAutorenew() throws Exception {
setEppInput("poll_ack.xml", ImmutableMap.of("MSGID", "1-3-EXAMPLE-4-3-2010"));
persistAutorenewPollMessage(clock.nowUtc().minusMonths(6), END_OF_TIME);
@ -140,7 +142,7 @@ class PollAckFlowTest extends FlowTestCase<PollAckFlow> {
runFlowAssertResponse(loadFile("poll_ack_response_empty.xml"));
}
@Test
@TestOfyAndSql
void testSuccess_oldActiveAutorenew() throws Exception {
setEppInput("poll_ack.xml", ImmutableMap.of("MSGID", "1-3-EXAMPLE-4-3-2009"));
persistAutorenewPollMessage(clock.nowUtc().minusYears(2), END_OF_TIME);
@ -156,7 +158,7 @@ class PollAckFlowTest extends FlowTestCase<PollAckFlow> {
ImmutableMap.of("MSGID", "1-3-EXAMPLE-4-3-2009", "COUNT", "4")));
}
@Test
@TestOfyAndSql
void testSuccess_oldInactiveAutorenew() throws Exception {
setEppInput("poll_ack.xml", ImmutableMap.of("MSGID", "1-3-EXAMPLE-4-3-2010"));
persistAutorenewPollMessage(clock.nowUtc().minusMonths(6), clock.nowUtc());
@ -164,7 +166,7 @@ class PollAckFlowTest extends FlowTestCase<PollAckFlow> {
runFlowAssertResponse(loadFile("poll_ack_response_empty.xml"));
}
@Test
@TestOfyAndSql
void testSuccess_moreMessages() throws Exception {
// Create five messages to be queued for retrieval, one of which will be acked.
for (int i = 0; i < 5; i++) {
@ -177,28 +179,28 @@ class PollAckFlowTest extends FlowTestCase<PollAckFlow> {
ImmutableMap.of("MSGID", "1-3-EXAMPLE-4-3-2011", "COUNT", "4")));
}
@Test
@TestOfyAndSql
void testFailure_noSuchMessage() throws Exception {
assertTransactionalFlow(true);
Exception e = assertThrows(MessageDoesNotExistException.class, this::runFlow);
assertThat(e).hasMessageThat().contains(String.format("(1-3-EXAMPLE-4-%d-2011)", MESSAGE_ID));
}
@Test
@TestOfyAndSql
void testFailure_invalidId_tooFewComponents() throws Exception {
setEppInput("poll_ack.xml", ImmutableMap.of("MSGID", "1-2-3"));
assertTransactionalFlow(true);
assertThrows(InvalidMessageIdException.class, this::runFlow);
}
@Test
@TestOfyAndSql
void testFailure_invalidId_tooManyComponents() throws Exception {
setEppInput("poll_ack.xml", ImmutableMap.of("MSGID", "2-2-ROID-4-3-1999-2007"));
assertTransactionalFlow(true);
assertThrows(InvalidMessageIdException.class, this::runFlow);
}
@Test
@TestOfyAndSql
void testFailure_contactPollMessage_withMissingYearField() throws Exception {
setEppInput("poll_ack.xml", ImmutableMap.of("MSGID", "2-2-ROID-4-3"));
persistResource(
@ -213,28 +215,28 @@ class PollAckFlowTest extends FlowTestCase<PollAckFlow> {
assertThrows(InvalidMessageIdException.class, this::runFlow);
}
@Test
@TestOfyAndSql
void testFailure_invalidId_stringInsteadOfNumeric() throws Exception {
setEppInput("poll_ack.xml", ImmutableMap.of("MSGID", "ABC-12345"));
assertTransactionalFlow(true);
assertThrows(InvalidMessageIdException.class, this::runFlow);
}
@Test
@TestOfyAndSql
void testFailure_invalidEppResourceClassId() throws Exception {
setEppInput("poll_ack.xml", ImmutableMap.of("MSGID", "999-1-1-1"));
assertTransactionalFlow(true);
assertThrows(InvalidMessageIdException.class, this::runFlow);
}
@Test
@TestOfyAndSql
void testFailure_missingId() throws Exception {
setEppInput("poll_ack_missing_id.xml");
assertTransactionalFlow(true);
assertThrows(MissingMessageIdException.class, this::runFlow);
}
@Test
@TestOfyAndSql
void testFailure_differentRegistrar() throws Exception {
persistResource(
new PollMessage.OneTime.Builder()
@ -248,7 +250,7 @@ class PollAckFlowTest extends FlowTestCase<PollAckFlow> {
assertThrows(NotAuthorizedToAckMessageException.class, this::runFlow);
}
@Test
@TestOfyAndSql
void testFailure_messageInFuture() throws Exception {
persistResource(
new PollMessage.OneTime.Builder()

View file

@ -38,14 +38,16 @@ import google.registry.model.reporting.HistoryEntry;
import google.registry.model.transfer.TransferResponse.ContactTransferResponse;
import google.registry.model.transfer.TransferResponse.DomainTransferResponse;
import google.registry.model.transfer.TransferStatus;
import google.registry.testing.DualDatabaseTest;
import google.registry.testing.ReplayExtension;
import google.registry.testing.SetClockExtension;
import google.registry.testing.TestOfyAndSql;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
/** Unit tests for {@link PollRequestFlow}. */
@DualDatabaseTest
class PollRequestFlowTest extends FlowTestCase<PollRequestFlow> {
@Order(value = Order.DEFAULT - 3)
@ -92,14 +94,14 @@ class PollRequestFlowTest extends FlowTestCase<PollRequestFlow> {
.build());
}
@Test
@TestOfyAndSql
void testSuccess_domainTransferApproved() throws Exception {
persistPendingTransferPollMessage();
assertTransactionalFlow(false);
runFlowAssertResponse(loadFile("poll_response_domain_transfer.xml"));
}
@Test
@TestOfyAndSql
void testSuccess_clTridNotSpecified() throws Exception {
setEppInput("poll_no_cltrid.xml");
persistPendingTransferPollMessage();
@ -107,7 +109,7 @@ class PollRequestFlowTest extends FlowTestCase<PollRequestFlow> {
runFlowAssertResponse(loadFile("poll_response_domain_transfer_no_cltrid.xml"));
}
@Test
@TestOfyAndSql
void testSuccess_contactTransferPending() throws Exception {
setClientIdForFlow("TheRegistrar");
persistResource(
@ -130,7 +132,7 @@ class PollRequestFlowTest extends FlowTestCase<PollRequestFlow> {
runFlowAssertResponse(loadFile("poll_response_contact_transfer.xml"));
}
@Test
@TestOfyAndSql
void testSuccess_domainPendingActionComplete() throws Exception {
persistResource(
new PollMessage.OneTime.Builder()
@ -145,7 +147,7 @@ class PollRequestFlowTest extends FlowTestCase<PollRequestFlow> {
runFlowAssertResponse(loadFile("poll_response_domain_pending_notification.xml"));
}
@Test
@TestOfyAndSql
void testSuccess_domainAutorenewMessage() throws Exception {
persistResource(
new PollMessage.Autorenew.Builder()
@ -159,12 +161,12 @@ class PollRequestFlowTest extends FlowTestCase<PollRequestFlow> {
runFlowAssertResponse(loadFile("poll_response_autorenew.xml"));
}
@Test
@TestOfyAndSql
void testSuccess_empty() throws Exception {
runFlowAssertResponse(loadFile("poll_response_empty.xml"));
}
@Test
@TestOfyAndSql
void testSuccess_wrongRegistrar() throws Exception {
persistResource(
new PollMessage.OneTime.Builder()
@ -176,7 +178,7 @@ class PollRequestFlowTest extends FlowTestCase<PollRequestFlow> {
runFlowAssertResponse(loadFile("poll_response_empty.xml"));
}
@Test
@TestOfyAndSql
void testSuccess_futurePollMessage() throws Exception {
persistResource(
new PollMessage.OneTime.Builder()
@ -188,7 +190,7 @@ class PollRequestFlowTest extends FlowTestCase<PollRequestFlow> {
runFlowAssertResponse(loadFile("poll_response_empty.xml"));
}
@Test
@TestOfyAndSql
void testSuccess_futureAutorenew() throws Exception {
persistResource(
new PollMessage.Autorenew.Builder()
@ -202,7 +204,7 @@ class PollRequestFlowTest extends FlowTestCase<PollRequestFlow> {
runFlowAssertResponse(loadFile("poll_response_empty.xml"));
}
@Test
@TestOfyAndSql
void testSuccess_contactDelete() throws Exception {
// Contact delete poll messages do not have any response data, so ensure that no
// response data block is produced in the poll message.
@ -223,7 +225,7 @@ class PollRequestFlowTest extends FlowTestCase<PollRequestFlow> {
runFlowAssertResponse(loadFile("poll_response_contact_delete.xml"));
}
@Test
@TestOfyAndSql
void testSuccess_hostDelete() throws Exception {
// Host delete poll messages do not have any response data, so ensure that no
// response data block is produced in the poll message.
@ -245,7 +247,7 @@ class PollRequestFlowTest extends FlowTestCase<PollRequestFlow> {
runFlowAssertResponse(loadFile("poll_response_host_delete.xml"));
}
@Test
@TestOfyAndSql
void testFailure_messageIdProvided() throws Exception {
setEppInput("poll_with_id.xml");
assertTransactionalFlow(false);

View file

@ -25,21 +25,25 @@ import static google.registry.testing.DatabaseHelper.persistResource;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.junit.jupiter.api.Assertions.assertThrows;
import com.googlecode.objectify.Key;
import google.registry.model.domain.DomainHistory;
import google.registry.model.domain.Period;
import google.registry.model.eppcommon.Trid;
import google.registry.model.ofy.Ofy;
import google.registry.model.poll.PollMessageExternalKeyConverter.PollMessageExternalKeyParseException;
import google.registry.model.reporting.HistoryEntry;
import google.registry.persistence.VKey;
import google.registry.testing.AppEngineExtension;
import google.registry.testing.DatabaseHelper;
import google.registry.testing.DualDatabaseTest;
import google.registry.testing.FakeClock;
import google.registry.testing.InjectExtension;
import google.registry.testing.TestOfyAndSql;
import org.joda.time.DateTime;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
/** Unit tests for {@link PollMessageExternalKeyConverter}. */
@DualDatabaseTest
public class PollMessageExternalKeyConverterTest {
@RegisterExtension
@ -55,21 +59,23 @@ public class PollMessageExternalKeyConverterTest {
void beforeEach() {
inject.setStaticField(Ofy.class, "clock", clock);
createTld("foobar");
historyEntry = persistResource(new HistoryEntry.Builder()
.setParent(persistActiveDomain("foo.foobar"))
.setType(HistoryEntry.Type.DOMAIN_CREATE)
.setPeriod(Period.create(1, Period.Unit.YEARS))
.setXmlBytes("<xml></xml>".getBytes(UTF_8))
.setModificationTime(clock.nowUtc())
.setClientId("foo")
.setTrid(Trid.create("ABC-123", "server-trid"))
.setBySuperuser(false)
.setReason("reason")
.setRequestedByRegistrar(false)
.build());
historyEntry =
persistResource(
new DomainHistory.Builder()
.setParent(persistActiveDomain("foo.foobar"))
.setType(HistoryEntry.Type.DOMAIN_CREATE)
.setPeriod(Period.create(1, Period.Unit.YEARS))
.setXmlBytes("<xml></xml>".getBytes(UTF_8))
.setModificationTime(clock.nowUtc())
.setClientId("TheRegistrar")
.setTrid(Trid.create("ABC-123", "server-trid"))
.setBySuperuser(false)
.setReason("reason")
.setRequestedByRegistrar(false)
.build());
}
@Test
@TestOfyAndSql
void testSuccess_domain() {
PollMessage.OneTime pollMessage =
persistResource(
@ -80,14 +86,14 @@ public class PollMessageExternalKeyConverterTest {
.setParent(historyEntry)
.build());
assertThat(makePollMessageExternalId(pollMessage)).isEqualTo("1-2-FOOBAR-4-5-2007");
assertThat(parsePollMessageExternalId("1-2-FOOBAR-4-5-2007"))
.isEqualTo(Key.create(pollMessage));
assertVKeysEqual(parsePollMessageExternalId("1-2-FOOBAR-4-5-2007"), pollMessage.createVKey());
}
@Test
@TestOfyAndSql
void testSuccess_contact() {
historyEntry =
persistResource(historyEntry.asBuilder().setParent(persistActiveContact("tim")).build());
persistResource(
DatabaseHelper.createHistoryEntryForEppResource(persistActiveContact("tim")));
PollMessage.OneTime pollMessage =
persistResource(
new PollMessage.OneTime.Builder()
@ -96,14 +102,15 @@ public class PollMessageExternalKeyConverterTest {
.setMsg("Test poll message")
.setParent(historyEntry)
.build());
assertThat(makePollMessageExternalId(pollMessage)).isEqualTo("2-5-ROID-4-6-2007");
assertThat(parsePollMessageExternalId("2-5-ROID-4-6-2007")).isEqualTo(Key.create(pollMessage));
assertThat(makePollMessageExternalId(pollMessage)).isEqualTo("2-5-ROID-6-7-2007");
assertVKeysEqual(parsePollMessageExternalId("2-5-ROID-6-7-2007"), pollMessage.createVKey());
}
@Test
@TestOfyAndSql
void testSuccess_host() {
historyEntry =
persistResource(historyEntry.asBuilder().setParent(persistActiveHost("time.zyx")).build());
persistResource(
DatabaseHelper.createHistoryEntryForEppResource(persistActiveHost("time.xyz")));
PollMessage.OneTime pollMessage =
persistResource(
new PollMessage.OneTime.Builder()
@ -112,18 +119,18 @@ public class PollMessageExternalKeyConverterTest {
.setMsg("Test poll message")
.setParent(historyEntry)
.build());
assertThat(makePollMessageExternalId(pollMessage)).isEqualTo("3-5-ROID-4-6-2007");
assertThat(parsePollMessageExternalId("3-5-ROID-4-6-2007")).isEqualTo(Key.create(pollMessage));
assertThat(makePollMessageExternalId(pollMessage)).isEqualTo("3-5-ROID-6-7-2007");
assertVKeysEqual(parsePollMessageExternalId("3-5-ROID-6-7-2007"), pollMessage.createVKey());
}
@Test
@TestOfyAndSql
void testFailure_missingYearField() {
assertThrows(
PollMessageExternalKeyParseException.class,
() -> parsePollMessageExternalId("1-2-FOOBAR-4-5"));
}
@Test
@TestOfyAndSql
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.
@ -133,24 +140,36 @@ public class PollMessageExternalKeyConverterTest {
() -> parsePollMessageExternalId("4-2-FOOBAR-4-5-2007"));
}
@Test
@TestOfyAndSql
void testFailure_tooFewComponentParts() {
assertThrows(
PollMessageExternalKeyParseException.class,
() -> parsePollMessageExternalId("1-3-EXAMPLE"));
}
@Test
@TestOfyAndSql
void testFailure_tooManyComponentParts() {
assertThrows(
PollMessageExternalKeyParseException.class,
() -> parsePollMessageExternalId("1-3-EXAMPLE-4-5-2007-2009"));
}
@Test
@TestOfyAndSql
void testFailure_nonNumericIds() {
assertThrows(
PollMessageExternalKeyParseException.class,
() -> parsePollMessageExternalId("A-B-FOOBAR-D-E-F"));
}
// We may have VKeys of slightly varying types, e.g. VKey<PollMessage> (superclass) and
// VKey<PollMessage.OneTime> (subclass). We should treat these as equal since the DB does.
private static void assertVKeysEqual(
VKey<? extends PollMessage> one, VKey<? extends PollMessage> two) {
assertThat(
one.getKind().isAssignableFrom(two.getKind())
|| two.getKind().isAssignableFrom(one.getKind()))
.isTrue();
assertThat(one.getSqlKey()).isEqualTo(two.getSqlKey());
assertThat(one.getOfyKey()).isEqualTo(two.getOfyKey());
}
}

View file

@ -119,6 +119,7 @@ import google.registry.tmch.LordnTaskUtils;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Optional;
import java.util.Set;
import java.util.function.Function;
@ -1208,6 +1209,7 @@ public class DatabaseHelper {
.setType(getHistoryEntryType(parentResource))
.setModificationTime(DateTime.now(DateTimeZone.UTC))
.setParent(parentResource)
.setClientId(parentResource.getPersistedCurrentSponsorClientId())
.build());
}
@ -1329,5 +1331,19 @@ public class DatabaseHelper {
return transactIfJpaTm(() -> tm().loadAllOf(clazz));
}
/**
* Loads the set of entities by their keys from the DB.
*
* <p>If the transaction manager is Cloud SQL, then this creates an inner wrapping transaction for
* convenience, so you don't need to wrap it in a transaction at the callsite.
*
* <p>Nonexistent keys / entities are absent from the resulting map, but no {@link
* NoSuchElementException} will be thrown.
*/
public static <T> ImmutableMap<VKey<? extends T>, T> loadByKeysIfPresent(
Iterable<? extends VKey<? extends T>> keys) {
return transactIfJpaTm(() -> tm().loadByKeysIfPresent(keys));
}
private DatabaseHelper() {}
}

View file

@ -16,39 +16,59 @@ package google.registry.tools;
import static com.google.common.collect.ImmutableList.toImmutableList;
import static com.google.common.truth.Truth.assertThat;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import static google.registry.testing.DatabaseHelper.createTld;
import static google.registry.testing.DatabaseHelper.loadByKeys;
import static google.registry.testing.DatabaseHelper.loadByKeysIfPresent;
import static google.registry.testing.DatabaseHelper.newDomainBase;
import static google.registry.testing.DatabaseHelper.persistResource;
import com.google.common.collect.ImmutableList;
import com.googlecode.objectify.Key;
import google.registry.model.domain.DomainBase;
import google.registry.model.domain.DomainHistory;
import google.registry.model.ofy.Ofy;
import google.registry.model.poll.PollMessage;
import google.registry.model.poll.PollMessage.Autorenew;
import google.registry.model.poll.PollMessage.OneTime;
import google.registry.model.reporting.HistoryEntry;
import google.registry.persistence.VKey;
import google.registry.testing.DualDatabaseTest;
import google.registry.testing.FakeClock;
import google.registry.testing.InjectExtension;
import google.registry.testing.TestOfyAndSql;
import org.joda.time.DateTime;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
/** Unit tests for {@link AckPollMessagesCommand}. */
@DualDatabaseTest
public class AckPollMessagesCommandTest extends CommandTestCase<AckPollMessagesCommand> {
private FakeClock clock = new FakeClock(DateTime.parse("2015-02-04T08:16:32.064Z"));
@RegisterExtension public final InjectExtension inject = new InjectExtension();
private DomainHistory domainHistory;
@BeforeEach
final void beforeEach() {
inject.setStaticField(Ofy.class, "clock", clock);
command.clock = clock;
createTld("tld");
DomainBase domain = newDomainBase("example.tld").asBuilder().setRepoId("FSDGS-TLD").build();
persistResource(domain);
domainHistory =
persistResource(
new DomainHistory.Builder()
.setModificationTime(clock.nowUtc())
.setDomainRepoId(domain.getRepoId())
.setType(HistoryEntry.Type.DOMAIN_CREATE)
.setId(2406L)
.build());
clock.advanceOneMilli();
}
@Test
@TestOfyAndSql
void testSuccess_doesntDeletePollMessagesInFuture() throws Exception {
VKey<OneTime> pm1 =
persistPollMessage(316L, DateTime.parse("2014-01-01T22:33:44Z"), "foobar").createVKey();
@ -60,7 +80,7 @@ public class AckPollMessagesCommandTest extends CommandTestCase<AckPollMessagesC
persistPollMessage(123L, DateTime.parse("2015-09-01T22:33:44Z"), "notme");
VKey<OneTime> pm4 = futurePollMessage.createVKey();
runCommand("-c", "TheRegistrar");
assertThat(tm().loadByKeysIfPresent(ImmutableList.of(pm1, pm2, pm3, pm4)).values())
assertThat(loadByKeysIfPresent(ImmutableList.of(pm1, pm2, pm3, pm4)).values())
.containsExactly(futurePollMessage);
assertInStdout(
"1-FSDGS-TLD-2406-624-2013,2013-05-01T22:33:44.000Z,ninelives",
@ -69,7 +89,7 @@ public class AckPollMessagesCommandTest extends CommandTestCase<AckPollMessagesC
assertNotInStdout("1-FSDGS-TLD-2406-123-2015,2015-09-01T22:33:44.000Z,notme");
}
@Test
@TestOfyAndSql
void testSuccess_resavesAutorenewPollMessages() throws Exception {
VKey<OneTime> pm1 =
persistPollMessage(316L, DateTime.parse("2014-01-01T22:33:44Z"), "foobar").createVKey();
@ -78,10 +98,8 @@ public class AckPollMessagesCommandTest extends CommandTestCase<AckPollMessagesC
Autorenew autorenew =
persistResource(
new PollMessage.Autorenew.Builder()
.setId(624L)
.setParentKey(
Key.create(
Key.create(DomainBase.class, "AAFSGS-TLD"), HistoryEntry.class, 99406L))
.setId(625L)
.setParentKey(domainHistory.createVKey().getOfyKey())
.setEventTime(DateTime.parse("2011-04-15T22:33:44Z"))
.setClientId("TheRegistrar")
.setMsg("autorenew")
@ -90,15 +108,15 @@ public class AckPollMessagesCommandTest extends CommandTestCase<AckPollMessagesC
autorenew.asBuilder().setEventTime(DateTime.parse("2012-04-15T22:33:44Z")).build();
VKey<Autorenew> pm3 = autorenew.createVKey();
runCommand("-c", "TheRegistrar");
assertThat(tm().loadByKeysIfPresent(ImmutableList.of(pm1, pm2, pm3)).values())
assertThat(loadByKeysIfPresent(ImmutableList.of(pm1, pm2, pm3)).values())
.containsExactly(resaved);
assertInStdout(
"1-AAFSGS-TLD-99406-624-2011,2011-04-15T22:33:44.000Z,autorenew",
"1-FSDGS-TLD-2406-625-2011,2011-04-15T22:33:44.000Z,autorenew",
"1-FSDGS-TLD-2406-624-2013,2013-05-01T22:33:44.000Z,ninelives",
"1-FSDGS-TLD-2406-316-2014,2014-01-01T22:33:44.000Z,foobar");
}
@Test
@TestOfyAndSql
void testSuccess_deletesExpiredAutorenewPollMessages() throws Exception {
VKey<OneTime> pm1 =
persistPollMessage(316L, DateTime.parse("2014-01-01T22:33:44Z"), "foobar").createVKey();
@ -107,10 +125,8 @@ public class AckPollMessagesCommandTest extends CommandTestCase<AckPollMessagesC
Autorenew autorenew =
persistResource(
new PollMessage.Autorenew.Builder()
.setId(624L)
.setParentKey(
Key.create(
Key.create(DomainBase.class, "AAFSGS-TLD"), HistoryEntry.class, 99406L))
.setId(625L)
.setParentKey(domainHistory.createVKey().getOfyKey())
.setEventTime(DateTime.parse("2011-04-15T22:33:44Z"))
.setAutorenewEndTime(DateTime.parse("2012-01-01T22:33:44Z"))
.setClientId("TheRegistrar")
@ -118,14 +134,14 @@ public class AckPollMessagesCommandTest extends CommandTestCase<AckPollMessagesC
.build());
VKey<Autorenew> pm3 = autorenew.createVKey();
runCommand("-c", "TheRegistrar");
assertThat(tm().loadByKeysIfPresent(ImmutableList.of(pm1, pm2, pm3))).isEmpty();
assertThat(loadByKeysIfPresent(ImmutableList.of(pm1, pm2, pm3))).isEmpty();
assertInStdout(
"1-AAFSGS-TLD-99406-624-2011,2011-04-15T22:33:44.000Z,autorenew",
"1-FSDGS-TLD-2406-625-2011,2011-04-15T22:33:44.000Z,autorenew",
"1-FSDGS-TLD-2406-624-2013,2013-05-01T22:33:44.000Z,ninelives",
"1-FSDGS-TLD-2406-316-2014,2014-01-01T22:33:44.000Z,foobar");
}
@Test
@TestOfyAndSql
void testSuccess_onlyDeletesPollMessagesMatchingMessage() throws Exception {
VKey<OneTime> pm1 =
persistPollMessage(316L, DateTime.parse("2014-01-01T22:33:44Z"), "food is good")
@ -139,11 +155,11 @@ public class AckPollMessagesCommandTest extends CommandTestCase<AckPollMessagesC
persistPollMessage(123L, DateTime.parse("2015-09-01T22:33:44Z"), "time flies");
VKey<OneTime> pm4 = notMatched2.createVKey();
runCommand("-c", "TheRegistrar", "-m", "food");
assertThat(tm().loadByKeysIfPresent(ImmutableList.of(pm1, pm2, pm3, pm4)).values())
assertThat(loadByKeysIfPresent(ImmutableList.of(pm1, pm2, pm3, pm4)).values())
.containsExactly(notMatched1, notMatched2);
}
@Test
@TestOfyAndSql
void testSuccess_onlyDeletesPollMessagesMatchingClientId() throws Exception {
VKey<OneTime> pm1 =
persistPollMessage(316L, DateTime.parse("2014-01-01T22:33:44Z"), "food is good")
@ -155,20 +171,18 @@ public class AckPollMessagesCommandTest extends CommandTestCase<AckPollMessagesC
persistResource(
new PollMessage.OneTime.Builder()
.setId(2474L)
.setParentKey(
Key.create(
Key.create(DomainBase.class, "FSDGS-TLD"), HistoryEntry.class, 2406L))
.setParentKey(domainHistory.createVKey().getOfyKey())
.setClientId("NewRegistrar")
.setEventTime(DateTime.parse("2013-06-01T22:33:44Z"))
.setMsg("baaaahh")
.build());
VKey<OneTime> pm3 = notMatched.createVKey();
runCommand("-c", "TheRegistrar");
assertThat(tm().loadByKeysIfPresent(ImmutableList.of(pm1, pm2, pm3)).values())
assertThat(loadByKeysIfPresent(ImmutableList.of(pm1, pm2, pm3)).values())
.containsExactly(notMatched);
}
@Test
@TestOfyAndSql
void testSuccess_dryRunDoesntDeleteAnything() throws Exception {
OneTime pm1 = persistPollMessage(316L, DateTime.parse("2014-01-01T22:33:44Z"), "foobar");
OneTime pm2 = persistPollMessage(624L, DateTime.parse("2013-05-01T22:33:44Z"), "ninelives");
@ -176,20 +190,22 @@ public class AckPollMessagesCommandTest extends CommandTestCase<AckPollMessagesC
OneTime pm4 = persistPollMessage(123L, DateTime.parse("2015-09-01T22:33:44Z"), "notme");
runCommand("-c", "TheRegistrar", "-d");
assertThat(
tm().loadByKeys(
ImmutableList.of(pm1, pm2, pm3, pm4).stream()
.map(OneTime::createVKey)
.collect(toImmutableList()))
.values())
loadByKeys(
ImmutableList.of(pm1, pm2, pm3, pm4).stream()
.map(OneTime::createVKey)
.collect(toImmutableList())))
.containsExactly(pm1, pm2, pm3, pm4);
}
private static OneTime persistPollMessage(long id, DateTime eventTime, String message) {
private OneTime persistPollMessage(long id, DateTime eventTime, String message) {
return persistResource(
new PollMessage.OneTime.Builder()
.setId(id)
.setParentKey(
Key.create(Key.create(DomainBase.class, "FSDGS-TLD"), HistoryEntry.class, 2406L))
Key.create(
Key.create(DomainBase.class, "FSDGS-TLD"),
HistoryEntry.class,
domainHistory.getId()))
.setClientId("TheRegistrar")
.setEventTime(eventTime)
.setMsg(message)

View file

@ -510,14 +510,14 @@ class google.registry.model.poll.PendingActionNotificationResponse$NameOrId {
}
class google.registry.model.poll.PollMessage {
@Id java.lang.Long id;
@Parent com.googlecode.objectify.Key<google.registry.model.reporting.HistoryEntry> parent;
@Parent com.googlecode.objectify.Key<? extends google.registry.model.reporting.HistoryEntry> parent;
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;
@Parent com.googlecode.objectify.Key<google.registry.model.reporting.HistoryEntry> parent;
@Parent com.googlecode.objectify.Key<? extends google.registry.model.reporting.HistoryEntry> parent;
java.lang.String clientId;
java.lang.String msg;
java.lang.String targetId;
@ -526,7 +526,7 @@ class google.registry.model.poll.PollMessage$Autorenew {
}
class google.registry.model.poll.PollMessage$OneTime {
@Id java.lang.Long id;
@Parent com.googlecode.objectify.Key<google.registry.model.reporting.HistoryEntry> parent;
@Parent com.googlecode.objectify.Key<? extends google.registry.model.reporting.HistoryEntry> parent;
java.lang.String clientId;
java.lang.String msg;
java.util.List<google.registry.model.poll.PendingActionNotificationResponse$ContactPendingActionNotificationResponse> contactPendingActionNotificationResponses;