panda_pal 5.17.1 → 5.17.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2f32b5b78d11428c9f4be64fc963ae2fac80cae44abfd66dcda0f39be8b17006
4
- data.tar.gz: cb494809a3aa72956b16bad0b7b17ba095156a1c4a7fa7261a51738d92442630
3
+ metadata.gz: 1d2cfdbfc9d2c60cc080b545d2ee582ce212623a45c286d8610b8ac5f6c1af37
4
+ data.tar.gz: 4918d3bee6808bfbf22e98e23f3cbedcd493d4ec7c946ac67e0c8ca5485d9eca
5
5
  SHA512:
6
- metadata.gz: 7819962aa331b91ae3b6ad0d95fdb8e5bf314d691cdaa4f120a1f12b199d26c916a811b9f071b9fd73802c8893ae70b6a6158a7ea9457b602f1ea2aa496d4092
7
- data.tar.gz: 5cfd2d2f902e658968b3ce2ce2495c5a58e605071db2c97436186b2893f178d2c198856ac42acd9371f6462d108a2a959834958b84ad1fa9d4f9c0740686cc93
6
+ metadata.gz: 0e06e419047c6a29e1ed8f03966bae4c31ed9e5b57ad6953133b890f6dab407d384ea1f071e0c88e01f7a69ef790f9b132f98a973aa3602b6b902d4871722799
7
+ data.tar.gz: 6d19e0a9ea13914f8045d62525dd73dcb97aadfc780dc1c4907fe3b80df9483144d1cc3cc087d509aa7cfba344aa64aaa4b7bd36b05fea354201d7e387094db4
@@ -148,10 +148,7 @@ module Apartment
148
148
 
149
149
  raise ActiveRecord::StatementInvalid, "PandaPal/Apartment Mutli-DB support does not currently support DB roles" if ActiveRecord::Base.current_role != ActiveRecord::Base.default_role
150
150
 
151
- unless ActiveRecord::Base.connected?
152
- Apartment.establish_connection multi_tenantify(tenant, false)
153
- Apartment.connection.verify!
154
- end
151
+ establish_connection_pool(tenant) unless connection_pool_registered?
155
152
 
156
153
  Apartment.connection.enable_query_cache! if query_cache_enabled
157
154
 
@@ -171,6 +168,25 @@ module Apartment
171
168
 
172
169
  protected
173
170
 
171
+ ESTABLISH_CONNECTION_LOCK = Mutex.new
172
+
173
+ def connection_pool_registered?
174
+ !ActiveRecord::Base.connection_handler.retrieve_connection_pool(
175
+ ActiveRecord::Base.connection_specification_name,
176
+ role: ActiveRecord::Base.current_role,
177
+ shard: ActiveRecord::Base.current_shard,
178
+ ).nil?
179
+ end
180
+
181
+ def establish_connection_pool(tenant)
182
+ ESTABLISH_CONNECTION_LOCK.synchronize do
183
+ next if connection_pool_registered?
184
+
185
+ Apartment.establish_connection multi_tenantify(tenant, false)
186
+ Apartment.connection.verify!
187
+ end
188
+ end
189
+
174
190
  def persistent_schemas
175
191
  map_to_schemas(super)
176
192
  end
@@ -1,3 +1,3 @@
1
1
  module PandaPal
2
- VERSION = '5.17.1'
2
+ VERSION = '5.17.2'
3
3
  end
@@ -53,6 +53,72 @@ RSpec.describe PandaPal::Organization, type: :model do
53
53
  expect(PandaPal::ApiCall.connection.exec_query("SELECT current_database()").pluck("current_database")[0]).to eq("panda_pal_test2")
54
54
  end
55
55
 
56
+ context "connection pool lifecycle" do
57
+ def alt_pool
58
+ ActiveRecord::Base.connection_handler.retrieve_connection_pool(
59
+ ActiveRecord::Base.connection_specification_name,
60
+ role: ActiveRecord::Base.current_role,
61
+ shard: "apt:alt",
62
+ )
63
+ end
64
+
65
+ def count_establish_connection_calls
66
+ calls = Queue.new
67
+ allow(Apartment).to receive(:establish_connection).and_wrap_original do |original, *args, **kwargs|
68
+ calls << true
69
+ original.call(*args, **kwargs)
70
+ end
71
+ yield
72
+ calls.size
73
+ end
74
+
75
+ def switch_in_threads(tenant, count)
76
+ start = Queue.new
77
+ threads = count.times.map do
78
+ Thread.new do
79
+ start.pop
80
+ Apartment::Tenant.switch(tenant) { PandaPal::ApiCall.count }
81
+ ensure
82
+ ActiveRecord::Base.connection_handler.clear_active_connections!
83
+ end
84
+ end
85
+ count.times { start << true }
86
+ threads.map(&:value)
87
+ end
88
+
89
+ it "reuses an existing shard pool whose connections have all been closed" do
90
+ org2.switch_tenant { PandaPal::ApiCall.count }
91
+ pool = alt_pool
92
+ ActiveRecord::Base.connection_handler.clear_active_connections!
93
+ pool.disconnect!
94
+
95
+ calls = count_establish_connection_calls do
96
+ org2.switch_tenant { expect(PandaPal::ApiCall.count).to eq(0) }
97
+ end
98
+
99
+ expect(calls).to eq(0)
100
+ expect(alt_pool).to equal(pool)
101
+ end
102
+
103
+ it "establishes a missing shard pool once when many threads need it at the same time" do
104
+ org2.switch_tenant { PandaPal::ApiCall.count }
105
+ ActiveRecord::Base.connection_handler.clear_active_connections!
106
+ ActiveRecord::Base.connection_handler.remove_connection_pool(
107
+ ActiveRecord::Base.connection_specification_name,
108
+ role: ActiveRecord::Base.current_role,
109
+ shard: "apt:alt",
110
+ )
111
+
112
+ results = nil
113
+ calls = count_establish_connection_calls do
114
+ results = switch_in_threads("alt:on_alt", 8)
115
+ end
116
+
117
+ expect(results).to eq([0] * 8)
118
+ expect(calls).to eq(1)
119
+ end
120
+ end
121
+
56
122
  # load_async is a Rails 7.0+ feature.
57
123
  context "load_async", skip: (ActiveRecord::Relation.method_defined?(:load_async) ? false : "requires Rails 7.0+ load_async") do
58
124
  it "works across shards" do
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: panda_pal
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.17.1
4
+ version: 5.17.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Instructure CustomDev