activerecord-tenanted 0.3.0 → 0.4.0
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/Rakefile +10 -0
- data/lib/active_record/tenanted/base.rb +2 -5
- data/lib/active_record/tenanted/database_configurations/base_config.rb +105 -0
- data/lib/active_record/tenanted/database_configurations/tenant_config.rb +56 -0
- data/lib/active_record/tenanted/database_configurations.rb +1 -150
- data/lib/active_record/tenanted/lru.rb +44 -0
- data/lib/active_record/tenanted/railtie.rb +6 -0
- data/lib/active_record/tenanted/subtenant.rb +3 -2
- data/lib/active_record/tenanted/tenant.rb +22 -9
- data/lib/active_record/tenanted/testing.rb +2 -2
- data/lib/active_record/tenanted/version.rb +1 -1
- metadata +8 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0c816167bb3121714715c597882f45c9b586ac562545b344417038a7cfcc61f0
|
4
|
+
data.tar.gz: 2f948cd900f8b8728fb02b05209cb85fa1da86340ecd0819de3e56db0ea5f618
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 29d74ec62e44edbfdd28dbad5a708b5bdd4816e88b758bc48a4b6244f2ca9641138a8ac3d25aeae84b9e901c17ca748d6a42016c3df2ae9d4e6818d0738a4f0e
|
7
|
+
data.tar.gz: ec01de5118d1c22ded517ab0228789664fa6864260c315f1ec4c51f0d198bc3507af7e373bc02e40d8f9fbef5a4d594d9c5609d6dbd435fdbbbd0691422de029
|
data/Rakefile
CHANGED
@@ -7,3 +7,13 @@ require "bundler/gem_tasks"
|
|
7
7
|
task :clean do
|
8
8
|
FileUtils.rm_f(Dir.glob("test/dummy/log/*.log"), verbose: true)
|
9
9
|
end
|
10
|
+
|
11
|
+
desc "Regenerate tables of contents in some files"
|
12
|
+
task "toc" do
|
13
|
+
require "mkmf"
|
14
|
+
if find_executable0("markdown-toc")
|
15
|
+
sh "markdown-toc --maxdepth=3 -i GUIDE.md"
|
16
|
+
else
|
17
|
+
puts "WARN: cannot find markdown-toc, skipping. install with 'npm install markdown-toc'"
|
18
|
+
end
|
19
|
+
end
|
@@ -8,9 +8,6 @@ module ActiveRecord
|
|
8
8
|
class_methods do
|
9
9
|
def initialize(...)
|
10
10
|
super
|
11
|
-
|
12
|
-
@tenanted_config_name = nil
|
13
|
-
@tenanted_subtenant_of = nil
|
14
11
|
end
|
15
12
|
|
16
13
|
def tenanted(config_name = "primary")
|
@@ -20,7 +17,7 @@ module ActiveRecord
|
|
20
17
|
prepend Tenant
|
21
18
|
|
22
19
|
self.connection_class = true
|
23
|
-
|
20
|
+
self.tenanted_config_name = config_name
|
24
21
|
|
25
22
|
unless tenanted_root_config.configuration_hash[:tenanted]
|
26
23
|
raise Error, "The '#{tenanted_config_name}' database is not configured as tenanted."
|
@@ -30,7 +27,7 @@ module ActiveRecord
|
|
30
27
|
def subtenant_of(class_name)
|
31
28
|
prepend Subtenant
|
32
29
|
|
33
|
-
|
30
|
+
self.tenanted_subtenant_of_klass_name = class_name
|
34
31
|
end
|
35
32
|
|
36
33
|
def tenanted?
|
@@ -0,0 +1,105 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveRecord
|
4
|
+
module Tenanted
|
5
|
+
module DatabaseConfigurations
|
6
|
+
class BaseConfig < ActiveRecord::DatabaseConfigurations::HashConfig
|
7
|
+
DEFAULT_MAX_CONNECTION_POOLS = 50
|
8
|
+
|
9
|
+
attr_accessor :test_worker_id
|
10
|
+
|
11
|
+
def initialize(...)
|
12
|
+
super
|
13
|
+
@test_worker_id = nil
|
14
|
+
end
|
15
|
+
|
16
|
+
def database_tasks?
|
17
|
+
false
|
18
|
+
end
|
19
|
+
|
20
|
+
def database_for(tenant_name)
|
21
|
+
tenant_name = tenant_name.to_s
|
22
|
+
|
23
|
+
validate_tenant_name(tenant_name)
|
24
|
+
|
25
|
+
path = sprintf(database, tenant: tenant_name)
|
26
|
+
|
27
|
+
if test_worker_id
|
28
|
+
test_worker_path(path)
|
29
|
+
else
|
30
|
+
path
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def database_path_for(tenant_name)
|
35
|
+
coerce_path(database_for(tenant_name))
|
36
|
+
end
|
37
|
+
|
38
|
+
def tenants
|
39
|
+
glob = database_path_for("*")
|
40
|
+
scanner = Regexp.new(database_path_for("(.+)"))
|
41
|
+
|
42
|
+
Dir.glob(glob).map do |path|
|
43
|
+
result = path.scan(scanner).flatten.first
|
44
|
+
if result.nil?
|
45
|
+
warn "WARN: ActiveRecord::Tenanted: Cannot parse tenant name from filename #{path.inspect}. " \
|
46
|
+
"This is a bug, please report it to https://github.com/basecamp/activerecord-tenanted/issues"
|
47
|
+
end
|
48
|
+
result
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def new_tenant_config(tenant_name)
|
53
|
+
config_name = "#{name}_#{tenant_name}"
|
54
|
+
config_hash = configuration_hash.dup.tap do |hash|
|
55
|
+
hash[:tenant] = tenant_name
|
56
|
+
hash[:database] = database_for(tenant_name)
|
57
|
+
hash[:database_path] = database_path_for(tenant_name)
|
58
|
+
hash[:tenanted_config_name] = name
|
59
|
+
end
|
60
|
+
Tenanted::DatabaseConfigurations::TenantConfig.new(env_name, config_name, config_hash)
|
61
|
+
end
|
62
|
+
|
63
|
+
def new_connection
|
64
|
+
raise NoTenantError, "Cannot use an untenanted ActiveRecord::Base connection. " \
|
65
|
+
"If you have a model that inherits directly from ActiveRecord::Base, " \
|
66
|
+
"make sure to use 'subtenant_of'. In development, you may see this error " \
|
67
|
+
"if constant reloading is not being done properly."
|
68
|
+
end
|
69
|
+
|
70
|
+
def max_connection_pools
|
71
|
+
(configuration_hash[:max_connection_pools] || DEFAULT_MAX_CONNECTION_POOLS).to_i
|
72
|
+
end
|
73
|
+
|
74
|
+
private
|
75
|
+
# A sqlite database path can be a file path or a URI (either relative or absolute).
|
76
|
+
# We can't parse it as a standard URI in all circumstances, though, see https://sqlite.org/uri.html
|
77
|
+
def coerce_path(path)
|
78
|
+
if path.start_with?("file:/")
|
79
|
+
URI.parse(path).path
|
80
|
+
elsif path.start_with?("file:")
|
81
|
+
URI.parse(path.sub(/\?.*$/, "")).opaque
|
82
|
+
else
|
83
|
+
path
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def validate_tenant_name(tenant_name)
|
88
|
+
if tenant_name.match?(%r{[/'"`]})
|
89
|
+
raise BadTenantNameError, "Tenant name contains an invalid character: #{tenant_name.inspect}"
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def test_worker_path(path)
|
94
|
+
test_worker_suffix = "_#{test_worker_id}"
|
95
|
+
|
96
|
+
if path.start_with?("file:") && path.include?("?")
|
97
|
+
path.sub(/(\?.*)$/, "#{test_worker_suffix}\\1")
|
98
|
+
else
|
99
|
+
path + test_worker_suffix
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveRecord
|
4
|
+
module Tenanted
|
5
|
+
module DatabaseConfigurations
|
6
|
+
class TenantConfig < ActiveRecord::DatabaseConfigurations::HashConfig
|
7
|
+
def tenant
|
8
|
+
configuration_hash.fetch(:tenant)
|
9
|
+
end
|
10
|
+
|
11
|
+
def new_connection
|
12
|
+
ensure_database_directory_exists # adapter doesn't handle this if the database is a URI
|
13
|
+
super.tap { |conn| conn.tenant = tenant }
|
14
|
+
end
|
15
|
+
|
16
|
+
def tenanted_config_name
|
17
|
+
configuration_hash.fetch(:tenanted_config_name)
|
18
|
+
end
|
19
|
+
|
20
|
+
def primary?
|
21
|
+
ActiveRecord::Base.configurations.primary?(tenanted_config_name)
|
22
|
+
end
|
23
|
+
|
24
|
+
def schema_dump(format = ActiveRecord.schema_format)
|
25
|
+
if configuration_hash.key?(:schema_dump) || primary?
|
26
|
+
super
|
27
|
+
else
|
28
|
+
"#{tenanted_config_name}_#{schema_file_type(format)}"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def default_schema_cache_path(db_dir = "db")
|
33
|
+
if primary?
|
34
|
+
super
|
35
|
+
else
|
36
|
+
File.join(db_dir, "#{tenanted_config_name}_schema_cache.yml")
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def database_path
|
41
|
+
configuration_hash[:database_path]
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
def ensure_database_directory_exists
|
46
|
+
return unless database_path
|
47
|
+
|
48
|
+
database_dir = File.dirname(database_path)
|
49
|
+
unless File.directory?(database_dir)
|
50
|
+
FileUtils.mkdir_p(database_dir)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -5,162 +5,13 @@ require "active_record/database_configurations"
|
|
5
5
|
module ActiveRecord
|
6
6
|
module Tenanted
|
7
7
|
module DatabaseConfigurations
|
8
|
-
class RootConfig < ActiveRecord::DatabaseConfigurations::HashConfig
|
9
|
-
attr_accessor :test_worker_id
|
10
|
-
|
11
|
-
def initialize(...)
|
12
|
-
super
|
13
|
-
@test_worker_id = nil
|
14
|
-
end
|
15
|
-
|
16
|
-
def database_tasks?
|
17
|
-
false
|
18
|
-
end
|
19
|
-
|
20
|
-
def database_for(tenant_name)
|
21
|
-
tenant_name = tenant_name.to_s
|
22
|
-
|
23
|
-
validate_tenant_name(tenant_name)
|
24
|
-
|
25
|
-
path = sprintf(database, tenant: tenant_name)
|
26
|
-
|
27
|
-
if test_worker_id
|
28
|
-
test_worker_path(path)
|
29
|
-
else
|
30
|
-
path
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
def database_path_for(tenant_name)
|
35
|
-
coerce_path(database_for(tenant_name))
|
36
|
-
end
|
37
|
-
|
38
|
-
def tenants
|
39
|
-
glob = database_path_for("*")
|
40
|
-
scanner = Regexp.new(database_path_for("(.+)"))
|
41
|
-
|
42
|
-
Dir.glob(glob).map do |path|
|
43
|
-
result = path.scan(scanner).flatten.first
|
44
|
-
if result.nil?
|
45
|
-
warn "WARN: ActiveRecord::Tenanted: Cannot parse tenant name from filename #{path.inspect}. " \
|
46
|
-
"This is a bug, please report it to https://github.com/basecamp/activerecord-tenanted/issues"
|
47
|
-
end
|
48
|
-
result
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
def new_tenant_config(tenant_name)
|
53
|
-
config_name = "#{name}_#{tenant_name}"
|
54
|
-
config_hash = configuration_hash.dup.tap do |hash|
|
55
|
-
hash[:tenant] = tenant_name
|
56
|
-
hash[:database] = database_for(tenant_name)
|
57
|
-
hash[:database_path] = database_path_for(tenant_name)
|
58
|
-
hash[:tenanted_config_name] = name
|
59
|
-
end
|
60
|
-
Tenanted::DatabaseConfigurations::TenantConfig.new(env_name, config_name, config_hash)
|
61
|
-
end
|
62
|
-
|
63
|
-
def new_connection
|
64
|
-
raise NoTenantError, "Cannot use an untenanted ActiveRecord::Base connection. " \
|
65
|
-
"If you have a model that inherits directly from ActiveRecord::Base, " \
|
66
|
-
"make sure to use 'subtenant_of'. In development, you may see this error " \
|
67
|
-
"if constant reloading is not being done properly."
|
68
|
-
end
|
69
|
-
|
70
|
-
private
|
71
|
-
# A sqlite database path can be a file path or a URI (either relative or absolute).
|
72
|
-
# We can't parse it as a standard URI in all circumstances, though, see https://sqlite.org/uri.html
|
73
|
-
def coerce_path(path)
|
74
|
-
if path.start_with?("file:/")
|
75
|
-
URI.parse(path).path
|
76
|
-
elsif path.start_with?("file:")
|
77
|
-
URI.parse(path.sub(/\?.*$/, "")).opaque
|
78
|
-
else
|
79
|
-
path
|
80
|
-
end
|
81
|
-
end
|
82
|
-
|
83
|
-
def validate_tenant_name(tenant_name)
|
84
|
-
if tenant_name.match?(%r{[/'"`]})
|
85
|
-
raise BadTenantNameError, "Tenant name contains an invalid character: #{tenant_name.inspect}"
|
86
|
-
end
|
87
|
-
end
|
88
|
-
|
89
|
-
def test_worker_path(path)
|
90
|
-
test_worker_suffix = "_#{test_worker_id}"
|
91
|
-
|
92
|
-
if path.start_with?("file:") && path.include?("?")
|
93
|
-
path.sub(/(\?.*)$/, "#{test_worker_suffix}\\1")
|
94
|
-
else
|
95
|
-
path + test_worker_suffix
|
96
|
-
end
|
97
|
-
end
|
98
|
-
end
|
99
|
-
|
100
|
-
class TenantConfig < ActiveRecord::DatabaseConfigurations::HashConfig
|
101
|
-
def tenant
|
102
|
-
configuration_hash.fetch(:tenant)
|
103
|
-
end
|
104
|
-
|
105
|
-
def new_connection
|
106
|
-
ensure_database_directory_exists # adapter doesn't handle this if the database is a URI
|
107
|
-
super.tap { |conn| conn.tenant = tenant }
|
108
|
-
end
|
109
|
-
|
110
|
-
def tenanted_config_name
|
111
|
-
configuration_hash.fetch(:tenanted_config_name)
|
112
|
-
end
|
113
|
-
|
114
|
-
def primary?
|
115
|
-
ActiveRecord::Base.configurations.primary?(tenanted_config_name)
|
116
|
-
end
|
117
|
-
|
118
|
-
def schema_dump(format = ActiveRecord.schema_format)
|
119
|
-
if configuration_hash.key?(:schema_dump) || primary?
|
120
|
-
super
|
121
|
-
else
|
122
|
-
"#{tenanted_config_name}_#{schema_file_type(format)}"
|
123
|
-
end
|
124
|
-
end
|
125
|
-
|
126
|
-
def default_schema_cache_path(db_dir = "db")
|
127
|
-
if primary?
|
128
|
-
super
|
129
|
-
else
|
130
|
-
File.join(db_dir, "#{tenanted_config_name}_schema_cache.yml")
|
131
|
-
end
|
132
|
-
end
|
133
|
-
|
134
|
-
def database_path
|
135
|
-
configuration_hash[:database_path]
|
136
|
-
end
|
137
|
-
|
138
|
-
private
|
139
|
-
def ensure_database_directory_exists
|
140
|
-
return unless database_path
|
141
|
-
|
142
|
-
database_dir = File.dirname(database_path)
|
143
|
-
unless File.directory?(database_dir)
|
144
|
-
FileUtils.mkdir_p(database_dir)
|
145
|
-
end
|
146
|
-
end
|
147
|
-
end
|
148
|
-
|
149
|
-
# Invoked by the railtie
|
150
8
|
def self.register_db_config_handler # :nodoc:
|
151
9
|
ActiveRecord::DatabaseConfigurations.register_db_config_handler do |env_name, name, _, config|
|
152
10
|
next unless config.fetch(:tenanted, false)
|
153
11
|
|
154
|
-
ActiveRecord::Tenanted::DatabaseConfigurations::
|
12
|
+
ActiveRecord::Tenanted::DatabaseConfigurations::BaseConfig.new(env_name, name, config)
|
155
13
|
end
|
156
14
|
end
|
157
15
|
end
|
158
16
|
end
|
159
17
|
end
|
160
|
-
|
161
|
-
# Do this here instead of the railtie so we register the handlers before Rails's rake tasks get
|
162
|
-
# loaded. If the handler is not present, then the RootConfigs will not return false from
|
163
|
-
# `#database_tasks?` and the database tasks will get created anyway.
|
164
|
-
#
|
165
|
-
# TODO: This can be moved back into the railtie if https://github.com/rails/rails/pull/54959 is merged.
|
166
|
-
ActiveRecord::Tenanted::DatabaseConfigurations.register_db_config_handler
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveRecord
|
4
|
+
module Tenanted
|
5
|
+
# Inspired by the lru_redux gem, this LRU queue relies on Concurrent::Hash being ordered
|
6
|
+
class LRU # :nodoc:
|
7
|
+
def initialize
|
8
|
+
@data = Concurrent::Hash.new
|
9
|
+
end
|
10
|
+
|
11
|
+
def [](key)
|
12
|
+
found = true
|
13
|
+
value = @data.delete(key) { found = false }
|
14
|
+
if found
|
15
|
+
@data[key] = value
|
16
|
+
else
|
17
|
+
nil
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def []=(key, value)
|
22
|
+
@data.delete key
|
23
|
+
@data[key] = value
|
24
|
+
value
|
25
|
+
end
|
26
|
+
|
27
|
+
def size
|
28
|
+
@data.size
|
29
|
+
end
|
30
|
+
|
31
|
+
def pop
|
32
|
+
key, value = @data.first
|
33
|
+
@data.delete(key)
|
34
|
+
[ key, value ]
|
35
|
+
end
|
36
|
+
|
37
|
+
def keys
|
38
|
+
@data.keys
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
Lru = LRU
|
43
|
+
end
|
44
|
+
end
|
@@ -57,6 +57,12 @@ module ActiveRecord
|
|
57
57
|
# Defaults to "development-tenant" in development and "test-tenant" in test environments.
|
58
58
|
config.active_record_tenanted.default_tenant = Rails.env.local? ? "#{Rails.env}-tenant" : nil
|
59
59
|
|
60
|
+
config.before_configuration do
|
61
|
+
ActiveSupport.on_load(:active_record_database_configurations) do
|
62
|
+
ActiveRecord::Tenanted::DatabaseConfigurations.register_db_config_handler
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
60
66
|
config.before_initialize do
|
61
67
|
Rails.application.configure do
|
62
68
|
if config.active_record_tenanted.connection_class.present?
|
@@ -12,8 +12,7 @@ module ActiveRecord
|
|
12
12
|
|
13
13
|
def tenanted_subtenant_of
|
14
14
|
# TODO: cache this / speed this up
|
15
|
-
|
16
|
-
klass = @tenanted_subtenant_of&.constantize || superclass.tenanted_subtenant_of
|
15
|
+
klass = tenanted_subtenant_of_klass_name&.constantize
|
17
16
|
|
18
17
|
raise Error, "Class #{klass} is not tenanted" unless klass.tenanted?
|
19
18
|
raise Error, "Class #{klass} is not a connection class" unless klass.abstract_class?
|
@@ -26,6 +25,8 @@ module ActiveRecord
|
|
26
25
|
|
27
26
|
prepended do
|
28
27
|
prepend TenantCommon
|
28
|
+
|
29
|
+
cattr_accessor :tenanted_subtenant_of_klass_name
|
29
30
|
end
|
30
31
|
|
31
32
|
def tenanted?
|
@@ -165,7 +165,7 @@ module ActiveRecord
|
|
165
165
|
end
|
166
166
|
|
167
167
|
def tenants
|
168
|
-
# DatabaseConfigurations::
|
168
|
+
# DatabaseConfigurations::BaseConfig#tenants returns all tenants whose database files
|
169
169
|
# exist, but some of those may be getting initially migrated, so we perform an additional
|
170
170
|
# filter on readiness with `tenant_exist?`.
|
171
171
|
tenanted_root_config.tenants.select { |t| tenant_exist?(t) }
|
@@ -206,10 +206,6 @@ module ActiveRecord
|
|
206
206
|
ActiveRecord::Base.configurations.resolve(tenanted_config_name.to_sym)
|
207
207
|
end
|
208
208
|
|
209
|
-
def tenanted_config_name # :nodoc:
|
210
|
-
@tenanted_config_name ||= (superclass.respond_to?(:tenanted_config_name) ? superclass.tenanted_config_name : nil)
|
211
|
-
end
|
212
|
-
|
213
209
|
def _create_tenanted_pool(schema_version_check: true) # :nodoc:
|
214
210
|
# ensure all classes use the same connection pool
|
215
211
|
return superclass._create_tenanted_pool unless connection_class?
|
@@ -232,10 +228,24 @@ module ActiveRecord
|
|
232
228
|
|
233
229
|
private
|
234
230
|
def retrieve_connection_pool(strict:)
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
231
|
+
role = current_role
|
232
|
+
shard = current_tenant
|
233
|
+
connection_handler.retrieve_connection_pool(connection_specification_name, role:, shard:, strict:).tap do |pool|
|
234
|
+
if pool
|
235
|
+
tenanted_connection_pools[[ shard, role ]] = pool
|
236
|
+
reap_connection_pools
|
237
|
+
end
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
241
|
+
def reap_connection_pools
|
242
|
+
while tenanted_connection_pools.size > tenanted_root_config.max_connection_pools
|
243
|
+
info, _ = *tenanted_connection_pools.pop
|
244
|
+
shard, role = *info
|
245
|
+
|
246
|
+
connection_handler.remove_connection_pool(connection_specification_name, role:, shard:)
|
247
|
+
Rails.logger.info " REAPED [tenant=#{shard} role=#{role}] Tenanted connection pool reaped to limit total connection pools"
|
248
|
+
end
|
239
249
|
end
|
240
250
|
|
241
251
|
def log_tenant_tag(tenant_name, &block)
|
@@ -251,6 +261,9 @@ module ActiveRecord
|
|
251
261
|
self.default_shard = ActiveRecord::Tenanted::Tenant::UNTENANTED_SENTINEL
|
252
262
|
|
253
263
|
prepend TenantCommon
|
264
|
+
|
265
|
+
cattr_accessor :tenanted_config_name
|
266
|
+
cattr_accessor(:tenanted_connection_pools) { LRU.new }
|
254
267
|
end
|
255
268
|
|
256
269
|
def tenanted?
|
@@ -73,9 +73,9 @@ module ActiveRecord
|
|
73
73
|
def transactional_tests_for_pool?(pool)
|
74
74
|
config = pool.db_config
|
75
75
|
|
76
|
-
# Prevent the tenanted
|
76
|
+
# Prevent the tenanted BaseConfig from creating transactional fixtures on an unnecessary
|
77
77
|
# database, which would result in sporadic locking errors.
|
78
|
-
is_root_config = config.instance_of?(Tenanted::DatabaseConfigurations::
|
78
|
+
is_root_config = config.instance_of?(Tenanted::DatabaseConfigurations::BaseConfig)
|
79
79
|
|
80
80
|
# Any tenanted database that isn't the default test fixture database should not be wrapped
|
81
81
|
# in a transaction, for a couple of reasons:
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: activerecord-tenanted
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mike Dalessio
|
@@ -15,28 +15,28 @@ dependencies:
|
|
15
15
|
requirements:
|
16
16
|
- - ">="
|
17
17
|
- !ruby/object:Gem::Version
|
18
|
-
version: 8.1.
|
18
|
+
version: 8.1.beta
|
19
19
|
type: :runtime
|
20
20
|
prerelease: false
|
21
21
|
version_requirements: !ruby/object:Gem::Requirement
|
22
22
|
requirements:
|
23
23
|
- - ">="
|
24
24
|
- !ruby/object:Gem::Version
|
25
|
-
version: 8.1.
|
25
|
+
version: 8.1.beta
|
26
26
|
- !ruby/object:Gem::Dependency
|
27
27
|
name: railties
|
28
28
|
requirement: !ruby/object:Gem::Requirement
|
29
29
|
requirements:
|
30
30
|
- - ">="
|
31
31
|
- !ruby/object:Gem::Version
|
32
|
-
version: 8.1.
|
32
|
+
version: 8.1.beta
|
33
33
|
type: :runtime
|
34
34
|
prerelease: false
|
35
35
|
version_requirements: !ruby/object:Gem::Requirement
|
36
36
|
requirements:
|
37
37
|
- - ">="
|
38
38
|
- !ruby/object:Gem::Version
|
39
|
-
version: 8.1.
|
39
|
+
version: 8.1.beta
|
40
40
|
- !ruby/object:Gem::Dependency
|
41
41
|
name: zeitwerk
|
42
42
|
requirement: !ruby/object:Gem::Requirement
|
@@ -74,9 +74,12 @@ files:
|
|
74
74
|
- lib/active_record/tenanted/connection_adapter.rb
|
75
75
|
- lib/active_record/tenanted/console.rb
|
76
76
|
- lib/active_record/tenanted/database_configurations.rb
|
77
|
+
- lib/active_record/tenanted/database_configurations/base_config.rb
|
78
|
+
- lib/active_record/tenanted/database_configurations/tenant_config.rb
|
77
79
|
- lib/active_record/tenanted/database_tasks.rb
|
78
80
|
- lib/active_record/tenanted/global_id.rb
|
79
81
|
- lib/active_record/tenanted/job.rb
|
82
|
+
- lib/active_record/tenanted/lru.rb
|
80
83
|
- lib/active_record/tenanted/mailer.rb
|
81
84
|
- lib/active_record/tenanted/mutex.rb
|
82
85
|
- lib/active_record/tenanted/patches.rb
|