From 1888b2c9a1f54fc3e4e788b0c4cc9005d1cfed42 Mon Sep 17 00:00:00 2001 From: Ben McIlwain Date: Fri, 27 May 2022 11:46:36 -0400 Subject: [PATCH] Inject a DomainPricingLogic into ExpandRecurringBillingEventsAction (#1648) * Inject a DomainPricingLogic into ExpandRecurringBillingEventsAction This will be used in other PRs to set the renewal price correctly based on the renewal price behavior of the BillingRecurrence event. Note that, in order for this to work, a not-null constraint has been lifted on the EPP flow state when the DomainPricingCustomLogic is being constructed, as the pricing here will occur in a backend action outside the context of any EPP flow. --- .../ExpandRecurringBillingEventsAction.java | 3 ++ .../flows/custom/BaseFlowCustomLogic.java | 34 +++++++++++++------ .../flows/custom/CustomLogicFactory.java | 8 +++-- .../flows/custom/CustomLogicModule.java | 21 +++++++++--- .../custom/DomainPricingCustomLogic.java | 5 ++- .../flows/domain/DomainPricingLogic.java | 2 -- .../backend/BackendRequestComponent.java | 2 ++ .../module/tools/ToolsRequestComponent.java | 16 ++++----- .../flows/custom/TestCustomLogicFactory.java | 8 +++-- .../TestDomainCreateFlowCustomLogic.java | 2 +- 10 files changed, 71 insertions(+), 30 deletions(-) diff --git a/core/src/main/java/google/registry/batch/ExpandRecurringBillingEventsAction.java b/core/src/main/java/google/registry/batch/ExpandRecurringBillingEventsAction.java index 27efd9a0b..042b89cf4 100644 --- a/core/src/main/java/google/registry/batch/ExpandRecurringBillingEventsAction.java +++ b/core/src/main/java/google/registry/batch/ExpandRecurringBillingEventsAction.java @@ -44,6 +44,7 @@ import com.google.common.collect.Range; import com.google.common.collect.Streams; import com.google.common.flogger.FluentLogger; import google.registry.config.RegistryConfig.Config; +import google.registry.flows.domain.DomainPricingLogic; import google.registry.mapreduce.MapreduceRunner; import google.registry.mapreduce.inputs.NullInput; import google.registry.model.ImmutableObject; @@ -98,6 +99,8 @@ public class ExpandRecurringBillingEventsAction implements Runnable { @Inject @Parameter(PARAM_DRY_RUN) boolean isDryRun; @Inject @Parameter(PARAM_CURSOR_TIME) Optional cursorTimeParam; + + @Inject DomainPricingLogic domainPricingLogic; @Inject Response response; @Inject ExpandRecurringBillingEventsAction() {} diff --git a/core/src/main/java/google/registry/flows/custom/BaseFlowCustomLogic.java b/core/src/main/java/google/registry/flows/custom/BaseFlowCustomLogic.java index 6d8d34b4a..8c828693e 100644 --- a/core/src/main/java/google/registry/flows/custom/BaseFlowCustomLogic.java +++ b/core/src/main/java/google/registry/flows/custom/BaseFlowCustomLogic.java @@ -17,6 +17,8 @@ package google.registry.flows.custom; import google.registry.flows.FlowMetadata; import google.registry.flows.SessionMetadata; import google.registry.model.eppinput.EppInput; +import java.util.Optional; +import javax.annotation.Nullable; /** * An abstract base class for all flow custom logic that stores the flow's {@link EppInput} and @@ -24,26 +26,38 @@ import google.registry.model.eppinput.EppInput; */ public abstract class BaseFlowCustomLogic { - private final EppInput eppInput; - private final SessionMetadata sessionMetadata; - private final FlowMetadata flowMetadata; + @Nullable private final EppInput eppInput; + @Nullable private final SessionMetadata sessionMetadata; + @Nullable private final FlowMetadata flowMetadata; + /** + * Constructs a BaseFlowCustomLogic for the specified EPP flow state. + * + *

Note that it is possible for the EPP flow state to be absent, which happens when the custom + * logic is running outside the context of an EPP flow (e.g. {@link DomainPricingCustomLogic} in + * backend actions). + */ protected BaseFlowCustomLogic( - EppInput eppInput, SessionMetadata sessionMetadata, FlowMetadata flowMetadata) { + @Nullable EppInput eppInput, + @Nullable SessionMetadata sessionMetadata, + @Nullable FlowMetadata flowMetadata) { this.eppInput = eppInput; this.sessionMetadata = sessionMetadata; this.flowMetadata = flowMetadata; } - protected EppInput getEppInput() { - return eppInput; + /** Returns the {@link EppInput}, which may be empty outside a flow context. */ + protected Optional getEppInput() { + return Optional.ofNullable(eppInput); } - protected SessionMetadata getSessionMetadata() { - return sessionMetadata; + /** Returns the {@link SessionMetadata}, which may be empty outside a flow context. */ + protected Optional getSessionMetadata() { + return Optional.ofNullable(sessionMetadata); } - protected FlowMetadata getFlowMetadata() { - return flowMetadata; + /** Returns the {@link FlowMetadata}, which may be empty outside a flow context. */ + protected Optional getFlowMetadata() { + return Optional.ofNullable(flowMetadata); } } diff --git a/core/src/main/java/google/registry/flows/custom/CustomLogicFactory.java b/core/src/main/java/google/registry/flows/custom/CustomLogicFactory.java index 8bae8b0d1..270cdd810 100644 --- a/core/src/main/java/google/registry/flows/custom/CustomLogicFactory.java +++ b/core/src/main/java/google/registry/flows/custom/CustomLogicFactory.java @@ -18,6 +18,7 @@ import google.registry.config.RegistryConfig.ConfigModule; import google.registry.flows.FlowMetadata; import google.registry.flows.SessionMetadata; import google.registry.model.eppinput.EppInput; +import java.util.Optional; /** * A no-op base custom logic factory. @@ -63,7 +64,10 @@ public class CustomLogicFactory { } public DomainPricingCustomLogic forDomainPricing( - EppInput eppInput, SessionMetadata sessionMetadata, FlowMetadata flowMetadata) { - return new DomainPricingCustomLogic(eppInput, sessionMetadata, flowMetadata); + Optional eppInput, + Optional sessionMetadata, + Optional flowMetadata) { + return new DomainPricingCustomLogic( + eppInput.orElse(null), sessionMetadata.orElse(null), flowMetadata.orElse(null)); } } diff --git a/core/src/main/java/google/registry/flows/custom/CustomLogicModule.java b/core/src/main/java/google/registry/flows/custom/CustomLogicModule.java index 001ab8c8e..e9c294670 100644 --- a/core/src/main/java/google/registry/flows/custom/CustomLogicModule.java +++ b/core/src/main/java/google/registry/flows/custom/CustomLogicModule.java @@ -14,15 +14,17 @@ package google.registry.flows.custom; +import dagger.BindsOptionalOf; import dagger.Module; import dagger.Provides; import google.registry.flows.FlowMetadata; import google.registry.flows.SessionMetadata; import google.registry.model.eppinput.EppInput; +import java.util.Optional; /** Dagger module to provide instances of custom logic classes for EPP flows. */ @Module -public class CustomLogicModule { +public abstract class CustomLogicModule { @Provides static DomainCreateFlowCustomLogic provideDomainCreateFlowCustomLogic( @@ -81,9 +83,20 @@ public class CustomLogicModule { @Provides static DomainPricingCustomLogic provideDomainPricingCustomLogic( CustomLogicFactory factory, - EppInput eppInput, - SessionMetadata sessionMetadata, - FlowMetadata flowMetadata) { + Optional eppInput, + Optional sessionMetadata, + Optional flowMetadata) { + // Note that, for DomainPricingCustomLogic, the EPP flow state won't be present outside the + // context of an EPP flow. return factory.forDomainPricing(eppInput, sessionMetadata, flowMetadata); } + + @BindsOptionalOf + abstract EppInput optionalEppInput(); + + @BindsOptionalOf + abstract SessionMetadata optionalSessionMetadata(); + + @BindsOptionalOf + abstract FlowMetadata optionalFlowMetadata(); } diff --git a/core/src/main/java/google/registry/flows/custom/DomainPricingCustomLogic.java b/core/src/main/java/google/registry/flows/custom/DomainPricingCustomLogic.java index ef8e786af..c80bf1b1f 100644 --- a/core/src/main/java/google/registry/flows/custom/DomainPricingCustomLogic.java +++ b/core/src/main/java/google/registry/flows/custom/DomainPricingCustomLogic.java @@ -24,6 +24,7 @@ import google.registry.flows.domain.FeesAndCredits; import google.registry.model.ImmutableObject; import google.registry.model.eppinput.EppInput; import google.registry.model.tld.Registry; +import javax.annotation.Nullable; import org.joda.time.DateTime; /** @@ -34,7 +35,9 @@ import org.joda.time.DateTime; public class DomainPricingCustomLogic extends BaseFlowCustomLogic { public DomainPricingCustomLogic( - EppInput eppInput, SessionMetadata sessionMetadata, FlowMetadata flowMetadata) { + @Nullable EppInput eppInput, + @Nullable SessionMetadata sessionMetadata, + @Nullable FlowMetadata flowMetadata) { super(eppInput, sessionMetadata, flowMetadata); } diff --git a/core/src/main/java/google/registry/flows/domain/DomainPricingLogic.java b/core/src/main/java/google/registry/flows/domain/DomainPricingLogic.java index 3867c2a5e..a953aacce 100644 --- a/core/src/main/java/google/registry/flows/domain/DomainPricingLogic.java +++ b/core/src/main/java/google/registry/flows/domain/DomainPricingLogic.java @@ -23,7 +23,6 @@ import static google.registry.util.PreconditionsUtils.checkArgumentPresent; import com.google.common.net.InternetDomainName; import google.registry.flows.EppException; import google.registry.flows.EppException.CommandUseErrorException; -import google.registry.flows.FlowScope; import google.registry.flows.custom.DomainPricingCustomLogic; import google.registry.flows.custom.DomainPricingCustomLogic.CreatePriceParameters; import google.registry.flows.custom.DomainPricingCustomLogic.RenewPriceParameters; @@ -50,7 +49,6 @@ import org.joda.time.DateTime; * providing a {@link DomainPricingCustomLogic} implementation that operates on cross-TLD or per-TLD * logic. */ -@FlowScope public final class DomainPricingLogic { @Inject DomainPricingCustomLogic customLogic; diff --git a/core/src/main/java/google/registry/module/backend/BackendRequestComponent.java b/core/src/main/java/google/registry/module/backend/BackendRequestComponent.java index ce9822a1c..fb06d0360 100644 --- a/core/src/main/java/google/registry/module/backend/BackendRequestComponent.java +++ b/core/src/main/java/google/registry/module/backend/BackendRequestComponent.java @@ -61,6 +61,7 @@ import google.registry.export.UploadDatastoreBackupAction; import google.registry.export.sheet.SheetModule; import google.registry.export.sheet.SyncRegistrarsSheetAction; import google.registry.flows.FlowComponent; +import google.registry.flows.custom.CustomLogicModule; import google.registry.mapreduce.MapreduceModule; import google.registry.model.replay.ReplicateToDatastoreAction; import google.registry.monitoring.whitebox.WhiteboxModule; @@ -103,6 +104,7 @@ import google.registry.tools.javascrap.CreateSyntheticHistoryEntriesAction; BillingModule.class, CloudDnsWriterModule.class, CronModule.class, + CustomLogicModule.class, DnsCountQueryCoordinatorModule.class, DnsModule.class, DnsUpdateConfigModule.class, diff --git a/core/src/main/java/google/registry/module/tools/ToolsRequestComponent.java b/core/src/main/java/google/registry/module/tools/ToolsRequestComponent.java index e7e677ce2..26655ccfe 100644 --- a/core/src/main/java/google/registry/module/tools/ToolsRequestComponent.java +++ b/core/src/main/java/google/registry/module/tools/ToolsRequestComponent.java @@ -48,14 +48,14 @@ import google.registry.tools.server.VerifyOteAction; @RequestScope @Subcomponent( modules = { - BackupModule.class, - DnsModule.class, - EppToolModule.class, - LoadTestModule.class, - MapreduceModule.class, - RequestModule.class, - ToolsServerModule.class, - WhiteboxModule.class, + BackupModule.class, + DnsModule.class, + EppToolModule.class, + LoadTestModule.class, + MapreduceModule.class, + RequestModule.class, + ToolsServerModule.class, + WhiteboxModule.class, }) interface ToolsRequestComponent { CreateGroupsAction createGroupsAction(); diff --git a/core/src/test/java/google/registry/flows/custom/TestCustomLogicFactory.java b/core/src/test/java/google/registry/flows/custom/TestCustomLogicFactory.java index d741db300..6b1fb96ce 100644 --- a/core/src/test/java/google/registry/flows/custom/TestCustomLogicFactory.java +++ b/core/src/test/java/google/registry/flows/custom/TestCustomLogicFactory.java @@ -17,6 +17,7 @@ package google.registry.flows.custom; import google.registry.flows.FlowMetadata; import google.registry.flows.SessionMetadata; import google.registry.model.eppinput.EppInput; +import java.util.Optional; /** A custom logic factory for testing. */ public class TestCustomLogicFactory extends CustomLogicFactory { @@ -29,7 +30,10 @@ public class TestCustomLogicFactory extends CustomLogicFactory { @Override public DomainPricingCustomLogic forDomainPricing( - EppInput eppInput, SessionMetadata sessionMetadata, FlowMetadata flowMetadata) { - return new TestDomainPricingCustomLogic(eppInput, sessionMetadata, flowMetadata); + Optional eppInput, + Optional sessionMetadata, + Optional flowMetadata) { + return new TestDomainPricingCustomLogic( + eppInput.orElse(null), sessionMetadata.orElse(null), flowMetadata.orElse(null)); } } diff --git a/core/src/test/java/google/registry/flows/custom/TestDomainCreateFlowCustomLogic.java b/core/src/test/java/google/registry/flows/custom/TestDomainCreateFlowCustomLogic.java index e79fa0c58..b5b8ba07d 100644 --- a/core/src/test/java/google/registry/flows/custom/TestDomainCreateFlowCustomLogic.java +++ b/core/src/test/java/google/registry/flows/custom/TestDomainCreateFlowCustomLogic.java @@ -36,7 +36,7 @@ public class TestDomainCreateFlowCustomLogic extends DomainCreateFlowCustomLogic new PollMessage.OneTime.Builder() .setParent(parameters.historyEntry()) .setEventTime(tm().getTransactionTime()) - .setRegistrarId(getSessionMetadata().getRegistrarId()) + .setRegistrarId(getSessionMetadata().get().getRegistrarId()) .setMsg("Custom logic was triggered") .build(); return EntityChanges.newBuilder()