mirror of
https://github.com/google/nomulus.git
synced 2025-07-09 04:33:28 +02:00
Add dual read for cursors (#473)
* Add dual read for cursors * Fix loadAndCompareAll to batch load cursors * fix javadocs
This commit is contained in:
parent
be395611ca
commit
f53aa8d55e
13 changed files with 323 additions and 50 deletions
|
@ -19,6 +19,8 @@ import static google.registry.model.common.Cursor.CursorType.BRDA;
|
|||
import static google.registry.model.common.Cursor.CursorType.RDE_UPLOAD;
|
||||
import static google.registry.model.common.Cursor.CursorType.RECURRING_BILLING;
|
||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||
import static google.registry.schema.cursor.Cursor.GLOBAL;
|
||||
import static google.registry.schema.cursor.CursorDao.loadAndCompare;
|
||||
import static google.registry.testing.DatastoreHelper.createTld;
|
||||
import static google.registry.testing.DatastoreHelper.persistActiveDomain;
|
||||
import static google.registry.util.DateTimeUtils.START_OF_TIME;
|
||||
|
@ -27,19 +29,30 @@ import static org.junit.Assert.assertThrows;
|
|||
import google.registry.model.EntityTestCase;
|
||||
import google.registry.model.domain.DomainBase;
|
||||
import google.registry.model.registry.Registry;
|
||||
import google.registry.persistence.transaction.JpaTestRules;
|
||||
import google.registry.persistence.transaction.JpaTestRules.JpaIntegrationWithCoverageRule;
|
||||
import google.registry.schema.cursor.CursorDao;
|
||||
import google.registry.testing.FakeClock;
|
||||
import org.joda.time.DateTime;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
|
||||
/** Unit tests for {@link Cursor}. */
|
||||
public class CursorTest extends EntityTestCase {
|
||||
|
||||
private final FakeClock fakeClock = new FakeClock(DateTime.parse("2010-10-17TZ"));
|
||||
|
||||
@Rule
|
||||
public final JpaIntegrationWithCoverageRule jpaRule =
|
||||
new JpaTestRules.Builder().withClock(fakeClock).buildIntegrationWithCoverageRule();
|
||||
|
||||
@Test
|
||||
public void testSuccess_persistScopedCursor() {
|
||||
createTld("tld");
|
||||
clock.advanceOneMilli();
|
||||
final DateTime time = DateTime.parse("2012-07-12T03:30:00.000Z");
|
||||
CursorDao.saveCursor(Cursor.create(RDE_UPLOAD, time, Registry.get("tld")), "tld");
|
||||
Cursor cursor = Cursor.create(RDE_UPLOAD, time, Registry.get("tld"));
|
||||
CursorDao.saveCursor(cursor, "tld");
|
||||
assertThat(ofy().load().key(Cursor.createKey(BRDA, Registry.get("tld"))).now()).isNull();
|
||||
assertThat(
|
||||
ofy()
|
||||
|
@ -48,23 +61,24 @@ public class CursorTest extends EntityTestCase {
|
|||
.now()
|
||||
.getCursorTime())
|
||||
.isEqualTo(time);
|
||||
loadAndCompare(cursor, "tld");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSuccess_persistGlobalCursor() {
|
||||
final DateTime time = DateTime.parse("2012-07-12T03:30:00.000Z");
|
||||
CursorDao.saveCursor(
|
||||
Cursor.createGlobal(RECURRING_BILLING, time), google.registry.schema.cursor.Cursor.GLOBAL);
|
||||
CursorDao.saveCursor(Cursor.createGlobal(RECURRING_BILLING, time), GLOBAL);
|
||||
assertThat(ofy().load().key(Cursor.createGlobalKey(RECURRING_BILLING)).now().getCursorTime())
|
||||
.isEqualTo(time);
|
||||
loadAndCompare(Cursor.createGlobal(RECURRING_BILLING, time), GLOBAL);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIndexing() throws Exception {
|
||||
final DateTime time = DateTime.parse("2012-07-12T03:30:00.000Z");
|
||||
CursorDao.saveCursor(
|
||||
Cursor.createGlobal(RECURRING_BILLING, time), google.registry.schema.cursor.Cursor.GLOBAL);
|
||||
CursorDao.saveCursor(Cursor.createGlobal(RECURRING_BILLING, time), GLOBAL);
|
||||
Cursor cursor = ofy().load().key(Cursor.createGlobalKey(RECURRING_BILLING)).now();
|
||||
loadAndCompare(cursor, GLOBAL);
|
||||
verifyIndexing(cursor);
|
||||
}
|
||||
|
||||
|
|
|
@ -259,4 +259,178 @@ public class CursorDaoTest {
|
|||
assertThat(createdCursor3.getCursorTime()).isEqualTo(cursor3.getCursorTime());
|
||||
assertThat(cursor3).isEqualTo(dataStoreCursor3);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void loadAndCompare_worksSuccessfully() {
|
||||
loggerToIntercept.addHandler(logHandler);
|
||||
createTld("tld");
|
||||
google.registry.model.common.Cursor cursor =
|
||||
google.registry.model.common.Cursor.create(
|
||||
CursorType.ICANN_UPLOAD_ACTIVITY, fakeClock.nowUtc(), Registry.get("tld"));
|
||||
CursorDao.saveCursor(cursor, "tld");
|
||||
CursorDao.loadAndCompare(cursor, "tld");
|
||||
assertAboutLogs().that(logHandler).hasNoLogsAtLevel(Level.WARNING);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void loadAndCompare_worksSuccessfullyGlobalCursor() {
|
||||
loggerToIntercept.addHandler(logHandler);
|
||||
google.registry.model.common.Cursor cursor =
|
||||
google.registry.model.common.Cursor.createGlobal(
|
||||
CursorType.RECURRING_BILLING, fakeClock.nowUtc());
|
||||
CursorDao.saveCursor(cursor, Cursor.GLOBAL);
|
||||
CursorDao.loadAndCompare(cursor, Cursor.GLOBAL);
|
||||
assertAboutLogs().that(logHandler).hasNoLogsAtLevel(Level.WARNING);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void loadAndCompare_worksSuccessfullyCursorNotInCloudSql() {
|
||||
loggerToIntercept.addHandler(logHandler);
|
||||
createTld("tld");
|
||||
google.registry.model.common.Cursor cursor =
|
||||
google.registry.model.common.Cursor.create(
|
||||
CursorType.ICANN_UPLOAD_ACTIVITY, fakeClock.nowUtc(), Registry.get("tld"));
|
||||
CursorDao.loadAndCompare(cursor, "tld");
|
||||
assertAboutLogs()
|
||||
.that(logHandler)
|
||||
.hasLogAtLevelWithMessage(
|
||||
Level.WARNING,
|
||||
"Cursor of type ICANN_UPLOAD_ACTIVITY with the scope tld was not found in Cloud SQL.");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void loadAndCompare_worksSuccessfullyGlobalCursorNotInCloudSql() {
|
||||
loggerToIntercept.addHandler(logHandler);
|
||||
google.registry.model.common.Cursor cursor =
|
||||
google.registry.model.common.Cursor.createGlobal(
|
||||
CursorType.RECURRING_BILLING, fakeClock.nowUtc());
|
||||
CursorDao.loadAndCompare(cursor, Cursor.GLOBAL);
|
||||
assertAboutLogs()
|
||||
.that(logHandler)
|
||||
.hasLogAtLevelWithMessage(
|
||||
Level.WARNING,
|
||||
"Cursor of type RECURRING_BILLING with the scope GLOBAL was not found in Cloud SQL.");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void loadAndCompare_worksSuccessfullyCursorsNotEqual() {
|
||||
loggerToIntercept.addHandler(logHandler);
|
||||
createTld("tld");
|
||||
google.registry.model.common.Cursor cursor =
|
||||
google.registry.model.common.Cursor.create(
|
||||
CursorType.ICANN_UPLOAD_ACTIVITY, fakeClock.nowUtc(), Registry.get("tld"));
|
||||
CursorDao.saveCursor(cursor, "tld");
|
||||
cursor =
|
||||
google.registry.model.common.Cursor.create(
|
||||
CursorType.ICANN_UPLOAD_ACTIVITY, fakeClock.nowUtc().minusDays(5), Registry.get("tld"));
|
||||
CursorDao.loadAndCompare(cursor, "tld");
|
||||
assertAboutLogs()
|
||||
.that(logHandler)
|
||||
.hasLogAtLevelWithMessage(
|
||||
Level.WARNING,
|
||||
"This cursor of type ICANN_UPLOAD_ACTIVITY with the scope tld has a cursorTime of"
|
||||
+ " 1969-12-27T00:00:00.000Z in Datastore and 1970-01-01T00:00:00.000Z in Cloud"
|
||||
+ " SQL.");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void loadAndCompareAll_worksSuccessfully() {
|
||||
loggerToIntercept.addHandler(logHandler);
|
||||
|
||||
// Create Datastore cursors
|
||||
createTlds("tld", "foo");
|
||||
google.registry.model.common.Cursor cursor1 =
|
||||
google.registry.model.common.Cursor.create(
|
||||
CursorType.ICANN_UPLOAD_ACTIVITY, fakeClock.nowUtc(), Registry.get("tld"));
|
||||
google.registry.model.common.Cursor cursor2 =
|
||||
google.registry.model.common.Cursor.create(
|
||||
CursorType.ICANN_UPLOAD_ACTIVITY, fakeClock.nowUtc(), Registry.get("foo"));
|
||||
|
||||
// Save cursors to Cloud SQL
|
||||
ImmutableMap<google.registry.model.common.Cursor, String> cursors =
|
||||
ImmutableMap.<google.registry.model.common.Cursor, String>builder()
|
||||
.put(cursor1, "tld")
|
||||
.put(cursor2, "foo")
|
||||
.build();
|
||||
CursorDao.saveCursors(cursors);
|
||||
|
||||
CursorDao.loadAndCompareAll(cursors, CursorType.ICANN_UPLOAD_ACTIVITY);
|
||||
assertAboutLogs().that(logHandler).hasNoLogsAtLevel(Level.WARNING);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void loadAndCompareAll_worksSuccessfullyMissingOne() {
|
||||
loggerToIntercept.addHandler(logHandler);
|
||||
|
||||
// Create Datastore cursors
|
||||
createTlds("tld", "foo", "lol");
|
||||
google.registry.model.common.Cursor cursor1 =
|
||||
google.registry.model.common.Cursor.create(
|
||||
CursorType.ICANN_UPLOAD_ACTIVITY, fakeClock.nowUtc(), Registry.get("tld"));
|
||||
google.registry.model.common.Cursor cursor2 =
|
||||
google.registry.model.common.Cursor.create(
|
||||
CursorType.ICANN_UPLOAD_ACTIVITY, fakeClock.nowUtc(), Registry.get("foo"));
|
||||
|
||||
// Save Cursors to Cloud SQL
|
||||
ImmutableMap.Builder<google.registry.model.common.Cursor, String> cursors =
|
||||
ImmutableMap.<google.registry.model.common.Cursor, String>builder()
|
||||
.put(cursor1, "tld")
|
||||
.put(cursor2, "foo");
|
||||
CursorDao.saveCursors(cursors.build());
|
||||
|
||||
// Create a new Datastore cursor that is not saved to Cloud SQL
|
||||
google.registry.model.common.Cursor cursor3 =
|
||||
google.registry.model.common.Cursor.create(
|
||||
CursorType.ICANN_UPLOAD_ACTIVITY, fakeClock.nowUtc().minusDays(4), Registry.get("lol"));
|
||||
|
||||
// Call loadAndCompareAll with all three Datastore cursors
|
||||
CursorDao.loadAndCompareAll(
|
||||
cursors.put(cursor3, "lol").build(), CursorType.ICANN_UPLOAD_ACTIVITY);
|
||||
|
||||
assertAboutLogs()
|
||||
.that(logHandler)
|
||||
.hasLogAtLevelWithMessage(
|
||||
Level.WARNING,
|
||||
"Cursor of type ICANN_UPLOAD_ACTIVITY with the scope lol was not found in Cloud SQL.");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void loadAndCompareAll_worksSuccessfullyOneWithWrongTime() {
|
||||
loggerToIntercept.addHandler(logHandler);
|
||||
|
||||
// Create Datastore cursors
|
||||
createTlds("tld", "foo");
|
||||
google.registry.model.common.Cursor cursor1 =
|
||||
google.registry.model.common.Cursor.create(
|
||||
CursorType.ICANN_UPLOAD_ACTIVITY, fakeClock.nowUtc(), Registry.get("tld"));
|
||||
google.registry.model.common.Cursor cursor2 =
|
||||
google.registry.model.common.Cursor.create(
|
||||
CursorType.ICANN_UPLOAD_ACTIVITY, fakeClock.nowUtc(), Registry.get("foo"));
|
||||
|
||||
// Save Cursors to Cloud SQL
|
||||
CursorDao.saveCursors(ImmutableMap.of(cursor1, "tld", cursor2, "foo"));
|
||||
|
||||
// Change time of first Datastore cursor, but don't save new time to Cloud SQL
|
||||
google.registry.model.common.Cursor cursor3 =
|
||||
google.registry.model.common.Cursor.create(
|
||||
CursorType.ICANN_UPLOAD_ACTIVITY, fakeClock.nowUtc().minusDays(4), Registry.get("tld"));
|
||||
|
||||
CursorDao.loadAndCompareAll(
|
||||
ImmutableMap.of(cursor2, "foo", cursor3, "tld"), CursorType.ICANN_UPLOAD_ACTIVITY);
|
||||
|
||||
assertAboutLogs()
|
||||
.that(logHandler)
|
||||
.hasLogAtLevelWithMessage(
|
||||
Level.WARNING,
|
||||
"This cursor of type ICANN_UPLOAD_ACTIVITY with the scope tld has a cursorTime of"
|
||||
+ " 1969-12-28T00:00:00.000Z in Datastore and 1970-01-01T00:00:00.000Z in Cloud"
|
||||
+ " SQL.");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void loadAndCompareAll_worksSuccessfullyEmptyMap() {
|
||||
loggerToIntercept.addHandler(logHandler);
|
||||
CursorDao.loadAndCompareAll(ImmutableMap.of(), CursorType.ICANN_UPLOAD_ACTIVITY);
|
||||
assertAboutLogs().that(logHandler).hasNoLogsAtLevel(Level.WARNING);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
package google.registry.schema.integration;
|
||||
|
||||
import com.google.common.truth.Expect;
|
||||
import google.registry.model.common.CursorTest;
|
||||
import google.registry.model.domain.DomainBaseSqlTest;
|
||||
import google.registry.model.registry.RegistryLockDaoTest;
|
||||
import google.registry.persistence.transaction.JpaEntityCoverage;
|
||||
|
@ -60,6 +61,7 @@ import org.junit.runners.Suite.SuiteClasses;
|
|||
CreateRegistrarCommandTest.class,
|
||||
CreateReservedListCommandTest.class,
|
||||
CursorDaoTest.class,
|
||||
CursorTest.class,
|
||||
DomainLockUtilsTest.class,
|
||||
LockDaoTest.class,
|
||||
LockDomainCommandTest.class,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue