panda_pal 5.16.1 → 5.16.3
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 +4 -4
- data/config/initializers/apartment.rb +52 -30
- data/lib/panda_pal/version.rb +1 -1
- data/spec/core/apartment_multidb_spec.rb +22 -0
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a2c0409f3edd41806fcd606b52eb0c6441c43dac7b9e1eeb89c1871b6e08525f
|
4
|
+
data.tar.gz: 14b3313348391ab1c364ee9bb404af319bf93b831fc5bd552059faf41a179b71
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e2c460dd7ac5ff05da55ef6db233f0d266983927e6a295b469d1d19002ea833b26479c5b7db53fb6306761afc683bf3494fc07c63f1ac401f736d73ad803248b
|
7
|
+
data.tar.gz: bcccc2e5ad50d546f3258e513118e97a37f8104901436b3b3920d64986ad83159034a905cce7ded7b81529989d16d8151f0583ec7b273732e2d38be443a6dc8e
|
@@ -250,49 +250,71 @@ module PandaPal::Plugins::ApartmentCache
|
|
250
250
|
end
|
251
251
|
ActiveSupport::Cache::Store.send(:prepend, PandaPal::Plugins::ApartmentCache)
|
252
252
|
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
253
|
+
ActiveSupport.on_load(:action_cable) do
|
254
|
+
ActionCable::Connection::Base.module_eval do
|
255
|
+
def tenant=(name)
|
256
|
+
@tenant = name
|
257
|
+
end
|
258
|
+
|
259
|
+
def tenant
|
260
|
+
@tenant || 'public'
|
261
|
+
end
|
262
|
+
end
|
262
263
|
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
264
|
+
# Include the Current Tenant in any broadcastings
|
265
|
+
if Rails.version >= '6.0'
|
266
|
+
ActionCable::Channel::Base.define_singleton_method(:broadcasting_for) do |*args|
|
267
|
+
cconn = ActionCable.server.worker_pool.connection
|
268
|
+
items = [cconn&.tenant || Apartment::Tenant.current, channel_name, *args]
|
269
|
+
serialize_broadcasting(items)
|
270
|
+
end
|
271
|
+
else
|
272
|
+
module ActionCable
|
273
|
+
module Channel
|
274
|
+
class Base
|
275
|
+
def broadcasting_for(model)
|
276
|
+
super([ Apartment::Tenant.current, model ])
|
271
277
|
end
|
272
278
|
end
|
273
279
|
end
|
274
280
|
end
|
275
281
|
end
|
276
282
|
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
283
|
+
# Lazily switch any worker threads to the correct tenant when they are working
|
284
|
+
# Actively calling `switch_tenant` for checks out a DB connection and calls `SET search_path`.
|
285
|
+
# The message processing may not interface with the DB, so this would be a huge waste.
|
286
|
+
# Instead, we ensure that the thread will trigger a :checkout if it needs a connection,
|
287
|
+
# at which time we hack-in the correct tenant/schema.
|
288
|
+
|
289
|
+
ActionCable::Server::Worker.set_callback :work, :around do |_, blk|
|
290
|
+
# Bit of a hack, but ensures the adapter is initialized (since such may incur DB calls (requiring a connection)
|
291
|
+
# which would then cause `checkout` to recurse)
|
292
|
+
Apartment::Tenant.adapter
|
293
|
+
|
294
|
+
# If the current thread already has a connection checked out, release it back to the pool so that the later after_checkout
|
295
|
+
# callback can set the schema properly.
|
296
|
+
pool = Apartment.connection_class.connection_pool
|
297
|
+
pool.release_connection if pool.active_connection?
|
298
|
+
|
299
|
+
Thread.current[:cable_tenant] = connection.tenant
|
300
|
+
blk.call
|
301
|
+
ensure
|
302
|
+
Thread.current[:cable_tenant] = nil
|
303
|
+
end
|
282
304
|
|
283
|
-
|
284
|
-
|
285
|
-
|
305
|
+
ActiveSupport.on_load(:active_record) do
|
306
|
+
if Apartment::Tenant.adapter.is_a?(Apartment::Adapters::PostgresqlSchemaAdapter)
|
307
|
+
ActiveRecord::Base.connection.class.set_callback :checkout, :after do |conn|
|
308
|
+
next unless conn.pool == Apartment.connection_class.connection_pool
|
286
309
|
|
287
|
-
|
288
|
-
|
289
|
-
|
310
|
+
if (ct = Thread.current[:cable_tenant]).present?
|
311
|
+
adapter = Apartment::Tenant.adapter
|
312
|
+
adapter.instance_variable_set(:@current, ct)
|
313
|
+
conn.schema_search_path = adapter.send :full_search_path
|
290
314
|
end
|
291
315
|
end
|
292
316
|
end
|
293
317
|
end
|
294
|
-
|
295
|
-
ActionCable::Connection::Base.prepend(PandaPal::Plugins::ActionCableApartment::Connection)
|
296
318
|
end
|
297
319
|
|
298
320
|
if defined?(Delayed)
|
data/lib/panda_pal/version.rb
CHANGED
@@ -31,6 +31,28 @@ RSpec.describe PandaPal::Organization, type: :model do
|
|
31
31
|
end
|
32
32
|
end
|
33
33
|
|
34
|
+
it "creates records on the target shard and schema" do
|
35
|
+
org1.switch_tenant
|
36
|
+
PandaPal::ApiCall.create!(logic: "from_primary")
|
37
|
+
expect(PandaPal::ApiCall.count).to eq(1)
|
38
|
+
expect(PandaPal::ApiCall.first.logic).to eq("from_primary")
|
39
|
+
|
40
|
+
org2.switch_tenant
|
41
|
+
PandaPal::ApiCall.create!(logic: "from_alt")
|
42
|
+
expect(PandaPal::ApiCall.count).to eq(1)
|
43
|
+
expect(PandaPal::ApiCall.first.logic).to eq("from_alt")
|
44
|
+
|
45
|
+
org1.switch_tenant
|
46
|
+
expect(PandaPal::ApiCall.count).to eq(1)
|
47
|
+
expect(PandaPal::ApiCall.first.logic).to eq("from_primary")
|
48
|
+
expect(PandaPal::ApiCall.connection.exec_query("SELECT current_database()").pluck("current_database")[0]).to eq("panda_pal_test1")
|
49
|
+
|
50
|
+
org2.switch_tenant
|
51
|
+
expect(PandaPal::ApiCall.count).to eq(1)
|
52
|
+
expect(PandaPal::ApiCall.first.logic).to eq("from_alt")
|
53
|
+
expect(PandaPal::ApiCall.connection.exec_query("SELECT current_database()").pluck("current_database")[0]).to eq("panda_pal_test2")
|
54
|
+
end
|
55
|
+
|
34
56
|
context "load_async" do
|
35
57
|
it "works across shards" do
|
36
58
|
qs = []
|