diff --git a/java/google/registry/model/registry/RegistryCursor.java b/java/google/registry/model/registry/RegistryCursor.java index d3d9db829..bb09e3fd5 100644 --- a/java/google/registry/model/registry/RegistryCursor.java +++ b/java/google/registry/model/registry/RegistryCursor.java @@ -73,8 +73,21 @@ public class RegistryCursor extends ImmutableObject { DateTime date; - /** Convenience shortcut to load a cursor for a given registry and cursor type. */ + /** + * Convenience shortcut to load a cursor (as an {@link Optional}) for a given registry and cursor + * type. Note that this currently reads the new cursor style first, then fails back to the old + * RegistryCursor if the corresponding new style cursor does not exist. + */ public static Optional load(Registry registry, CursorType cursorType) { + Cursor newStyleCursor = + ofy() + .load() + .key(Cursor.createKey(Cursor.CursorType.valueOf(cursorType.name()), registry)) + .now(); + if (newStyleCursor != null) { + return Optional.of(newStyleCursor.getCursorTime()); + } + // New cursor style wasn't found for this TLD and cursor type, so load the old style. Key key = Key.create(Key.create(registry), RegistryCursor.class, cursorType.name()); RegistryCursor cursor = ofy().load().key(key).now(); diff --git a/javatests/google/registry/model/registry/RegistryCursorTest.java b/javatests/google/registry/model/registry/RegistryCursorTest.java index 1452f69a6..a6f19041f 100644 --- a/javatests/google/registry/model/registry/RegistryCursorTest.java +++ b/javatests/google/registry/model/registry/RegistryCursorTest.java @@ -23,6 +23,7 @@ import static google.registry.testing.DatastoreHelper.createTld; import com.googlecode.objectify.VoidWork; import google.registry.model.EntityTestCase; +import google.registry.model.common.Cursor; import org.joda.time.DateTime; import org.junit.Test; @@ -31,7 +32,7 @@ import org.junit.Test; public class RegistryCursorTest extends EntityTestCase { @Test - public void test_persistence() { + public void testPersistence() { createTld("tld"); clock.advanceOneMilli(); final DateTime time = DateTime.parse("2012-07-12T03:30:00.000Z"); @@ -43,4 +44,43 @@ public class RegistryCursorTest extends EntityTestCase { assertThat(RegistryCursor.load(Registry.get("tld"), BRDA)).isAbsent(); assertThat(RegistryCursor.load(Registry.get("tld"), RDE_UPLOAD)).hasValue(time); } + + @Test + public void testSuccess_dualRead_newOverOld() { + createTld("tld"); + final DateTime newCursorTime = DateTime.parse("2012-07-12T03:30:00.000Z"); + final DateTime oldCursorTime = DateTime.parse("2012-07-11T03:30:00.000Z"); + ofy().transact( + new VoidWork() { + @Override + public void vrun() { + ofy() + .save() + .entities( + // We can't use RegistryCursor.save() since dual-writing happens there. + RegistryCursor.create(Registry.get("tld"), RDE_UPLOAD, oldCursorTime), + Cursor.create( + Cursor.CursorType.RDE_UPLOAD, newCursorTime, Registry.get("tld"))) + .now(); + } + }); + assertThat(RegistryCursor.load(Registry.get("tld"), RDE_UPLOAD)).hasValue(newCursorTime); + } + + @Test + public void testSuccess_dualRead_onlyOld() { + createTld("tld"); + final DateTime oldCursorTime = DateTime.parse("2012-07-11T03:30:00.000Z"); + ofy().transact( + new VoidWork() { + @Override + public void vrun() { + ofy() + .save() + .entity(RegistryCursor.create(Registry.get("tld"), RDE_UPLOAD, oldCursorTime)) + .now(); + } + }); + assertThat(RegistryCursor.load(Registry.get("tld"), RDE_UPLOAD)).hasValue(oldCursorTime); + } }