diff --git a/java/google/registry/tools/server/javascrap/BUILD b/java/google/registry/tools/server/javascrap/BUILD new file mode 100644 index 000000000..96180035e --- /dev/null +++ b/java/google/registry/tools/server/javascrap/BUILD @@ -0,0 +1,26 @@ +package( + default_visibility = ["//java/google/registry:registry_project"], +) + +licenses(["notice"]) # Apache 2.0 + + +java_library( + name = "javascrap", + srcs = glob(["*.java"]), + deps = [ + "//java/com/google/common/base", + "//java/com/google/common/collect", + "//third_party/java/appengine:appengine-api", + "//third_party/java/appengine_mapreduce2:appengine_mapreduce", + "//third_party/java/dagger", + "//third_party/java/jsr305_annotations", + "//third_party/java/jsr330_inject", + "//third_party/java/objectify:objectify-v4_1", + "//java/google/registry/mapreduce", + "//java/google/registry/mapreduce/inputs", + "//java/google/registry/model", + "//java/google/registry/request", + "//java/google/registry/util", + ], +) diff --git a/java/google/registry/tools/server/javascrap/BackfillAutorenewBillingFlagAction.java b/java/google/registry/tools/server/javascrap/BackfillAutorenewBillingFlagAction.java new file mode 100644 index 000000000..d265ff9d9 --- /dev/null +++ b/java/google/registry/tools/server/javascrap/BackfillAutorenewBillingFlagAction.java @@ -0,0 +1,101 @@ +// Copyright 2016 The Domain Registry Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package google.registry.tools.server.javascrap; + +import static google.registry.mapreduce.MapreduceRunner.PARAM_DRY_RUN; +import static google.registry.mapreduce.inputs.EppResourceInputs.createChildEntityInput; +import static google.registry.model.ofy.ObjectifyService.ofy; +import static google.registry.util.PipelineUtils.createJobPath; + +import com.google.appengine.tools.mapreduce.Input; +import com.google.appengine.tools.mapreduce.Mapper; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; + +import com.googlecode.objectify.VoidWork; + +import google.registry.mapreduce.MapreduceAction; +import google.registry.mapreduce.MapreduceRunner; +import google.registry.model.billing.BillingEvent.Flag; +import google.registry.model.billing.BillingEvent.Recurring; +import google.registry.model.domain.DomainResource; +import google.registry.request.Action; +import google.registry.request.Parameter; +import google.registry.request.Response; +import google.registry.util.FormattingLogger; + +import javax.inject.Inject; + +/** A mapreduce that backfills new {@link Flag#AUTO_RENEW} flag on recurring billing events. */ +@Action(path = "/_dr/task/backfillAutorenewBillingFlag") +public class BackfillAutorenewBillingFlagAction implements MapreduceAction { + + private static final FormattingLogger logger = FormattingLogger.getLoggerForCallerClass(); + + @Inject MapreduceRunner mrRunner; + @Inject @Parameter(PARAM_DRY_RUN) boolean isDryRun; + @Inject Response response; + @Inject BackfillAutorenewBillingFlagAction() {} + + @Override + public void run() { + response.sendJavaScriptRedirect(createJobPath(mrRunner + .setJobName("Backfill AUTO_RENEW flag on Recurring billing events") + .setModuleName("tools") + .runMapOnly( + new BackfillAutorenewBillingFlagMapper(isDryRun), + ImmutableList.of(createRecurringInput())))); + } + + private Input createRecurringInput() { + return createChildEntityInput( + ImmutableSet.>of(DomainResource.class), + ImmutableSet.>of(Recurring.class)); + } + + /** Mapper to count BillingEvent.Recurring resources. */ + public static class BackfillAutorenewBillingFlagMapper extends Mapper { + + private static final long serialVersionUID = -6576637759905280988L; + + private final boolean isDryRun; + + public BackfillAutorenewBillingFlagMapper(boolean isDryRun) { + this.isDryRun = isDryRun; + } + + @Override + public final void map(final Recurring recurring) { + try { + // A note on how this works: Since OnLoad makes the backfill change for us, all we need to + // do is check that this condition exists on the loaded entity, and just re-save to persist + // the new data to datastore. + if (!isDryRun) { + ofy().transactNew(new VoidWork() { + @Override + public void vrun() { + ofy().save().entity(ofy().load().entity(recurring).now()); + } + }); + getContext().incrementCounter("Saved Recurring billing events"); + } + getContext().incrementCounter("Recurring billing events encountered"); + } catch (Throwable t) { + logger.severe(t, "Error while backfilling AUTO_RENEW flags."); + getContext().incrementCounter("error: " + t.getClass().getSimpleName()); + } + } + } +} diff --git a/java/google/registry/tools/server/javascrap/CountRecurringBillingEventsAction.java b/java/google/registry/tools/server/javascrap/CountRecurringBillingEventsAction.java new file mode 100644 index 000000000..e3290251d --- /dev/null +++ b/java/google/registry/tools/server/javascrap/CountRecurringBillingEventsAction.java @@ -0,0 +1,76 @@ +// Copyright 2016 The Domain Registry Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package google.registry.tools.server.javascrap; + +import static google.registry.mapreduce.inputs.EppResourceInputs.createChildEntityInput; +import static google.registry.util.PipelineUtils.createJobPath; + +import com.google.appengine.tools.mapreduce.Input; +import com.google.appengine.tools.mapreduce.Mapper; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; + +import google.registry.mapreduce.MapreduceAction; +import google.registry.mapreduce.MapreduceRunner; +import google.registry.model.EppResource; +import google.registry.model.billing.BillingEvent.Recurring; +import google.registry.request.Action; +import google.registry.request.Response; + +import javax.inject.Inject; + +/** + * A mapreduce that counts all BillingEvent.Recurring entities. + * + *

This is a test of the ChildEntityInput/ChildEntityReader classes. + */ +@Action(path = "/_dr/task/countRecurringBillingEvents") +public class CountRecurringBillingEventsAction implements MapreduceAction { + + // TODO(b/27562876): Delete this mapreduce once tested in production. + + @Inject MapreduceRunner mrRunner; + @Inject Response response; + @Inject CountRecurringBillingEventsAction() {} + + @Override + public void run() { + response.sendJavaScriptRedirect(createJobPath(mrRunner + .setJobName("Count recurring billing events") + .setModuleName("tools") + .runMapOnly( + new CountRecurringBillingEventsMapper(), + ImmutableList.of(createRecurringInput())))); + } + + private Input createRecurringInput() { + return createChildEntityInput( + ImmutableSet.>of(EppResource.class), + ImmutableSet.>of(Recurring.class)); + } + + /** Mapper to count BillingEvent.Recurring resources. */ + public static class CountRecurringBillingEventsMapper extends Mapper { + + private static final long serialVersionUID = -8547238315947793512L; + + public CountRecurringBillingEventsMapper() {} + + @Override + public final void map(final Recurring recurring) { + getContext().incrementCounter("recurring billing events"); + } + } +}