-
Notifications
You must be signed in to change notification settings - Fork 274
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add a beam pipeline to expand recurring billing event (#1881)
This will replace the ExpandRecurringBillingEventsAction, which has a couple of issues: 1) The action starts with too many Recurrings that are later filtered out because their expanded OneTimes are not actually in scope. This is due to the Recurrings not recording its latest expanded event time, and therefore many Recurrings that are not yet due for renewal get included in the initial query. 2) The action works in sequence, which exacerbated the issue in 1) and makes it very slow to run if the window of operation is wider than one day, which in turn makes it impossible to run any catch-up expansions with any significant gap to fill. 3) The action only expands the recurrence when the billing times because due, but most of its logic works on event time, which is 45 days before billing time, making the code hard to reason about and error-prone. This has led to b/258822640 where a premature optimization intended to fix 1) caused some autorenwals to not be expanded correctly when subsequent manual renews within the autorenew grace period closed the original recurrece. As a result, the new pipeline addresses the above issues in the following way: 1) Update the recurrenceLastExpansion field on the Recurring when a new expansion occurs, and narrow down the Recurrings in scope for expansion by only looking for the ones that have not been expanded for more than a year. 2) Make it a Beam pipeline so expansions can happen in parallel. The Recurrings are grouped into batches in order to not overwhelm the database with writes for each expansion. 3) Create new expansions when the event time, as opposed to billing time, is within the operation window. This streamlines the logic and makes it clearer and easier to reason about. This also aligns with how other (cancelllable) operations for which there are accompanying grace periods are handled, when the corresponding data is always speculatively created at event time. Lastly, doing this negates the need to check if the expansion has finished running before generating the monthly invoices, because the billing events are now created not just-in-time, but 45 days in advance. Note that this PR only adds the pipeline. It does not switch the default behavior to using the pipeline, which is still done by ExpandRecurringBillingEventsAction. We will first use this pipeline to generate missing billing events and domain histories caused by b/258822640. This also allows us to test it in production, as it backfills data that will not affect ongoing invoice generation. If anything goes wrong, we can always delete the generated billing events and domain histories, based on the unique "reason" in them. This pipeline can only run after we switch to use SQL sequence based ID allocation, introduced in #1831.
- Loading branch information
Showing
29 changed files
with
1,194 additions
and
27 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
460 changes: 460 additions & 0 deletions
460
core/src/main/java/google/registry/beam/billing/ExpandRecurringBillingEventsPipeline.java
Large diffs are not rendered by default.
Oops, something went wrong.
49 changes: 49 additions & 0 deletions
49
...c/main/java/google/registry/beam/billing/ExpandRecurringBillingEventsPipelineOptions.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
// Copyright 2022 The Nomulus 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.beam.billing; | ||
|
||
import google.registry.beam.common.RegistryPipelineOptions; | ||
import org.apache.beam.sdk.options.Default; | ||
import org.apache.beam.sdk.options.Description; | ||
|
||
public interface ExpandRecurringBillingEventsPipelineOptions extends RegistryPipelineOptions { | ||
@Description( | ||
"The inclusive lower bound of on the range of event times that will be expanded, in ISO 8601" | ||
+ " format") | ||
String getStartTime(); | ||
|
||
void setStartTime(String startTime); | ||
|
||
@Description( | ||
"The exclusive upper bound of on the range of event times that will be expanded, in ISO 8601" | ||
+ " format") | ||
String getEndTime(); | ||
|
||
void setEndTime(String endTime); | ||
|
||
@Description("If true, the expanded billing events and history entries will not be saved.") | ||
@Default.Boolean(false) | ||
boolean getIsDryRun(); | ||
|
||
void setIsDryRun(boolean isDryRun); | ||
|
||
@Description( | ||
"If true, set the RECURRING_BILLING global cursor to endTime after saving all expanded" | ||
+ " billing events and history entries.") | ||
@Default.Boolean(true) | ||
boolean getAdvanceCursor(); | ||
|
||
void setAdvanceCursor(boolean advanceCursor); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
51 changes: 51 additions & 0 deletions
51
...ain/resources/google/registry/beam/expand_recurring_billing_events_pipeline_metadata.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
{ | ||
"name": "Expand Recurring Billings Events for Implicit Auto-Renewals", | ||
"description": "An Apache Beam batch pipeline that finds all auto-renewals that have implicitly occurred between the given window and creates the corresponding billing events and hisotry entries.", | ||
"parameters": [ | ||
{ | ||
"name": "registryEnvironment", | ||
"label": "The Registry environment.", | ||
"helpText": "The Registry environment.", | ||
"is_optional": false, | ||
"regexes": [ | ||
"^PRODUCTION|SANDBOX|CRASH|QA|ALPHA$" | ||
] | ||
}, | ||
{ | ||
"name": "startTime", | ||
"label": "The inclusive lower bound of the operation window.", | ||
"helpText": "The inclusive lower bound of the operation window, in ISO 8601 format.", | ||
"is_optional": false | ||
}, | ||
{ | ||
"name": "endTime", | ||
"label": "The exclusive upper bound of the operation window.", | ||
"helpText": "The exclusive upper bound of the operation window, in ISO 8601 format.", | ||
"is_optional": false | ||
}, | ||
{ | ||
"name": "shard", | ||
"label": "The exclusive upper bound of the operation window.", | ||
"helpText": "The exclusive upper bound of the operation window, in ISO 8601 format.", | ||
"is_optional": true | ||
}, | ||
{ | ||
"name": "isDryRun", | ||
"label": "Whether this job is a dry run.", | ||
"helpText": "If true, no changes will be saved to the database.", | ||
"is_optional": true, | ||
"regexes": [ | ||
"^true|false$" | ||
] | ||
}, | ||
{ | ||
"name": "advanceCursor", | ||
"label": "Whether the BILLING_TIME global cursor should be advanced.", | ||
"helpText": "If true, after all expansions are persisted, the cursor will be changed from startTime to endTime.", | ||
"is_optional": true, | ||
"regexes": [ | ||
"^true|false$" | ||
] | ||
} | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.