mirror of
https://github.com/google/nomulus.git
synced 2025-07-21 18:26:12 +02:00
Fail genenerate invoices job when billing events not finished expanding (#1791)
This commit is contained in:
parent
5ec4ec3af5
commit
341a6e84cf
3 changed files with 59 additions and 2 deletions
|
@ -267,7 +267,7 @@
|
||||||
about 2 hours to complete, so we give 11 hours to be safe. Normally, we give 24+ hours (see
|
about 2 hours to complete, so we give 11 hours to be safe. Normally, we give 24+ hours (see
|
||||||
icannReportingStaging), but the invoicing team prefers receiving the e-mail on the first of
|
icannReportingStaging), but the invoicing team prefers receiving the e-mail on the first of
|
||||||
each month. -->
|
each month. -->
|
||||||
<schedule>1 of month 17:00</schedule>
|
<schedule>1 of month 19:00</schedule>
|
||||||
<target>backend</target>
|
<target>backend</target>
|
||||||
</cron>
|
</cron>
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,10 @@
|
||||||
package google.registry.reporting.billing;
|
package google.registry.reporting.billing;
|
||||||
|
|
||||||
import static google.registry.beam.BeamUtils.createJobName;
|
import static google.registry.beam.BeamUtils.createJobName;
|
||||||
|
import static google.registry.model.common.Cursor.CursorType.RECURRING_BILLING;
|
||||||
|
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||||
import static google.registry.request.Action.Method.POST;
|
import static google.registry.request.Action.Method.POST;
|
||||||
|
import static google.registry.util.DateTimeUtils.START_OF_TIME;
|
||||||
import static javax.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
|
import static javax.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
|
||||||
import static javax.servlet.http.HttpServletResponse.SC_OK;
|
import static javax.servlet.http.HttpServletResponse.SC_OK;
|
||||||
|
|
||||||
|
@ -29,6 +32,7 @@ import com.google.common.flogger.FluentLogger;
|
||||||
import com.google.common.net.MediaType;
|
import com.google.common.net.MediaType;
|
||||||
import google.registry.config.RegistryConfig.Config;
|
import google.registry.config.RegistryConfig.Config;
|
||||||
import google.registry.config.RegistryEnvironment;
|
import google.registry.config.RegistryEnvironment;
|
||||||
|
import google.registry.model.common.Cursor;
|
||||||
import google.registry.persistence.PersistenceModule;
|
import google.registry.persistence.PersistenceModule;
|
||||||
import google.registry.reporting.ReportingModule;
|
import google.registry.reporting.ReportingModule;
|
||||||
import google.registry.request.Action;
|
import google.registry.request.Action;
|
||||||
|
@ -40,6 +44,7 @@ import google.registry.util.Clock;
|
||||||
import google.registry.util.CloudTasksUtils;
|
import google.registry.util.CloudTasksUtils;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
import org.joda.time.DateTime;
|
||||||
import org.joda.time.Duration;
|
import org.joda.time.Duration;
|
||||||
import org.joda.time.YearMonth;
|
import org.joda.time.YearMonth;
|
||||||
|
|
||||||
|
@ -108,6 +113,19 @@ public class GenerateInvoicesAction implements Runnable {
|
||||||
response.setContentType(MediaType.PLAIN_TEXT_UTF_8);
|
response.setContentType(MediaType.PLAIN_TEXT_UTF_8);
|
||||||
logger.atInfo().log("Launching invoicing pipeline for %s.", yearMonth);
|
logger.atInfo().log("Launching invoicing pipeline for %s.", yearMonth);
|
||||||
try {
|
try {
|
||||||
|
DateTime currentCursorTime =
|
||||||
|
tm().transact(
|
||||||
|
() ->
|
||||||
|
tm().loadByKeyIfPresent(Cursor.createGlobalVKey(RECURRING_BILLING))
|
||||||
|
.orElse(Cursor.createGlobal(RECURRING_BILLING, START_OF_TIME))
|
||||||
|
.getCursorTime());
|
||||||
|
|
||||||
|
if (yearMonth.getMonthOfYear() >= currentCursorTime.getMonthOfYear()) {
|
||||||
|
throw new IllegalStateException(
|
||||||
|
"Latest billing events expansion cycle hasn't finished yet, terminating invoicing"
|
||||||
|
+ " pipeline");
|
||||||
|
}
|
||||||
|
|
||||||
LaunchFlexTemplateParameter parameter =
|
LaunchFlexTemplateParameter parameter =
|
||||||
new LaunchFlexTemplateParameter()
|
new LaunchFlexTemplateParameter()
|
||||||
.setJobName(createJobName("invoicing", clock))
|
.setJobName(createJobName("invoicing", clock))
|
||||||
|
@ -150,7 +168,7 @@ public class GenerateInvoicesAction implements Runnable {
|
||||||
}
|
}
|
||||||
response.setStatus(SC_OK);
|
response.setStatus(SC_OK);
|
||||||
response.setPayload(String.format("Launched invoicing pipeline: %s", jobId));
|
response.setPayload(String.format("Launched invoicing pipeline: %s", jobId));
|
||||||
} catch (IOException e) {
|
} catch (IOException | IllegalStateException e) {
|
||||||
logger.atWarning().withCause(e).log("Template Launch failed.");
|
logger.atWarning().withCause(e).log("Template Launch failed.");
|
||||||
emailUtils.sendAlertEmail(String.format("Pipeline Launch failed due to %s", e.getMessage()));
|
emailUtils.sendAlertEmail(String.format("Pipeline Launch failed due to %s", e.getMessage()));
|
||||||
response.setStatus(SC_INTERNAL_SERVER_ERROR);
|
response.setStatus(SC_INTERNAL_SERVER_ERROR);
|
||||||
|
|
|
@ -15,6 +15,8 @@
|
||||||
package google.registry.reporting.billing;
|
package google.registry.reporting.billing;
|
||||||
|
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
import static google.registry.model.common.Cursor.CursorType.RECURRING_BILLING;
|
||||||
|
import static google.registry.testing.DatabaseHelper.persistResource;
|
||||||
import static javax.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
|
import static javax.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
|
||||||
import static javax.servlet.http.HttpServletResponse.SC_OK;
|
import static javax.servlet.http.HttpServletResponse.SC_OK;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
|
@ -24,6 +26,7 @@ import static org.mockito.Mockito.when;
|
||||||
import com.google.cloud.tasks.v2.HttpMethod;
|
import com.google.cloud.tasks.v2.HttpMethod;
|
||||||
import com.google.common.net.MediaType;
|
import com.google.common.net.MediaType;
|
||||||
import google.registry.beam.BeamActionTestBase;
|
import google.registry.beam.BeamActionTestBase;
|
||||||
|
import google.registry.model.common.Cursor;
|
||||||
import google.registry.reporting.ReportingModule;
|
import google.registry.reporting.ReportingModule;
|
||||||
import google.registry.testing.AppEngineExtension;
|
import google.registry.testing.AppEngineExtension;
|
||||||
import google.registry.testing.CloudTasksHelper;
|
import google.registry.testing.CloudTasksHelper;
|
||||||
|
@ -31,8 +34,10 @@ import google.registry.testing.CloudTasksHelper.TaskMatcher;
|
||||||
import google.registry.testing.FakeClock;
|
import google.registry.testing.FakeClock;
|
||||||
import google.registry.util.CloudTasksUtils;
|
import google.registry.util.CloudTasksUtils;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import org.joda.time.DateTime;
|
||||||
import org.joda.time.Duration;
|
import org.joda.time.Duration;
|
||||||
import org.joda.time.YearMonth;
|
import org.joda.time.YearMonth;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||||
|
|
||||||
|
@ -49,6 +54,13 @@ class GenerateInvoicesActionTest extends BeamActionTestBase {
|
||||||
private CloudTasksUtils cloudTasksUtils = cloudTasksHelper.getTestCloudTasksUtils();
|
private CloudTasksUtils cloudTasksUtils = cloudTasksHelper.getTestCloudTasksUtils();
|
||||||
private GenerateInvoicesAction action;
|
private GenerateInvoicesAction action;
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
@Override
|
||||||
|
protected void beforeEach() throws Exception {
|
||||||
|
super.beforeEach();
|
||||||
|
persistResource(Cursor.createGlobal(RECURRING_BILLING, DateTime.parse("2017-11-30TZ")));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testLaunchTemplateJob_withPublish() throws Exception {
|
void testLaunchTemplateJob_withPublish() throws Exception {
|
||||||
action =
|
action =
|
||||||
|
@ -129,4 +141,31 @@ class GenerateInvoicesActionTest extends BeamActionTestBase {
|
||||||
verify(emailUtils).sendAlertEmail("Pipeline Launch failed due to Pipeline error");
|
verify(emailUtils).sendAlertEmail("Pipeline Launch failed due to Pipeline error");
|
||||||
cloudTasksHelper.assertNoTasksEnqueued("beam-reporting");
|
cloudTasksHelper.assertNoTasksEnqueued("beam-reporting");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testFailsToGenerateInvoicesNotExpandedBillingEvents() throws Exception {
|
||||||
|
persistResource(Cursor.createGlobal(RECURRING_BILLING, DateTime.parse("2017-10-30TZ")));
|
||||||
|
action =
|
||||||
|
new GenerateInvoicesAction(
|
||||||
|
"test-project",
|
||||||
|
"test-region",
|
||||||
|
"staging_bucket",
|
||||||
|
"billing_bucket",
|
||||||
|
"REG-INV",
|
||||||
|
false,
|
||||||
|
new YearMonth(2017, 10),
|
||||||
|
emailUtils,
|
||||||
|
cloudTasksUtils,
|
||||||
|
clock,
|
||||||
|
response,
|
||||||
|
dataflow);
|
||||||
|
action.run();
|
||||||
|
assertThat(response.getContentType()).isEqualTo(MediaType.PLAIN_TEXT_UTF_8);
|
||||||
|
assertThat(response.getStatus()).isEqualTo(SC_INTERNAL_SERVER_ERROR);
|
||||||
|
assertThat(response.getPayload())
|
||||||
|
.isEqualTo(
|
||||||
|
"Pipeline launch failed: Latest billing events expansion cycle hasn't finished yet,"
|
||||||
|
+ " terminating invoicing pipeline");
|
||||||
|
cloudTasksHelper.assertNoTasksEnqueued("beam-reporting");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue