DEV: Add pagination to plans request

When pulling up a users subscriptions a 500 might occur if we don't find
their plan. If your account happens to have over 100 plans this can be
the cause of the 500 error. This change adds pagination when fetching
plans form stripe, so that we fetch them all.

https://meta.discourse.org/t/problem-with-500-error-with-subscriptions/360808?u=blake
This commit is contained in:
Blake Erickson 2025-04-09 15:53:22 -06:00
parent b0af86f12b
commit d97988ae29
2 changed files with 53 additions and 2 deletions

View File

@ -24,7 +24,14 @@ module DiscourseSubscriptions
subscriptions = []
if subscription_ids
plans = ::Stripe::Price.list(expand: ["data.product"], limit: 100)
prices = []
price_params = { limit: 100, expand: ["data.product"] }
loop do
response = ::Stripe::Price.list(price_params)
prices.concat(response[:data])
break unless response[:has_more]
price_params[:starting_after] = response[:data].last.id
end
all_subscriptions = []
stripe_customer_ids.each do |stripe_customer_id|
@ -35,7 +42,7 @@ module DiscourseSubscriptions
subscriptions = all_subscriptions.select { |sub| subscription_ids.include?(sub[:id]) }
subscriptions.map! do |subscription|
plan = plans[:data].find { |p| p[:id] == subscription[:items][:data][0][:price][:id] }
plan = prices.find { |p| p[:id] == subscription[:items][:data][0][:price][:id] }
subscription.to_h.except!(:plan)
subscription.to_h.merge(plan: plan, product: plan[:product].to_h.slice(:id, :name))
end

View File

@ -5,6 +5,14 @@ require "rails_helper"
RSpec.describe DiscourseSubscriptions::User::SubscriptionsController do
before { SiteSetting.discourse_subscriptions_enabled = true }
def create_price(id, product)
price = { id: id, product: product }
def price.id
self[:id]
end
price
end
it "is a subclass of ApplicationController" do
expect(DiscourseSubscriptions::User::SubscriptionsController < ::ApplicationController).to eq(
true,
@ -80,6 +88,42 @@ RSpec.describe DiscourseSubscriptions::User::SubscriptionsController do
expect(subscription[:items][:data][0][:plan][:id]).to eq("price_1OrmlvEYXaQnncShNahrpKvA")
expect(subscription[:product][:name]).to eq("Exclusive Access")
end
it "aggregates prices from multiple pages using pagination logic" do
subscription_data = { id: "sub_10z", items: { data: [{ price: { id: "price_200" } }] } }
::Stripe::Subscription
.stubs(:list)
.with(customer: "cus_23456", status: "all")
.returns({ data: [subscription_data] })
# Build the first page of 100 prices that do NOT include the desired price.
prices_page_1 =
(1..100).map do |i|
create_price("price_#{i}", { id: "prod_dummy", name: "Dummy Product #{i}" })
end
# Second page containing the desired price.
prices_page_2 = [create_price("price_200", { id: "prod_200", name: "Matching Product" })]
::Stripe::Price
.expects(:list)
.with(has_entries(limit: 100, expand: ["data.product"]))
.returns({ data: prices_page_1, has_more: true })
::Stripe::Price
.expects(:list)
.with(has_entries(limit: 100, expand: ["data.product"], starting_after: "price_100"))
.returns({ data: prices_page_2, has_more: false })
get "/s/user/subscriptions.json"
result = JSON.parse(response.body, symbolize_names: true)
subscription = result.first
expect(subscription[:id]).to eq("sub_10z")
expect(subscription[:plan][:id]).to eq("price_200")
expect(subscription[:product][:id]).to eq("prod_200")
expect(subscription[:product][:name]).to eq("Matching Product")
end
end
describe "update" do