1
0
mirror of https://github.com/google/nomulus synced 2026-05-26 01:30:36 +00:00

Compare commits

..

5 Commits

Author SHA1 Message Date
Lai Jiang
bbac81996b Make a few quality-of-life improvements in CloudTasksUtils (#1521)
* Make a few quality-of-life improvements in CloudTasksUtils

1. Update the method names. There are too many overloaded methods and it
   is hard to figure out which one does which without checking the
   javadoc.

2. Added a method in the task matcher to specify the delay time in
   DateTime, so the caller does not need to convert it to Timestamp.

3. Remove the expilict dependency on a clock when enqueueing a task with
   delay, the clock is now injected directly into the util instance
   itself.
2022-02-18 20:21:56 -05:00
Ben McIlwain
52c759d1db Disable prober data deletion cron job in prod & sandbox (#1525)
* Disable prober data deletion cron job in prod & sandbox

This is going to unnecessarily make the database migration more complex, and we
don't need them that badly. We'll re-enable these cron jobs once we've written
the new version of this action that handles Cloud SQL correctly (the current
version only does Datastore anyway).
2022-02-17 08:46:40 -08:00
Weimin Yu
453af87615 Ignore prober data when comparing databases (#1523)
* Ignore prober data when comparing databases

Completely ignore prober data when comparing Datastore and SQL.

Prober data deletions are not propagated from Datastore to SQL. It is
difficult to distinguish soft-deletes from normal updates, therefore
difficult to avoid false positives when looking for differences.
2022-02-15 12:01:20 -05:00
Ben McIlwain
d0d7515c0a Make NordnUploadAction resilient to duplicate task queue tasks (#1516)
This is necessary because the Cloud Tasks API is not transactionally enrolled,
so it's possible that multiple tasks might end up being enqueued. We need to be
able to handle them.
2022-02-14 14:59:46 -05:00
Michael Muller
2c70127573 Fix update timestamps for DomainContent types (#1517)
* Fix update timestamps for DomainContent types

We expect update timestamps to be updated whenever a containing entity is
modified and persisted, but unfortunately Hibernate doesn't seem to do this --
instead it appears to regard such an entity as unchanged.

To work around this, we explicitly reset the update timestamp whenever a
nested collection is modified in the Builder.

Note that this change only solves the problem for DomainContent.  All other
entitities containing UpdateAutoTimestamp will need to be audited and
instrumented with a similar change.

* Fix a handful of tests broken by this change

* Reformatted.
2022-02-14 11:31:03 -05:00
42 changed files with 253 additions and 164 deletions

View File

@@ -96,7 +96,7 @@ public final class CommitLogCheckpointAction implements Runnable {
// Enqueue a diff task between previous and current checkpoints.
cloudTasksUtils.enqueue(
QUEUE_NAME,
CloudTasksUtils.createPostTask(
cloudTasksUtils.createPostTask(
ExportCommitLogDiffAction.PATH,
Service.BACKEND.toString(),
ImmutableMultimap.of(

View File

@@ -23,7 +23,6 @@ import com.google.common.collect.ImmutableSet;
import com.google.common.flogger.FluentLogger;
import google.registry.beam.initsql.Transforms;
import google.registry.config.RegistryEnvironment;
import google.registry.model.BackupGroupRoot;
import google.registry.model.EppResource;
import google.registry.model.ImmutableObject;
import google.registry.model.annotations.DeleteAfterMigration;
@@ -185,12 +184,19 @@ final class ValidateSqlUtils {
}
return;
}
SqlEntity entity0;
SqlEntity entity1;
SqlEntity entity0 = entities.get(0);
SqlEntity entity1 = entities.get(1);
if (isSpecialCaseProberEntity(entity0) && isSpecialCaseProberEntity(entity1)) {
// Ignore prober-related data: their deletions are not propagated from Datastore to SQL.
// When code reaches here, in most cases it involves one soft deleted entity in Datastore
// and an SQL entity with its pre-deletion status.
return;
}
try {
entity0 = normalizeEntity(entities.get(0));
entity1 = normalizeEntity(entities.get(1));
entity0 = normalizeEntity(entity0);
entity1 = normalizeEntity(entity1);
} catch (Exception e) {
// Temporary debugging help. See logDiff() above.
if (!logPrinted) {
@@ -227,15 +233,6 @@ final class ValidateSqlUtils {
*/
static SqlEntity normalizeEppResource(SqlEntity eppResource) {
try {
if (isSpecialCaseProberEntity(eppResource)) {
// Clearing some timestamps. See isSpecialCaseProberEntity() for reasons.
Field lastUpdateTime = BackupGroupRoot.class.getDeclaredField("updateTimestamp");
lastUpdateTime.setAccessible(true);
lastUpdateTime.set(eppResource, null);
Field deletionTime = EppResource.class.getDeclaredField("deletionTime");
deletionTime.setAccessible(true);
deletionTime.set(eppResource, null);
}
Field authField =
eppResource instanceof DomainContent
? DomainContent.class.getDeclaredField("authInfo")

View File

@@ -304,7 +304,7 @@ public class RdeIO {
if (key.mode() == RdeMode.FULL) {
cloudTasksUtils.enqueue(
RDE_UPLOAD_QUEUE,
CloudTasksUtils.createPostTask(
cloudTasksUtils.createPostTask(
RdeUploadAction.PATH,
Service.BACKEND.getServiceId(),
ImmutableMultimap.of(
@@ -315,7 +315,7 @@ public class RdeIO {
} else {
cloudTasksUtils.enqueue(
BRDA_QUEUE,
CloudTasksUtils.createPostTask(
cloudTasksUtils.createPostTask(
BrdaCopyAction.PATH,
Service.BACKEND.getServiceId(),
ImmutableMultimap.of(

View File

@@ -21,6 +21,7 @@ import dagger.Module;
import dagger.Provides;
import google.registry.config.CredentialModule.DefaultCredential;
import google.registry.config.RegistryConfig.Config;
import google.registry.util.Clock;
import google.registry.util.CloudTasksUtils;
import google.registry.util.CloudTasksUtils.GcpCloudTasksClient;
import google.registry.util.CloudTasksUtils.SerializableCloudTasksClient;
@@ -46,8 +47,9 @@ public abstract class CloudTasksUtilsModule {
@Config("projectId") String projectId,
@Config("locationId") String locationId,
SerializableCloudTasksClient client,
Retrier retrier) {
return new CloudTasksUtils(retrier, projectId, locationId, client);
Retrier retrier,
Clock clock) {
return new CloudTasksUtils(retrier, clock, projectId, locationId, client);
}
// Provides a supplier instead of using a Dagger @Provider because the latter is not serializable.

View File

@@ -20,7 +20,6 @@ import google.registry.request.Action;
import google.registry.request.Action.Service;
import google.registry.request.Parameter;
import google.registry.request.auth.Auth;
import google.registry.util.Clock;
import google.registry.util.CloudTasksUtils;
import java.util.Optional;
import javax.inject.Inject;
@@ -35,7 +34,6 @@ public final class CommitLogFanoutAction implements Runnable {
public static final String BUCKET_PARAM = "bucket";
@Inject Clock clock;
@Inject CloudTasksUtils cloudTasksUtils;
@Inject @Parameter("endpoint") String endpoint;
@@ -43,18 +41,15 @@ public final class CommitLogFanoutAction implements Runnable {
@Inject @Parameter("jitterSeconds") Optional<Integer> jitterSeconds;
@Inject CommitLogFanoutAction() {}
@Override
public void run() {
for (int bucketId : CommitLogBucket.getBucketIds()) {
cloudTasksUtils.enqueue(
queue,
CloudTasksUtils.createPostTask(
cloudTasksUtils.createPostTaskWithJitter(
endpoint,
Service.BACKEND.toString(),
ImmutableMultimap.of(BUCKET_PARAM, Integer.toString(bucketId)),
clock,
jitterSeconds));
}
}

View File

@@ -45,7 +45,6 @@ import google.registry.request.ParameterMap;
import google.registry.request.RequestParameters;
import google.registry.request.Response;
import google.registry.request.auth.Auth;
import google.registry.util.Clock;
import google.registry.util.CloudTasksUtils;
import java.util.Optional;
import java.util.stream.Stream;
@@ -98,7 +97,6 @@ public final class TldFanoutAction implements Runnable {
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
@Inject Clock clock;
@Inject CloudTasksUtils cloudTasksUtils;
@Inject Response response;
@Inject @Parameter(ENDPOINT_PARAM) String endpoint;
@@ -159,7 +157,7 @@ public final class TldFanoutAction implements Runnable {
params = ArrayListMultimap.create(params);
params.put(RequestParameters.PARAM_TLD, tld);
}
return CloudTasksUtils.createPostTask(
endpoint, Service.BACKEND.toString(), params, clock, jitterSeconds);
return cloudTasksUtils.createPostTaskWithJitter(
endpoint, Service.BACKEND.toString(), params, jitterSeconds);
}
}

View File

@@ -253,16 +253,6 @@
<target>backend</target>
</cron>
<cron>
<url><![CDATA[/_dr/cron/fanout?queue=retryable-cron-tasks&endpoint=/_dr/task/deleteProberData&runInEmpty]]></url>
<description>
This job clears out data from probers and runs once a week.
</description>
<schedule>every monday 14:00</schedule>
<timezone>UTC</timezone>
<target>backend</target>
</cron>
<cron>
<url><![CDATA[/_dr/cron/fanout?queue=retryable-cron-tasks&endpoint=/_dr/task/exportReservedTerms&forEachRealTld]]></url>
<description>

View File

@@ -191,16 +191,6 @@
<target>backend</target>
</cron>
<cron>
<url><![CDATA[/_dr/cron/fanout?queue=retryable-cron-tasks&endpoint=/_dr/task/deleteProberData&runInEmpty]]></url>
<description>
This job clears out data from probers and runs once a week.
</description>
<schedule>every monday 14:00</schedule>
<timezone>UTC</timezone>
<target>backend</target>
</cron>
<cron>
<url><![CDATA[/_dr/cron/fanout?queue=retryable-cron-tasks&endpoint=/_dr/task/exportReservedTerms&forEachRealTld]]></url>
<description>

View File

@@ -334,7 +334,8 @@ public class LoadTestAction implements Runnable {
tasks.add(
Task.newBuilder()
.setAppEngineHttpRequest(
CloudTasksUtils.createPostTask(
cloudTasksUtils
.createPostTask(
"/_dr/epptool",
Service.TOOLS.toString(),
ImmutableMultimap.of(

View File

@@ -60,4 +60,25 @@ public abstract class BackupGroupRoot extends ImmutableObject implements UnsafeS
protected void copyUpdateTimestamp(BackupGroupRoot other) {
this.updateTimestamp = PreconditionsUtils.checkArgumentNotNull(other, "other").updateTimestamp;
}
/**
* Resets the {@link #updateTimestamp} to force Hibernate to persist it.
*
* <p>This method is for use in setters in derived builders that do not result in the derived
* object being persisted.
*/
protected void resetUpdateTimestamp() {
this.updateTimestamp = UpdateAutoTimestamp.create(null);
}
/**
* Sets the {@link #updateTimestamp}.
*
* <p>This method is for use in the few places where we need to restore the update timestamp after
* mutating a collection in order to force the new timestamp to be persisted when it ordinarily
* wouldn't.
*/
protected void setUpdateTimestamp(UpdateAutoTimestamp timestamp) {
updateTimestamp = timestamp;
}
}

View File

@@ -362,6 +362,16 @@ public abstract class EppResource extends BackupGroupRoot implements Buildable {
return thisCastToDerived();
}
/**
* Set the update timestamp.
*
* <p>This is provided at EppResource since BackupGroupRoot doesn't have a Builder.
*/
public B setUpdateTimestamp(UpdateAutoTimestamp updateTimestamp) {
getInstance().setUpdateTimestamp(updateTimestamp);
return thisCastToDerived();
}
/** Build the resource, nullifying empty strings and sets and setting defaults. */
@Override
public T build() {

View File

@@ -74,6 +74,8 @@ public class BulkQueryEntities {
builder.setGracePeriods(gracePeriods);
builder.setDsData(delegationSignerData);
builder.setNameservers(nsHosts);
// Restore the original update timestamp (this gets cleared when we set nameservers or DS data).
builder.setUpdateTimestamp(domainBaseLite.getUpdateTimestamp());
return builder.build();
}
@@ -100,6 +102,9 @@ public class BulkQueryEntities {
dsDataHistories.stream()
.map(DelegationSignerData::create)
.collect(toImmutableSet()))
// Restore the original update timestamp (this gets cleared when we set nameservers or
// DS data).
.setUpdateTimestamp(domainHistoryLite.domainContent.getUpdateTimestamp())
.build();
builder.setDomain(newDomainContent);
}

View File

@@ -895,6 +895,7 @@ public class DomainContent extends EppResource
public B setDsData(ImmutableSet<DelegationSignerData> dsData) {
getInstance().dsData = dsData;
getInstance().resetUpdateTimestamp();
return thisCastToDerived();
}
@@ -918,11 +919,13 @@ public class DomainContent extends EppResource
public B setNameservers(VKey<HostResource> nameserver) {
getInstance().nsHosts = ImmutableSet.of(nameserver);
getInstance().resetUpdateTimestamp();
return thisCastToDerived();
}
public B setNameservers(ImmutableSet<VKey<HostResource>> nameservers) {
getInstance().nsHosts = forceEmptyToNull(nameservers);
getInstance().resetUpdateTimestamp();
return thisCastToDerived();
}

View File

@@ -233,14 +233,14 @@ public final class RdeStagingReducer extends Reducer<PendingDeposit, DepositFrag
if (mode == RdeMode.FULL) {
cloudTasksUtils.enqueue(
"rde-upload",
CloudTasksUtils.createPostTask(
cloudTasksUtils.createPostTask(
RdeUploadAction.PATH,
Service.BACKEND.toString(),
ImmutableMultimap.of(RequestParameters.PARAM_TLD, tld)));
} else {
cloudTasksUtils.enqueue(
"brda",
CloudTasksUtils.createPostTask(
cloudTasksUtils.createPostTask(
BrdaCopyAction.PATH,
Service.BACKEND.toString(),
ImmutableMultimap.of(

View File

@@ -134,7 +134,7 @@ public final class RdeUploadAction implements Runnable, EscrowTask {
}
cloudTasksUtils.enqueue(
RDE_REPORT_QUEUE,
CloudTasksUtils.createPostTask(
cloudTasksUtils.createPostTask(
RdeReportAction.PATH, Service.BACKEND.getServiceId(), params));
}

View File

@@ -151,7 +151,7 @@ public class GenerateInvoicesAction implements Runnable {
if (shouldPublish) {
cloudTasksUtils.enqueue(
ReportingModule.BEAM_QUEUE,
CloudTasksUtils.createPostTask(
cloudTasksUtils.createPostTaskWithDelay(
PublishInvoicesAction.PATH,
Service.BACKEND.toString(),
ImmutableMultimap.of(
@@ -159,7 +159,6 @@ public class GenerateInvoicesAction implements Runnable {
jobId,
ReportingModule.PARAM_YEAR_MONTH,
yearMonth.toString()),
clock,
Duration.standardMinutes(ReportingModule.ENQUEUE_DELAY_MINUTES)));
}
response.setStatus(SC_OK);

View File

@@ -125,7 +125,7 @@ public class PublishInvoicesAction implements Runnable {
private void enqueueCopyDetailReportsTask() {
cloudTasksUtils.enqueue(
BillingModule.CRON_QUEUE,
CloudTasksUtils.createPostTask(
cloudTasksUtils.createPostTask(
CopyDetailReportsAction.PATH,
Service.BACKEND.toString(),
ImmutableMultimap.of(PARAM_YEAR_MONTH, yearMonth.toString())));

View File

@@ -34,7 +34,6 @@ import google.registry.request.Action.Service;
import google.registry.request.Parameter;
import google.registry.request.Response;
import google.registry.request.auth.Auth;
import google.registry.util.Clock;
import google.registry.util.CloudTasksUtils;
import google.registry.util.EmailMessage;
import google.registry.util.Retrier;
@@ -86,7 +85,6 @@ public final class IcannReportingStagingAction implements Runnable {
@Inject @Config("gSuiteOutgoingEmailAddress") InternetAddress sender;
@Inject @Config("alertRecipientEmailAddress") InternetAddress recipient;
@Inject SendEmailService emailService;
@Inject Clock clock;
@Inject CloudTasksUtils cloudTasksUtils;
@Inject IcannReportingStagingAction() {}
@@ -123,11 +121,10 @@ public final class IcannReportingStagingAction implements Runnable {
logger.atInfo().log("Enqueueing report upload.");
cloudTasksUtils.enqueue(
CRON_QUEUE,
CloudTasksUtils.createPostTask(
cloudTasksUtils.createPostTaskWithDelay(
IcannReportingUploadAction.PATH,
Service.BACKEND.toString(),
null,
clock,
Duration.standardMinutes(2)));
return null;
},

View File

@@ -144,7 +144,7 @@ public class GenerateSpec11ReportAction implements Runnable {
if (sendEmail) {
cloudTasksUtils.enqueue(
ReportingModule.BEAM_QUEUE,
CloudTasksUtils.createPostTask(
cloudTasksUtils.createPostTaskWithDelay(
PublishSpec11ReportAction.PATH,
Service.BACKEND.toString(),
ImmutableMultimap.of(
@@ -152,7 +152,6 @@ public class GenerateSpec11ReportAction implements Runnable {
jobId,
ReportingModule.PARAM_DATE,
date.toString()),
clock,
Duration.standardMinutes(ReportingModule.ENQUEUE_DELAY_MINUTES)));
}
response.setStatus(SC_OK);

View File

@@ -39,8 +39,11 @@ import com.google.appengine.api.urlfetch.HTTPRequest;
import com.google.appengine.api.urlfetch.HTTPResponse;
import com.google.appengine.api.urlfetch.URLFetchService;
import com.google.apphosting.api.DeadlineExceededException;
import com.google.common.base.Joiner;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSortedSet;
import com.google.common.collect.Ordering;
import com.google.common.flogger.FluentLogger;
import google.registry.config.RegistryConfig.Config;
import google.registry.request.Action;
@@ -125,15 +128,19 @@ public final class NordnUploadAction implements Runnable {
* delimited String.
*/
static String convertTasksToCsv(List<TaskHandle> tasks, DateTime now, String columns) {
String header = String.format("1,%s,%d\n%s\n", now, tasks.size(), columns);
StringBuilder csv = new StringBuilder(header);
// Use a Set for deduping purposes so we can be idempotent in case tasks happened to be
// enqueued multiple times for a given domain create.
ImmutableSortedSet.Builder<String> builder =
new ImmutableSortedSet.Builder<>(Ordering.natural());
for (TaskHandle task : checkNotNull(tasks)) {
String payload = new String(task.getPayload(), UTF_8);
if (!Strings.isNullOrEmpty(payload)) {
csv.append(payload).append("\n");
builder.add(payload + '\n');
}
}
return csv.toString();
ImmutableSortedSet<String> csvLines = builder.build();
String header = String.format("1,%s,%d\n%s\n", now, csvLines.size(), columns);
return header + Joiner.on("").join(csvLines);
}
/** Leases and returns all tasks from the queue with the specified tag tld, in batches. */
@@ -168,6 +175,11 @@ public final class NordnUploadAction implements Runnable {
: LordnTaskUtils.QUEUE_CLAIMS);
String columns = phase.equals(PARAM_LORDN_PHASE_SUNRISE) ? COLUMNS_SUNRISE : COLUMNS_CLAIMS;
List<TaskHandle> tasks = loadAllTasks(queue, tld);
// Note: This upload/task deletion isn't done atomically (it's not clear how one would do so
// anyway). As a result, it is possible that the upload might succeed yet the deletion of
// enqueued tasks might fail. If so, this would result in the same lines being uploaded to NORDN
// across mulitple uploads. This is probably OK; all that we really cannot have is a missing
// line.
if (!tasks.isEmpty()) {
String csvData = convertTasksToCsv(tasks, now, columns);
uploadCsvToLordn(String.format("/LORDN/%s/%s", tld, phase), csvData);

View File

@@ -133,7 +133,7 @@ final class GenerateEscrowDepositCommand implements CommandWithRemoteApi {
}
cloudTasksUtils.enqueue(
RDE_REPORT_QUEUE,
CloudTasksUtils.createPostTask(
cloudTasksUtils.createPostTask(
RdeStagingAction.PATH, Service.BACKEND.toString(), paramsBuilder.build()));
}

View File

@@ -641,7 +641,7 @@ public class RegistrarSettingsAction implements Runnable, JsonActionRunner.JsonA
// there's an update besides the lastUpdateTime
cloudTasksUtils.enqueue(
SyncRegistrarsSheetAction.QUEUE,
CloudTasksUtils.createGetTask(
cloudTasksUtils.createGetTask(
SyncRegistrarsSheetAction.PATH, Service.BACKEND.toString(), ImmutableMultimap.of()));
}
String environment = Ascii.toLowerCase(String.valueOf(RegistryEnvironment.get()));

View File

@@ -195,7 +195,7 @@ public class DomainBaseUtilTest {
domainTransformedByUtil = domainTransformedByUtil.asBuilder().build();
assertAboutImmutableObjects()
.that(domainTransformedByUtil)
.isEqualExceptFields(domainTransformedByOfy, "revisions");
.isEqualExceptFields(domainTransformedByOfy, "revisions", "updateTimestamp");
}
@Test
@@ -218,7 +218,7 @@ public class DomainBaseUtilTest {
domainTransformedByUtil = domainTransformedByUtil.asBuilder().build();
assertAboutImmutableObjects()
.that(domainTransformedByUtil)
.isEqualExceptFields(domainWithoutFKeys, "revisions");
.isEqualExceptFields(domainWithoutFKeys, "revisions", "updateTimestamp");
}
@Test

View File

@@ -33,7 +33,7 @@ class CommitLogFanoutActionTest {
private static final String ENDPOINT = "/the/servlet";
private static final String QUEUE = "the-queue";
private final CloudTasksHelper cloudTasksHelper = new CloudTasksHelper();
private final CloudTasksHelper cloudTasksHelper = new CloudTasksHelper(new FakeClock());
@RegisterExtension
final AppEngineExtension appEngineExtension =
@@ -58,7 +58,6 @@ class CommitLogFanoutActionTest {
action.endpoint = ENDPOINT;
action.queue = QUEUE;
action.jitterSeconds = Optional.empty();
action.clock = new FakeClock();
action.run();
List<TaskMatcher> matchers = new ArrayList<>();
for (int bucketId : CommitLogBucket.getBucketIds()) {

View File

@@ -45,7 +45,7 @@ class TldFanoutActionTest {
private static final String ENDPOINT = "/the/servlet";
private static final String QUEUE = "the-queue";
private final FakeResponse response = new FakeResponse();
private final CloudTasksHelper cloudTasksHelper = new CloudTasksHelper();
private final CloudTasksHelper cloudTasksHelper = new CloudTasksHelper(new FakeClock());
@RegisterExtension
final AppEngineExtension appEngine =
@@ -61,7 +61,6 @@ class TldFanoutActionTest {
private void run(ImmutableListMultimap<String, String> params) {
TldFanoutAction action = new TldFanoutAction();
action.clock = new FakeClock();
action.params = params;
action.endpoint = ENDPOINT;
action.queue = QUEUE;

View File

@@ -671,4 +671,56 @@ public class DomainBaseSqlTest {
.that(domain.getTransferData())
.isEqualExceptFields(thatDomain.getTransferData(), "serverApproveEntities");
}
@TestSqlOnly
void testUpdateTimeAfterNameserverUpdate() {
persistDomain();
DomainBase persisted = loadByKey(domain.createVKey());
DateTime originalUpdateTime = persisted.getUpdateTimestamp().getTimestamp();
fakeClock.advanceOneMilli();
DateTime transactionTime =
jpaTm()
.transact(
() -> {
HostResource host2 =
new HostResource.Builder()
.setRepoId("host2")
.setHostName("ns2.example.com")
.setCreationRegistrarId("registrar1")
.setPersistedCurrentSponsorRegistrarId("registrar2")
.build();
insertInDb(host2);
domain = persisted.asBuilder().addNameserver(host2.createVKey()).build();
updateInDb(domain);
return jpaTm().getTransactionTime();
});
domain = loadByKey(domain.createVKey());
assertThat(domain.getUpdateTimestamp().getTimestamp()).isEqualTo(transactionTime);
assertThat(domain.getUpdateTimestamp().getTimestamp()).isNotEqualTo(originalUpdateTime);
}
@TestSqlOnly
void testUpdateTimeAfterDsDataUpdate() {
persistDomain();
DomainBase persisted = loadByKey(domain.createVKey());
DateTime originalUpdateTime = persisted.getUpdateTimestamp().getTimestamp();
fakeClock.advanceOneMilli();
DateTime transactionTime =
jpaTm()
.transact(
() -> {
domain =
persisted
.asBuilder()
.setDsData(
ImmutableSet.of(
DelegationSignerData.create(1, 2, 3, new byte[] {0, 1, 2})))
.build();
updateInDb(domain);
return jpaTm().getTransactionTime();
});
domain = loadByKey(domain.createVKey());
assertThat(domain.getUpdateTimestamp().getTimestamp()).isEqualTo(transactionTime);
assertThat(domain.getUpdateTimestamp().getTimestamp()).isNotEqualTo(originalUpdateTime);
}
}

View File

@@ -23,7 +23,6 @@ import static org.mockito.Mockito.when;
import com.google.cloud.tasks.v2.HttpMethod;
import com.google.common.net.MediaType;
import com.google.protobuf.util.Timestamps;
import google.registry.beam.BeamActionTestBase;
import google.registry.model.common.DatabaseMigrationStateSchedule.PrimaryDatabase;
import google.registry.reporting.ReportingModule;
@@ -83,11 +82,9 @@ class GenerateInvoicesActionTest extends BeamActionTestBase {
.param("jobId", "jobid")
.param("yearMonth", "2017-10")
.scheduleTime(
Timestamps.fromMillis(
clock
.nowUtc()
.plus(Duration.standardMinutes(ReportingModule.ENQUEUE_DELAY_MINUTES))
.getMillis())));
clock
.nowUtc()
.plus(Duration.standardMinutes(ReportingModule.ENQUEUE_DELAY_MINUTES))));
}
@TestOfyAndSql

View File

@@ -24,7 +24,6 @@ import static org.mockito.Mockito.when;
import com.google.cloud.tasks.v2.HttpMethod;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.protobuf.util.Timestamps;
import google.registry.bigquery.BigqueryJobFailureException;
import google.registry.reporting.icann.IcannReportingModule.ReportType;
import google.registry.request.HttpException.BadRequestException;
@@ -54,7 +53,8 @@ class IcannReportingStagingActionTest {
private YearMonth yearMonth = new YearMonth(2017, 6);
private String subdir = "default/dir";
private IcannReportingStagingAction action;
private CloudTasksHelper cloudTasksHelper = new CloudTasksHelper();
private FakeClock clock = new FakeClock(DateTime.parse("2021-01-02T11:00:00Z"));
private CloudTasksHelper cloudTasksHelper = new CloudTasksHelper(clock);
@RegisterExtension
final AppEngineExtension appEngine =
@@ -77,7 +77,6 @@ class IcannReportingStagingActionTest {
action.recipient = new InternetAddress("recipient@example.com");
action.emailService = mock(SendEmailService.class);
action.cloudTasksUtils = cloudTasksHelper.getTestCloudTasksUtils();
action.clock = new FakeClock(DateTime.parse("2021-01-02T11:00:00Z"));
when(stager.stageReports(yearMonth, subdir, ReportType.ACTIVITY))
.thenReturn(ImmutableList.of("a", "b"));
@@ -91,9 +90,7 @@ class IcannReportingStagingActionTest {
new TaskMatcher()
.url("/_dr/task/icannReportingUpload")
.method(HttpMethod.POST)
.scheduleTime(
Timestamps.fromMillis(
action.clock.nowUtc().plus(Duration.standardMinutes(2)).getMillis())));
.scheduleTime(clock.nowUtc().plus(Duration.standardMinutes(2))));
}
@Test

View File

@@ -21,7 +21,6 @@ import static org.mockito.Mockito.when;
import com.google.cloud.tasks.v2.HttpMethod;
import com.google.common.net.MediaType;
import com.google.protobuf.util.Timestamps;
import google.registry.beam.BeamActionTestBase;
import google.registry.model.common.DatabaseMigrationStateSchedule.PrimaryDatabase;
import google.registry.reporting.ReportingModule;
@@ -44,7 +43,7 @@ class GenerateSpec11ReportActionTest extends BeamActionTestBase {
AppEngineExtension.builder().withDatastoreAndCloudSql().withTaskQueue().build();
private final FakeClock clock = new FakeClock(DateTime.parse("2018-06-11T12:23:56Z"));
private CloudTasksHelper cloudTasksHelper = new CloudTasksHelper();
private CloudTasksHelper cloudTasksHelper = new CloudTasksHelper(clock);
private CloudTasksUtils cloudTasksUtils = cloudTasksHelper.getTestCloudTasksUtils();
private GenerateSpec11ReportAction action;
@@ -101,11 +100,9 @@ class GenerateSpec11ReportActionTest extends BeamActionTestBase {
.param("jobId", "jobid")
.param("date", "2018-06-11")
.scheduleTime(
Timestamps.fromMillis(
clock
.nowUtc()
.plus(Duration.standardMinutes(ReportingModule.ENQUEUE_DELAY_MINUTES))
.getMillis())));
clock
.nowUtc()
.plus(Duration.standardMinutes(ReportingModule.ENQUEUE_DELAY_MINUTES))));
}
@Test

View File

@@ -40,6 +40,7 @@ import com.google.common.net.HttpHeaders;
import com.google.common.net.MediaType;
import com.google.common.truth.Truth8;
import com.google.protobuf.Timestamp;
import com.google.protobuf.util.Timestamps;
import google.registry.model.ImmutableObject;
import google.registry.util.CloudTasksUtils;
import google.registry.util.Retrier;
@@ -60,6 +61,7 @@ import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Function;
import java.util.function.Predicate;
import javax.annotation.Nonnull;
import org.joda.time.DateTime;
/**
* Static utility functions for testing task queues.
@@ -92,13 +94,22 @@ public class CloudTasksHelper implements Serializable {
private static final String PROJECT_ID = "test-project";
private static final String LOCATION_ID = "test-location";
private final Retrier retrier = new Retrier(new FakeSleeper(new FakeClock()), 1);
private final int instanceId = nextInstanceId.getAndIncrement();
private final CloudTasksUtils cloudTasksUtils =
new CloudTasksUtils(retrier, PROJECT_ID, LOCATION_ID, new FakeCloudTasksClient());
private final CloudTasksUtils cloudTasksUtils;
public CloudTasksHelper(FakeClock clock) {
this.cloudTasksUtils =
new CloudTasksUtils(
new Retrier(new FakeSleeper(clock), 1),
clock,
PROJECT_ID,
LOCATION_ID,
new FakeCloudTasksClient());
testTasks.put(instanceId, Multimaps.synchronizedListMultimap(LinkedListMultimap.create()));
}
public CloudTasksHelper() {
testTasks.put(instanceId, Multimaps.synchronizedListMultimap(LinkedListMultimap.create()));
this(new FakeClock());
}
public CloudTasksUtils getTestCloudTasksUtils() {
@@ -302,6 +313,10 @@ public class CloudTasksHelper implements Serializable {
return this;
}
public TaskMatcher scheduleTime(DateTime scheduleTime) {
return scheduleTime(Timestamps.fromMillis(scheduleTime.getMillis()));
}
public TaskMatcher param(String key, String value) {
checkNotNull(value, "Test error: A param can never have a null value, so don't assert it");
expected.params.put(key, value);

View File

@@ -138,13 +138,26 @@ class NordnUploadActionTest {
void test_convertTasksToCsv() {
List<TaskHandle> tasks =
ImmutableList.of(
makeTaskHandle("task1", "example", "csvLine1", "lordn-sunrise"),
makeTaskHandle("task2", "example", "csvLine2", "lordn-sunrise"),
makeTaskHandle("task1", "example", "csvLine1", "lordn-sunrise"),
makeTaskHandle("task3", "example", "ending", "lordn-sunrise"));
assertThat(NordnUploadAction.convertTasksToCsv(tasks, clock.nowUtc(), "col1,col2"))
.isEqualTo("1,2010-05-01T10:11:12.000Z,3\ncol1,col2\ncsvLine1\ncsvLine2\nending\n");
}
@MockitoSettings(strictness = Strictness.LENIENT)
@Test
void test_convertTasksToCsv_dedupesDuplicates() {
List<TaskHandle> tasks =
ImmutableList.of(
makeTaskHandle("task2", "example", "csvLine2", "lordn-sunrise"),
makeTaskHandle("task1", "example", "csvLine1", "lordn-sunrise"),
makeTaskHandle("task3", "example", "ending", "lordn-sunrise"),
makeTaskHandle("task1", "example", "csvLine1", "lordn-sunrise"));
assertThat(NordnUploadAction.convertTasksToCsv(tasks, clock.nowUtc(), "col1,col2"))
.isEqualTo("1,2010-05-01T10:11:12.000Z,3\ncol1,col2\ncsvLine1\ncsvLine2\nending\n");
}
@MockitoSettings(strictness = Strictness.LENIENT)
@Test
void test_convertTasksToCsv_doesntFailOnEmptyTasks() {

View File

@@ -30,6 +30,7 @@ com.google.http-client:google-http-client-gson:1.39.2
com.google.http-client:google-http-client:1.39.2
com.google.j2objc:j2objc-annotations:1.3
com.google.oauth-client:google-oauth-client:1.31.4
com.google.protobuf:protobuf-java-util:3.17.3
com.google.protobuf:protobuf-java:3.17.3
com.google.re2j:re2j:1.6
com.ibm.icu:icu4j:68.2

View File

@@ -34,6 +34,7 @@ com.google.http-client:google-http-client-gson:1.39.2
com.google.http-client:google-http-client:1.39.2
com.google.j2objc:j2objc-annotations:1.3
com.google.oauth-client:google-oauth-client:1.31.4
com.google.protobuf:protobuf-java-util:3.17.3
com.google.protobuf:protobuf-java:3.17.3
com.google.re2j:re2j:1.6
com.google.truth:truth:1.1.2

View File

@@ -32,6 +32,7 @@ com.google.http-client:google-http-client:1.39.2
com.google.j2objc:j2objc-annotations:1.3
com.google.monitoring-client:metrics:1.0.7
com.google.oauth-client:google-oauth-client:1.31.4
com.google.protobuf:protobuf-java-util:3.17.3
com.google.protobuf:protobuf-java:3.17.3
com.google.re2j:re2j:1.6
com.ibm.icu:icu4j:68.2

View File

@@ -37,6 +37,7 @@ com.google.j2objc:j2objc-annotations:1.3
com.google.monitoring-client:contrib:1.0.7
com.google.monitoring-client:metrics:1.0.7
com.google.oauth-client:google-oauth-client:1.31.4
com.google.protobuf:protobuf-java-util:3.17.3
com.google.protobuf:protobuf-java:3.17.3
com.google.re2j:re2j:1.6
com.google.truth:truth:1.1.2

View File

@@ -45,7 +45,7 @@ com.google.j2objc:j2objc-annotations:1.3
com.google.monitoring-client:metrics:1.0.7
com.google.monitoring-client:stackdriver:1.0.7
com.google.oauth-client:google-oauth-client:1.31.4
com.google.protobuf:protobuf-java-util:3.15.3
com.google.protobuf:protobuf-java-util:3.17.3
com.google.protobuf:protobuf-java:3.17.3
com.google.re2j:re2j:1.6
com.ibm.icu:icu4j:68.2

View File

@@ -50,7 +50,7 @@ com.google.monitoring-client:contrib:1.0.7
com.google.monitoring-client:metrics:1.0.7
com.google.monitoring-client:stackdriver:1.0.7
com.google.oauth-client:google-oauth-client:1.31.4
com.google.protobuf:protobuf-java-util:3.15.3
com.google.protobuf:protobuf-java-util:3.17.3
com.google.protobuf:protobuf-java:3.17.3
com.google.re2j:re2j:1.6
com.google.truth:truth:1.1.2

View File

@@ -30,6 +30,7 @@ dependencies {
compile deps['com.google.guava:guava']
compile deps['com.google.http-client:google-http-client']
compile deps['com.google.protobuf:protobuf-java']
compile deps['com.google.protobuf:protobuf-java-util']
compile deps['com.google.re2j:re2j']
compile deps['com.ibm.icu:icu4j']
compile deps['commons-codec:commons-codec']

View File

@@ -29,6 +29,7 @@ com.google.http-client:google-http-client-gson:1.39.2
com.google.http-client:google-http-client:1.39.2
com.google.j2objc:j2objc-annotations:1.3
com.google.oauth-client:google-oauth-client:1.31.4
com.google.protobuf:protobuf-java-util:3.17.3
com.google.protobuf:protobuf-java:3.17.3
com.google.re2j:re2j:1.6
com.ibm.icu:icu4j:68.2

View File

@@ -35,6 +35,7 @@ com.google.http-client:google-http-client-gson:1.39.2
com.google.http-client:google-http-client:1.39.2
com.google.j2objc:j2objc-annotations:1.3
com.google.oauth-client:google-oauth-client:1.31.4
com.google.protobuf:protobuf-java-util:3.17.3
com.google.protobuf:protobuf-java:3.17.3
com.google.re2j:re2j:1.6
com.google.truth:truth:1.1.2

View File

@@ -35,10 +35,9 @@ import com.google.common.net.HttpHeaders;
import com.google.common.net.MediaType;
import com.google.common.net.UrlEscapers;
import com.google.protobuf.ByteString;
import com.google.protobuf.Timestamp;
import com.google.protobuf.util.Timestamps;
import java.io.Serializable;
import java.nio.charset.StandardCharsets;
import java.time.Instant;
import java.util.Arrays;
import java.util.Optional;
import java.util.Random;
@@ -53,13 +52,19 @@ public class CloudTasksUtils implements Serializable {
private static final Random random = new Random();
private final Retrier retrier;
private final Clock clock;
private final String projectId;
private final String locationId;
private final SerializableCloudTasksClient client;
public CloudTasksUtils(
Retrier retrier, String projectId, String locationId, SerializableCloudTasksClient client) {
Retrier retrier,
Clock clock,
String projectId,
String locationId,
SerializableCloudTasksClient client) {
this.retrier = retrier;
this.clock = clock;
this.projectId = projectId;
this.locationId = locationId;
this.client = client;
@@ -102,7 +107,7 @@ public class CloudTasksUtils implements Serializable {
* href=ttps://cloud.google.com/appengine/docs/standard/java/taskqueue/push/creating-tasks#target>Specifyinig
* the worker service</a>
*/
private static Task createTask(
private Task createTask(
String path, HttpMethod method, String service, Multimap<String, String> params) {
checkArgument(
path != null && !path.isEmpty() && path.charAt(0) == '/',
@@ -151,29 +156,26 @@ public class CloudTasksUtils implements Serializable {
* needs to be explicitly specified.
* @param params a multi-map of URL query parameters. Duplicate keys are saved as is, and it is up
* to the server to process the duplicate keys.
* @param clock a source of time.
* @param jitterSeconds the number of seconds that a task is randomly delayed up to.
* @return the enqueued task.
* @see <a
* href=ttps://cloud.google.com/appengine/docs/standard/java/taskqueue/push/creating-tasks#target>Specifyinig
* the worker service</a>
*/
private static Task createTask(
private Task createTaskWithJitter(
String path,
HttpMethod method,
String service,
Multimap<String, String> params,
Clock clock,
Optional<Integer> jitterSeconds) {
if (!jitterSeconds.isPresent() || jitterSeconds.get() <= 0) {
return createTask(path, method, service, params);
}
return createTask(
return createTaskWithDelay(
path,
method,
service,
params,
clock,
Duration.millis(random.nextInt((int) SECONDS.toMillis(jitterSeconds.get()))));
}
@@ -188,76 +190,67 @@ public class CloudTasksUtils implements Serializable {
* needs to be explicitly specified.
* @param params a multi-map of URL query parameters. Duplicate keys are saved as is, and it is up
* to the server to process the duplicate keys.
* @param clock a source of time.
* @param delay the amount of time that a task needs to delayed for.
* @return the enqueued task.
* @see <a
* href=ttps://cloud.google.com/appengine/docs/standard/java/taskqueue/push/creating-tasks#target>Specifyinig
* the worker service</a>
*/
private static Task createTask(
private Task createTaskWithDelay(
String path,
HttpMethod method,
String service,
Multimap<String, String> params,
Clock clock,
Duration delay) {
if (delay.isEqual(Duration.ZERO)) {
return createTask(path, method, service, params);
}
checkArgument(delay.isLongerThan(Duration.ZERO), "Negative duration is not supported.");
Instant scheduleTime = Instant.ofEpochMilli(clock.nowUtc().getMillis() + delay.getMillis());
return Task.newBuilder(createTask(path, method, service, params))
.setScheduleTime(
Timestamp.newBuilder()
.setSeconds(scheduleTime.getEpochSecond())
.setNanos(scheduleTime.getNano())
.build())
.setScheduleTime(Timestamps.fromMillis(clock.nowUtc().plus(delay).getMillis()))
.build();
}
public static Task createPostTask(String path, String service, Multimap<String, String> params) {
public Task createPostTask(String path, String service, Multimap<String, String> params) {
return createTask(path, HttpMethod.POST, service, params);
}
public static Task createGetTask(String path, String service, Multimap<String, String> params) {
public Task createGetTask(String path, String service, Multimap<String, String> params) {
return createTask(path, HttpMethod.GET, service, params);
}
/**
* Create a {@link Task} via HTTP.POST that will be randomly delayed up to {@code jitterSeconds}.
*/
public static Task createPostTask(
public Task createPostTaskWithJitter(
String path,
String service,
Multimap<String, String> params,
Clock clock,
Optional<Integer> jitterSeconds) {
return createTask(path, HttpMethod.POST, service, params, clock, jitterSeconds);
return createTaskWithJitter(path, HttpMethod.POST, service, params, jitterSeconds);
}
/**
* Create a {@link Task} via HTTP.GET that will be randomly delayed up to {@code jitterSeconds}.
*/
public static Task createGetTask(
public Task createGetTaskWithJitter(
String path,
String service,
Multimap<String, String> params,
Clock clock,
Optional<Integer> jitterSeconds) {
return createTask(path, HttpMethod.GET, service, params, clock, jitterSeconds);
return createTaskWithJitter(path, HttpMethod.GET, service, params, jitterSeconds);
}
/** Create a {@link Task} via HTTP.POST that will be delayed for {@code delay}. */
public static Task createPostTask(
String path, String service, Multimap<String, String> params, Clock clock, Duration delay) {
return createTask(path, HttpMethod.POST, service, params, clock, delay);
public Task createPostTaskWithDelay(
String path, String service, Multimap<String, String> params, Duration delay) {
return createTaskWithDelay(path, HttpMethod.POST, service, params, delay);
}
/** Create a {@link Task} via HTTP.GET that will be delayed for {@code delay}. */
public static Task createGetTask(
String path, String service, Multimap<String, String> params, Clock clock, Duration delay) {
return createTask(path, HttpMethod.GET, service, params, clock, delay);
public Task createGetTaskWithDelay(
String path, String service, Multimap<String, String> params, Duration delay) {
return createTaskWithDelay(path, HttpMethod.GET, service, params, delay);
}
public abstract static class SerializableCloudTasksClient implements Serializable {

View File

@@ -43,10 +43,10 @@ public class CloudTasksUtilsTest {
// Use a LinkedListMultimap to preserve order of the inserted entries for assertion.
private final LinkedListMultimap<String, String> params = LinkedListMultimap.create();
private final SerializableCloudTasksClient mockClient = mock(SerializableCloudTasksClient.class);
private final FakeClock clock = new FakeClock(DateTime.parse("2021-11-08"));
private final CloudTasksUtils cloudTasksUtils =
new CloudTasksUtils(
new Retrier(new FakeSleeper(new FakeClock()), 1), "project", "location", mockClient);
private final Clock clock = new FakeClock(DateTime.parse("2021-11-08"));
new Retrier(new FakeSleeper(clock), 1), clock, "project", "location", mockClient);
@BeforeEach
void beforeEach() {
@@ -59,7 +59,7 @@ public class CloudTasksUtilsTest {
@Test
void testSuccess_createGetTasks() {
Task task = CloudTasksUtils.createGetTask("/the/path", "myservice", params);
Task task = cloudTasksUtils.createGetTask("/the/path", "myservice", params);
assertThat(task.getAppEngineHttpRequest().getHttpMethod()).isEqualTo(HttpMethod.GET);
assertThat(task.getAppEngineHttpRequest().getRelativeUri())
.isEqualTo("/the/path?key1=val1&key2=val2&key1=val3");
@@ -70,7 +70,7 @@ public class CloudTasksUtilsTest {
@Test
void testSuccess_createPostTasks() {
Task task = CloudTasksUtils.createPostTask("/the/path", "myservice", params);
Task task = cloudTasksUtils.createPostTask("/the/path", "myservice", params);
assertThat(task.getAppEngineHttpRequest().getHttpMethod()).isEqualTo(HttpMethod.POST);
assertThat(task.getAppEngineHttpRequest().getRelativeUri()).isEqualTo("/the/path");
assertThat(task.getAppEngineHttpRequest().getAppEngineRouting().getService())
@@ -84,7 +84,7 @@ public class CloudTasksUtilsTest {
@Test
void testSuccess_createGetTasks_withNullParams() {
Task task = CloudTasksUtils.createGetTask("/the/path", "myservice", null);
Task task = cloudTasksUtils.createGetTask("/the/path", "myservice", null);
assertThat(task.getAppEngineHttpRequest().getHttpMethod()).isEqualTo(HttpMethod.GET);
assertThat(task.getAppEngineHttpRequest().getRelativeUri()).isEqualTo("/the/path");
assertThat(task.getAppEngineHttpRequest().getAppEngineRouting().getService())
@@ -94,7 +94,7 @@ public class CloudTasksUtilsTest {
@Test
void testSuccess_createPostTasks_withNullParams() {
Task task = CloudTasksUtils.createPostTask("/the/path", "myservice", null);
Task task = cloudTasksUtils.createPostTask("/the/path", "myservice", null);
assertThat(task.getAppEngineHttpRequest().getHttpMethod()).isEqualTo(HttpMethod.POST);
assertThat(task.getAppEngineHttpRequest().getRelativeUri()).isEqualTo("/the/path");
assertThat(task.getAppEngineHttpRequest().getAppEngineRouting().getService())
@@ -105,7 +105,7 @@ public class CloudTasksUtilsTest {
@Test
void testSuccess_createGetTasks_withEmptyParams() {
Task task = CloudTasksUtils.createGetTask("/the/path", "myservice", ImmutableMultimap.of());
Task task = cloudTasksUtils.createGetTask("/the/path", "myservice", ImmutableMultimap.of());
assertThat(task.getAppEngineHttpRequest().getHttpMethod()).isEqualTo(HttpMethod.GET);
assertThat(task.getAppEngineHttpRequest().getRelativeUri()).isEqualTo("/the/path");
assertThat(task.getAppEngineHttpRequest().getAppEngineRouting().getService())
@@ -115,7 +115,7 @@ public class CloudTasksUtilsTest {
@Test
void testSuccess_createPostTasks_withEmptyParams() {
Task task = CloudTasksUtils.createPostTask("/the/path", "myservice", ImmutableMultimap.of());
Task task = cloudTasksUtils.createPostTask("/the/path", "myservice", ImmutableMultimap.of());
assertThat(task.getAppEngineHttpRequest().getHttpMethod()).isEqualTo(HttpMethod.POST);
assertThat(task.getAppEngineHttpRequest().getRelativeUri()).isEqualTo("/the/path");
assertThat(task.getAppEngineHttpRequest().getAppEngineRouting().getService())
@@ -128,7 +128,7 @@ public class CloudTasksUtilsTest {
@Test
void testSuccess_createGetTasks_withJitterSeconds() {
Task task =
CloudTasksUtils.createGetTask("/the/path", "myservice", params, clock, Optional.of(100));
cloudTasksUtils.createGetTaskWithJitter("/the/path", "myservice", params, Optional.of(100));
assertThat(task.getAppEngineHttpRequest().getHttpMethod()).isEqualTo(HttpMethod.GET);
assertThat(task.getAppEngineHttpRequest().getRelativeUri())
.isEqualTo("/the/path?key1=val1&key2=val2&key1=val3");
@@ -147,7 +147,7 @@ public class CloudTasksUtilsTest {
@Test
void testSuccess_createPostTasks_withJitterSeconds() {
Task task =
CloudTasksUtils.createPostTask("/the/path", "myservice", params, clock, Optional.of(1));
cloudTasksUtils.createPostTaskWithJitter("/the/path", "myservice", params, Optional.of(1));
assertThat(task.getAppEngineHttpRequest().getHttpMethod()).isEqualTo(HttpMethod.POST);
assertThat(task.getAppEngineHttpRequest().getRelativeUri()).isEqualTo("/the/path");
assertThat(task.getAppEngineHttpRequest().getAppEngineRouting().getService())
@@ -169,7 +169,8 @@ public class CloudTasksUtilsTest {
@Test
void testSuccess_createPostTasks_withEmptyJitterSeconds() {
Task task =
CloudTasksUtils.createPostTask("/the/path", "myservice", params, clock, Optional.empty());
cloudTasksUtils.createPostTaskWithJitter(
"/the/path", "myservice", params, Optional.empty());
assertThat(task.getAppEngineHttpRequest().getHttpMethod()).isEqualTo(HttpMethod.POST);
assertThat(task.getAppEngineHttpRequest().getRelativeUri()).isEqualTo("/the/path");
assertThat(task.getAppEngineHttpRequest().getAppEngineRouting().getService())
@@ -184,7 +185,7 @@ public class CloudTasksUtilsTest {
@Test
void testSuccess_createGetTasks_withEmptyJitterSeconds() {
Task task =
CloudTasksUtils.createGetTask("/the/path", "myservice", params, clock, Optional.empty());
cloudTasksUtils.createGetTaskWithJitter("/the/path", "myservice", params, Optional.empty());
assertThat(task.getAppEngineHttpRequest().getHttpMethod()).isEqualTo(HttpMethod.GET);
assertThat(task.getAppEngineHttpRequest().getRelativeUri())
.isEqualTo("/the/path?key1=val1&key2=val2&key1=val3");
@@ -196,7 +197,7 @@ public class CloudTasksUtilsTest {
@Test
void testSuccess_createPostTasks_withZeroJitterSeconds() {
Task task =
CloudTasksUtils.createPostTask("/the/path", "myservice", params, clock, Optional.of(0));
cloudTasksUtils.createPostTaskWithJitter("/the/path", "myservice", params, Optional.of(0));
assertThat(task.getAppEngineHttpRequest().getHttpMethod()).isEqualTo(HttpMethod.POST);
assertThat(task.getAppEngineHttpRequest().getRelativeUri()).isEqualTo("/the/path");
assertThat(task.getAppEngineHttpRequest().getAppEngineRouting().getService())
@@ -211,7 +212,7 @@ public class CloudTasksUtilsTest {
@Test
void testSuccess_createGetTasks_withZeroJitterSeconds() {
Task task =
CloudTasksUtils.createGetTask("/the/path", "myservice", params, clock, Optional.of(0));
cloudTasksUtils.createGetTaskWithJitter("/the/path", "myservice", params, Optional.of(0));
assertThat(task.getAppEngineHttpRequest().getHttpMethod()).isEqualTo(HttpMethod.GET);
assertThat(task.getAppEngineHttpRequest().getRelativeUri())
.isEqualTo("/the/path?key1=val1&key2=val2&key1=val3");
@@ -223,8 +224,8 @@ public class CloudTasksUtilsTest {
@Test
void testSuccess_createGetTasks_withDelay() {
Task task =
CloudTasksUtils.createGetTask(
"/the/path", "myservice", params, clock, Duration.standardMinutes(10));
cloudTasksUtils.createGetTaskWithDelay(
"/the/path", "myservice", params, Duration.standardMinutes(10));
assertThat(task.getAppEngineHttpRequest().getHttpMethod()).isEqualTo(HttpMethod.GET);
assertThat(task.getAppEngineHttpRequest().getRelativeUri())
.isEqualTo("/the/path?key1=val1&key2=val2&key1=val3");
@@ -237,8 +238,8 @@ public class CloudTasksUtilsTest {
@Test
void testSuccess_createPostTasks_withDelay() {
Task task =
CloudTasksUtils.createPostTask(
"/the/path", "myservice", params, clock, Duration.standardMinutes(10));
cloudTasksUtils.createPostTaskWithDelay(
"/the/path", "myservice", params, Duration.standardMinutes(10));
assertThat(task.getAppEngineHttpRequest().getHttpMethod()).isEqualTo(HttpMethod.POST);
assertThat(task.getAppEngineHttpRequest().getRelativeUri()).isEqualTo("/the/path");
assertThat(task.getAppEngineHttpRequest().getAppEngineRouting().getService())
@@ -258,8 +259,8 @@ public class CloudTasksUtilsTest {
assertThrows(
IllegalArgumentException.class,
() ->
CloudTasksUtils.createGetTask(
"/the/path", "myservice", params, clock, Duration.standardMinutes(-10)));
cloudTasksUtils.createGetTaskWithDelay(
"/the/path", "myservice", params, Duration.standardMinutes(-10)));
assertThat(thrown).hasMessageThat().isEqualTo("Negative duration is not supported.");
}
@@ -269,15 +270,15 @@ public class CloudTasksUtilsTest {
assertThrows(
IllegalArgumentException.class,
() ->
CloudTasksUtils.createGetTask(
"/the/path", "myservice", params, clock, Duration.standardMinutes(-10)));
cloudTasksUtils.createGetTaskWithDelay(
"/the/path", "myservice", params, Duration.standardMinutes(-10)));
assertThat(thrown).hasMessageThat().isEqualTo("Negative duration is not supported.");
}
@Test
void testSuccess_createPostTasks_withZeroDelay() {
Task task =
CloudTasksUtils.createPostTask("/the/path", "myservice", params, clock, Duration.ZERO);
cloudTasksUtils.createPostTaskWithDelay("/the/path", "myservice", params, Duration.ZERO);
assertThat(task.getAppEngineHttpRequest().getHttpMethod()).isEqualTo(HttpMethod.POST);
assertThat(task.getAppEngineHttpRequest().getRelativeUri()).isEqualTo("/the/path");
assertThat(task.getAppEngineHttpRequest().getAppEngineRouting().getService())
@@ -292,7 +293,7 @@ public class CloudTasksUtilsTest {
@Test
void testSuccess_createGetTasks_withZeroDelay() {
Task task =
CloudTasksUtils.createGetTask("/the/path", "myservice", params, clock, Duration.ZERO);
cloudTasksUtils.createGetTaskWithDelay("/the/path", "myservice", params, Duration.ZERO);
assertThat(task.getAppEngineHttpRequest().getHttpMethod()).isEqualTo(HttpMethod.GET);
assertThat(task.getAppEngineHttpRequest().getRelativeUri())
.isEqualTo("/the/path?key1=val1&key2=val2&key1=val3");
@@ -305,26 +306,26 @@ public class CloudTasksUtilsTest {
void testFailure_illegalPath() {
assertThrows(
IllegalArgumentException.class,
() -> CloudTasksUtils.createPostTask("the/path", "myservice", params));
() -> cloudTasksUtils.createPostTask("the/path", "myservice", params));
assertThrows(
IllegalArgumentException.class,
() -> CloudTasksUtils.createPostTask(null, "myservice", params));
() -> cloudTasksUtils.createPostTask(null, "myservice", params));
assertThrows(
IllegalArgumentException.class,
() -> CloudTasksUtils.createPostTask("", "myservice", params));
() -> cloudTasksUtils.createPostTask("", "myservice", params));
}
@Test
void testSuccess_enqueueTask() {
Task task = CloudTasksUtils.createGetTask("/the/path", "myservice", params);
Task task = cloudTasksUtils.createGetTask("/the/path", "myservice", params);
cloudTasksUtils.enqueue("test-queue", task);
verify(mockClient).enqueue("project", "location", "test-queue", task);
}
@Test
void testSuccess_enqueueTasks_varargs() {
Task task1 = CloudTasksUtils.createGetTask("/the/path", "myservice", params);
Task task2 = CloudTasksUtils.createGetTask("/other/path", "yourservice", params);
Task task1 = cloudTasksUtils.createGetTask("/the/path", "myservice", params);
Task task2 = cloudTasksUtils.createGetTask("/other/path", "yourservice", params);
cloudTasksUtils.enqueue("test-queue", task1, task2);
verify(mockClient).enqueue("project", "location", "test-queue", task1);
verify(mockClient).enqueue("project", "location", "test-queue", task2);
@@ -332,8 +333,8 @@ public class CloudTasksUtilsTest {
@Test
void testSuccess_enqueueTasks_iterable() {
Task task1 = CloudTasksUtils.createGetTask("/the/path", "myservice", params);
Task task2 = CloudTasksUtils.createGetTask("/other/path", "yourservice", params);
Task task1 = cloudTasksUtils.createGetTask("/the/path", "myservice", params);
Task task2 = cloudTasksUtils.createGetTask("/other/path", "yourservice", params);
cloudTasksUtils.enqueue("test-queue", ImmutableList.of(task1, task2));
verify(mockClient).enqueue("project", "location", "test-queue", task1);
verify(mockClient).enqueue("project", "location", "test-queue", task2);