chore(perf): Dedupe charge filter preload#5945
Open
jdenquin wants to merge 1 commit into
Open
Conversation
Contributor
Author
|
with #5882, we can again win around 50ms per subscription during a customer usage computation. |
This file contains hidden or 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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Context
When computing customer usage, the plan's charges and their filter tree (
charge_filters+charge_filter_valueswith their largepropertiesjsonb) areloaded from PostgreSQL twice per computation:
Invoices::CustomerUsageService#chargespreloads them for the fee loopEvents::BillingPeriodFilterService#non_recurring_charges_with_eventsre-loads the exact same associations for the same planOn large plans (~1,600 charge filters) each load costs seconds, and
RefreshWalletsServicepays this per subscription.Description
Load the charge/filter set once and share it:
Events::BillingPeriodFilterServiceaccepts an optionalcharges:argument (pre-loaded charges withbillable_metricandfilters: {values: :billable_metric_filter}). When provided,non_recurring_charges_with_events,recurring_event_charges_and_filtersandcurrent_recurring_chargesareresolved in memory instead of re-querying. Without it, behavior is unchanged, so
CalculateFeesServiceandProgressiveBillingServiceare unaffected.Invoices::CustomerUsageServicepasses its memoized charges relation to the service; since it is the same object, the fee loop then reuses the loadedrecords.
find_eachis replaced byeachin the fee loop:find_eachalways re-queries in batches, which would have triggered the preload a second time.billable_metric: :filters, required byChargeFilters::EventMatchingServiceto stay query-free on pre-loaded charges.