diff --git a/java/google/registry/batch/ExpandRecurringBillingEventsAction.java b/java/google/registry/batch/ExpandRecurringBillingEventsAction.java index 5837e6fa4..625ece5a3 100644 --- a/java/google/registry/batch/ExpandRecurringBillingEventsAction.java +++ b/java/google/registry/batch/ExpandRecurringBillingEventsAction.java @@ -138,6 +138,11 @@ public class ExpandRecurringBillingEventsAction implements Runnable { return; } getContext().incrementCounter("Recurring billing events encountered"); + // Ignore any recurring billing events that have yet to apply. + if (recurring.getEventTime().isAfter(executeTime)) { + getContext().incrementCounter("Recurring billing events ignored"); + return; + } int billingEventsSaved = 0; try { billingEventsSaved = ofy().transactNew(new Work() { @@ -199,6 +204,7 @@ public class ExpandRecurringBillingEventsAction implements Runnable { t, "Error while expanding Recurring billing events for %s", recurring.getId()); getContext().incrementCounter("error: " + t.getClass().getSimpleName()); getContext().incrementCounter(ERROR_COUNTER); + throw t; } if (!isDryRun) { getContext().incrementCounter("Saved OneTime billing events", billingEventsSaved); diff --git a/javatests/google/registry/batch/ExpandRecurringBillingEventsActionTest.java b/javatests/google/registry/batch/ExpandRecurringBillingEventsActionTest.java index 7e6e8b757..755a067d7 100644 --- a/javatests/google/registry/batch/ExpandRecurringBillingEventsActionTest.java +++ b/javatests/google/registry/batch/ExpandRecurringBillingEventsActionTest.java @@ -17,6 +17,7 @@ package google.registry.batch; import static com.google.common.truth.Truth.assertThat; import static google.registry.model.common.Cursor.CursorType.RECURRING_BILLING; import static google.registry.model.ofy.ObjectifyService.ofy; +import static google.registry.testing.DatastoreHelper.assertBillingEvents; import static google.registry.testing.DatastoreHelper.assertBillingEventsForResource; import static google.registry.testing.DatastoreHelper.createTld; import static google.registry.testing.DatastoreHelper.persistActiveDomain; @@ -53,6 +54,7 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; + /** Unit tests for {@link ExpandRecurringBillingEventsAction}. */ @RunWith(JUnit4.class) public class ExpandRecurringBillingEventsActionTest @@ -259,7 +261,6 @@ public class ExpandRecurringBillingEventsActionTest action.cursorTimeParam = Optional.of(START_OF_TIME); runMapreduce(); assertBillingEventsForResource(domain, recurring); - assertCursorAt(clock.nowUtc()); } @Test @@ -664,4 +665,14 @@ public class ExpandRecurringBillingEventsActionTest IllegalArgumentException.class, "Cursor time must be earlier than execution time."); runMapreduce(); } + + @Test + public void testFailure_mapperException_doesNotMoveCursor() throws Exception { + saveCursor(START_OF_TIME); // Need a saved cursor to verify that it didn't move. + // Set target to a TLD that doesn't exist. + recurring = persistResource(recurring.asBuilder().setTargetId("domain.junk").build()); + runMapreduce(); + assertBillingEvents(recurring); // only the bogus one in datastore + assertCursorAt(START_OF_TIME); // Cursor doesn't move on a failure. + } }