Skip to content

Commit 5b973db

Browse files
surkovaclaudembroshi-stripe
authored
Use autoload instead of eager require for generated resource, service, and param files (stripe#1855)
* Convert eager require to autoload for resources, services, and params Replace ~985 eager require calls with Ruby's autoload in the three generated barrel files (resources.rb, services.rb, params.rb). This defers loading of resource classes, service classes, and param classes until they are first referenced, rather than loading all of them on require 'stripe'. Add Stripe.eager_load! for production use — it walks the same file list in the same order as the old require calls, so there are no load-order surprises. A Railtie registers Stripe in config.eager_load_namespaces so Rails calls eager_load! automatically when config.eager_load is true (the production default). On Ruby 4.0.2 / Apple M1: - Boot time: 214ms -> 61ms (-71%) - Object allocations: 193k -> 35k (-82%) - Retained memory: 9.0 MB -> 1.4 MB (-85%) Ref stripe#1432 Co-authored-by: Claude <noreply@anthropic.com> * Fix lint and typecheck CI failures - Run rubocop autocorrect to fix line length, trailing whitespace, and argument alignment in autoload statements - Exclude lib/stripe/params.rb from CollectionLiteralLength (generated list, same as existing event_types.rb exclusion) - Add typed: ignore to railtie files since Rails isn't a Sorbet-visible dependency Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Committed-By-Agent: claude * Regenerate resources, services, and params from updated codegen Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Committed-By-Agent: claude * Remove redundant rubocop.yml exclusion for params.rb The codegen now emits an inline rubocop:disable comment around the PARAM_FILES array, making the .rubocop.yml file-level exclusion unnecessary. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Committed-By-Agent: claude --------- Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: Michael Broshi <mbroshi@stripe.com>
1 parent 0b1d66f commit 5b973db

7 files changed

Lines changed: 2381 additions & 985 deletions

File tree

lib/stripe.rb

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,11 +52,11 @@
5252
require "stripe/singleton_api_resource"
5353
require "stripe/webhook"
5454
require "stripe/stripe_configuration"
55-
require "stripe/resources/v2/amount"
56-
require "stripe/resources/v2/deleted_object"
57-
require "stripe/resources/v2/core/event_notification"
5855

59-
# Named API resources
56+
# Named API resources — autoloaded on first use to reduce boot time.
57+
# Call Stripe.eager_load! to load everything upfront (recommended
58+
# before forking in production). In Rails, this happens automatically
59+
# when config.eager_load is true.
6060
require "stripe/resources"
6161
require "stripe/services"
6262
require "stripe/params"
@@ -65,6 +65,10 @@
6565
require "stripe/oauth"
6666
require "stripe/services/oauth_service"
6767

68+
# Rails integration — registers Stripe in config.eager_load_namespaces
69+
# so Stripe.eager_load! is called automatically when config.eager_load is true.
70+
require "stripe/railtie" if defined?(Rails::Railtie)
71+
6872
module Stripe
6973
DEFAULT_CA_BUNDLE_PATH = __dir__ + "/data/ca-certificates.crt"
7074

@@ -136,6 +140,23 @@ class << self
136140
def_delegators :@config, :ca_store
137141
end
138142

143+
# Eagerly loads all autoloaded Stripe constants (resources, services,
144+
# params) using the same file list and load order as previous versions
145+
# of this gem that used eager require.
146+
#
147+
# Call this before forking in production (Puma, Unicorn, etc.) to
148+
# avoid autoload in multi-threaded request handling. In Rails apps
149+
# this is called automatically when config.eager_load is true.
150+
#
151+
# # Non-Rails production / pre-fork hook:
152+
# Stripe.eager_load!
153+
#
154+
def self.eager_load!
155+
(RESOURCE_FILES + SERVICE_FILES + PARAM_FILES).each do |path|
156+
require path
157+
end
158+
end
159+
139160
# Gets the application for a plugin that's identified some. See
140161
# #set_app_info.
141162
def self.app_info

lib/stripe/params.rb

Lines changed: 1331 additions & 614 deletions
Large diffs are not rendered by default.

lib/stripe/railtie.rb

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# typed: ignore
2+
# frozen_string_literal: true
3+
4+
module Stripe
5+
class Railtie < ::Rails::Railtie
6+
config.eager_load_namespaces << Stripe
7+
end
8+
end

lib/stripe/resources.rb

Lines changed: 475 additions & 178 deletions
Large diffs are not rendered by default.

lib/stripe/services.rb

Lines changed: 457 additions & 189 deletions
Large diffs are not rendered by default.

test/stripe/autoload_test.rb

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
# frozen_string_literal: true
2+
3+
require File.expand_path("../test_helper", __dir__)
4+
5+
module Stripe
6+
class AutoloadTest < Test::Unit::TestCase
7+
context "autoloaded constants" do
8+
should "resolve all v1 object type classes" do
9+
Stripe::ObjectTypes.object_names_to_classes.each do |name, klass|
10+
assert_kind_of Class, klass, "#{name} did not resolve to a class"
11+
end
12+
end
13+
14+
should "resolve all v2 object type classes" do
15+
Stripe::ObjectTypes.v2_object_names_to_classes.each do |name, klass|
16+
assert_kind_of Class, klass, "#{name} did not resolve to a class"
17+
end
18+
end
19+
20+
should "resolve all v2 event type classes" do
21+
Stripe::EventTypes.v2_event_types_to_classes.each do |type, klass|
22+
assert_kind_of Class, klass, "#{type} did not resolve to a class"
23+
end
24+
end
25+
26+
should "resolve all event notification type classes" do
27+
Stripe::EventTypes.event_notification_types_to_classes.each do |type, klass|
28+
assert_kind_of Class, klass, "#{type} did not resolve to a class"
29+
end
30+
end
31+
32+
should "define EventNotification constants from event files" do
33+
# Each event file defines both *Event and *EventNotification.
34+
# Verify the *EventNotification constants are accessible.
35+
assert_kind_of Class, Stripe::Events::V2CoreAccountClosedEventNotification
36+
assert_kind_of Class, Stripe::Events::V1BillingMeterErrorReportTriggeredEventNotification
37+
end
38+
end
39+
40+
context ".eager_load!" do
41+
should "load all registered files without error" do
42+
assert_nothing_raised { Stripe.eager_load! }
43+
end
44+
45+
should "make all resource constants available" do
46+
Stripe.eager_load!
47+
48+
# Spot-check a sample of resources across namespaces
49+
assert_equal "customer", Stripe::Customer::OBJECT_NAME
50+
assert_equal "billing.alert", Stripe::Billing::Alert::OBJECT_NAME
51+
assert_equal "checkout.session", Stripe::Checkout::Session::OBJECT_NAME
52+
assert_equal "issuing.card", Stripe::Issuing::Card::OBJECT_NAME
53+
assert_equal "treasury.financial_account", Stripe::Treasury::FinancialAccount::OBJECT_NAME
54+
end
55+
end
56+
end
57+
end

test/stripe/railtie_test.rb

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# typed: ignore
2+
# frozen_string_literal: true
3+
4+
require "test/unit"
5+
6+
begin
7+
require "rails"
8+
rescue LoadError
9+
# Rails is not a dependency of stripe-ruby; skip these tests when unavailable.
10+
end
11+
12+
if defined?(Rails::Railtie)
13+
require "stripe"
14+
15+
class RailtieTest < Test::Unit::TestCase
16+
test "Railtie is defined and is a Rails::Railtie" do
17+
assert_operator Stripe::Railtie, :<, ::Rails::Railtie
18+
end
19+
20+
test "Stripe is registered in eager_load_namespaces" do
21+
app = Class.new(Rails::Application) do
22+
config.eager_load = false
23+
config.active_support.to_time_preserves_timezone = :zone
24+
end
25+
assert_includes app.config.eager_load_namespaces, Stripe
26+
end
27+
end
28+
end

0 commit comments

Comments
 (0)