rails_multisite 2.0.7 → 2.3.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of rails_multisite might be problematic. Click here for more details.

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1a0e0f9bb773343cb717c3342bdba03296eb1d7f298a26527aa435309aba5c71
4
- data.tar.gz: 8b2d59de4f66e24d753f72b4bf43618769178191e3b25a1117b8a0fd4460e0a0
3
+ metadata.gz: 2acf52c9b8002bff6a1590222b85d778cb1ddd9e28de6ac91eed45d5117e30aa
4
+ data.tar.gz: 3b39a8d9a2d2b70c62e29a0541d585c499a51cb9ac6b8dac2544343b1c22d45c
5
5
  SHA512:
6
- metadata.gz: 706c6793500ab5a89ceec191519033263f2851c94fb707614b28c1c2da9fee89b274ee268bac880e8893a0f2ad4c24ee86d087894b4a9bec35fd28abe0200312
7
- data.tar.gz: a1156c538005d8cd01dfc3994c890a12cf872c4400b9c5e6e0ddcdd1e4d018ab9486edd3227b5c67718b643933258f6c009712e7c1c90b474cdc05c7d6e31a31
6
+ metadata.gz: f7b8775f143c21083b7141ca6592c5f8d75f12a287f14452a63ff159f0932c0fafe918256d8219431d9d3647b09b340daab747d5b0b10ff3e1c1b1c1f3eeab34
7
+ data.tar.gz: 81abf0c622d83d541bb0870a7bc2cac379c137ae4057b11a44bc8ab8ff4a6be3e1b730420766b22a55ff3aa7505ef7e9e0ab5494c8c1bdedfc8444e862cf0af0
data/README.md CHANGED
@@ -35,7 +35,6 @@ mlp:
35
35
  host: dbhost
36
36
  pool: 5
37
37
  timeout: 5000
38
- db_id: 1 # ensure db_id is unique for each site
39
38
  host_names:
40
39
  - discourse.equestria.com
41
40
  - discourse.equestria.internal
@@ -48,7 +47,6 @@ drwho:
48
47
  host: dbhost
49
48
  pool: 5
50
49
  timeout: 5000
51
- db_id: 2 # ensure db_id is unique for each site
52
50
  host_names:
53
51
  - discuss.tardis.gallifrey
54
52
  ```
@@ -92,7 +90,7 @@ db_two:
92
90
  To get a Rails console that is connected to `some_database_1` database:
93
91
 
94
92
  ```
95
- RAILS_ENV=db_one rails console
93
+ RAILS_DB=db_one rails console
96
94
  ```
97
95
 
98
96
 
@@ -4,12 +4,17 @@ module RailsMultisite
4
4
  class ConnectionManagement
5
5
 
6
6
  DEFAULT = 'default'
7
+ SPEC_KLASS = ActiveRecord::ConnectionAdapters::ConnectionSpecification
7
8
 
8
9
  def self.default_config_filename
9
10
  File.absolute_path(Rails.root.to_s + "/config/multisite.yml")
10
11
  end
11
12
 
12
13
  def self.clear_settings!
14
+ @instance&.db_spec_cache&.each do |key, spec|
15
+ @instance.connection_handlers.delete(self.handler_key(spec))
16
+ end
17
+
13
18
  @instance = nil
14
19
  end
15
20
 
@@ -35,7 +40,7 @@ module RailsMultisite
35
40
  end
36
41
 
37
42
  def self.reload
38
- @instance = new(instance.config_filename)
43
+ @instance.reload
39
44
  end
40
45
 
41
46
  def self.has_db?(db)
@@ -97,6 +102,13 @@ module RailsMultisite
97
102
  config[:host_names].nil? ? config[:host] : config[:host_names].first
98
103
  end
99
104
 
105
+ def self.current_db_hostnames
106
+ spec = @instance.connection_spec(db: self.current_db) if @instance
107
+ spec ||= ActiveRecord::Base.connection_pool.spec
108
+ config = spec.config
109
+ config[:host_names].nil? ? [config[:host]] : config[:host_names]
110
+ end
111
+
100
112
  def self.connection_spec(opts)
101
113
  if @instance
102
114
  @instance.connection_spec(opts)
@@ -113,12 +125,52 @@ module RailsMultisite
113
125
  end
114
126
  end
115
127
 
116
- attr_reader :config_filename
128
+ def self.handler_key(spec)
129
+ @handler_key_suffix ||= begin
130
+ if ActiveRecord::Base.respond_to?(:writing_role)
131
+ "_#{ActiveRecord::Base.writing_role}"
132
+ else
133
+ ""
134
+ end
135
+ end
136
+
137
+ :"#{spec.name}#{@handler_key_suffix}"
138
+ end
139
+
140
+ def self.default_connection_handler=(connection_handler)
141
+ if @instance
142
+ unless connection_handler.is_a?(ActiveRecord::ConnectionAdapters::ConnectionHandler)
143
+ raise ArgumentError.new("Invalid connection handler")
144
+ end
145
+
146
+ @instance.default_connection_handler = connection_handler
147
+ end
148
+ end
149
+
150
+ attr_reader :config_filename, :db_spec_cache, :connection_handlers
151
+ attr_writer :default_connection_handler
117
152
 
118
153
  def initialize(config_filename)
119
154
  @config_filename = config_filename
120
155
 
121
- spec_klass = ActiveRecord::ConnectionAdapters::ConnectionSpecification
156
+ @connection_handlers = begin
157
+ if ActiveRecord::Base.respond_to?(:connection_handlers)
158
+ ActiveRecord::Base.connection_handlers
159
+ else
160
+ {}
161
+ end
162
+ end
163
+
164
+ @db_spec_cache = {}
165
+ @default_spec = SPEC_KLASS::Resolver.new(ActiveRecord::Base.configurations).spec(Rails.env.to_sym)
166
+ @default_connection_handler = ActiveRecord::Base.connection_handler
167
+
168
+ @reload_mutex = Mutex.new
169
+
170
+ load_config!
171
+ end
172
+
173
+ def load_config!
122
174
  configs = YAML::load(File.open(@config_filename))
123
175
 
124
176
  no_prepared_statements = ActiveRecord::Base.configurations[Rails.env]["prepared_statements"] == false
@@ -136,27 +188,45 @@ module RailsMultisite
136
188
  resolve_configs = ActiveRecord::DatabaseConfigurations.new(configs)
137
189
  end
138
190
 
139
- resolver = spec_klass::Resolver.new(resolve_configs)
140
- @db_spec_cache = Hash[*configs.map { |k, _| [k, resolver.spec(k.to_sym)] }.flatten]
191
+ resolver = SPEC_KLASS::Resolver.new(resolve_configs)
141
192
 
142
- @host_spec_cache = {}
193
+ # Build a hash of db name => spec
194
+ new_db_spec_cache = Hash[*configs.map { |k, _| [k, resolver.spec(k.to_sym)] }.flatten]
195
+ new_db_spec_cache.each do |k, v|
196
+ # If spec already existed, use the old version
197
+ if v&.to_hash == @db_spec_cache[k]&.to_hash
198
+ new_db_spec_cache[k] = @db_spec_cache[k]
199
+ end
200
+ end
143
201
 
202
+ # Build a hash of hostname => spec
203
+ new_host_spec_cache = {}
144
204
  configs.each do |k, v|
145
205
  next unless v["host_names"]
146
206
  v["host_names"].each do |host|
147
- @host_spec_cache[host] = @db_spec_cache[k]
207
+ new_host_spec_cache[host] = new_db_spec_cache[k]
148
208
  end
149
209
  end
150
210
 
151
- @default_spec = spec_klass::Resolver.new(ActiveRecord::Base.configurations).spec(Rails.env.to_sym)
211
+ # Add the default hostnames as well
152
212
  ActiveRecord::Base.configurations[Rails.env]["host_names"].each do |host|
153
- @host_spec_cache[host] = @default_spec
213
+ new_host_spec_cache[host] = @default_spec
154
214
  end
155
215
 
156
- @default_connection_handler = ActiveRecord::Base.connection_handler
216
+ removed_dbs = @db_spec_cache.keys - new_db_spec_cache.keys
217
+ removed_specs = @db_spec_cache.values_at(*removed_dbs)
218
+
219
+ @host_spec_cache = new_host_spec_cache
220
+ @db_spec_cache = new_db_spec_cache
157
221
 
158
- @connection_handlers = {}
159
- @established_default = false
222
+ # Clean up connection handler cache.
223
+ removed_specs.each { |s| @connection_handlers.delete(handler_key(s)) }
224
+ end
225
+
226
+ def reload
227
+ @reload_mutex.synchronize do
228
+ load_config!
229
+ end
160
230
  end
161
231
 
162
232
  def has_db?(db)
@@ -178,18 +248,14 @@ module RailsMultisite
178
248
  spec ||= @default_spec
179
249
  handler = nil
180
250
  if spec != @default_spec
181
- handler = @connection_handlers[spec]
251
+ handler = @connection_handlers[handler_key(spec)]
182
252
  unless handler
183
253
  handler = ActiveRecord::ConnectionAdapters::ConnectionHandler.new
184
254
  handler_establish_connection(handler, spec)
185
- @connection_handlers[spec] = handler
255
+ @connection_handlers[handler_key(spec)] = handler
186
256
  end
187
257
  else
188
258
  handler = @default_connection_handler
189
- if !@established_default
190
- handler_establish_connection(handler, spec)
191
- @established_default = true
192
- end
193
259
  end
194
260
 
195
261
  ActiveRecord::Base.connection_handler = handler
@@ -320,11 +386,11 @@ module RailsMultisite
320
386
  private
321
387
 
322
388
  def handler_establish_connection(handler, spec)
323
- if Rails::VERSION::MAJOR >= 5
324
- handler.establish_connection(spec.config)
325
- else
326
- handler.establish_connection(ActiveRecord::Base, spec)
327
- end
389
+ handler.establish_connection(spec.config)
390
+ end
391
+
392
+ def handler_key(spec)
393
+ self.class.handler_key(spec)
328
394
  end
329
395
 
330
396
  end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module RailsMultisite
2
3
  class Middleware
3
4
  def initialize(app, config = nil)
@@ -7,20 +7,28 @@ module RailsMultisite
7
7
  end
8
8
 
9
9
  initializer "RailsMultisite.init" do |app|
10
- Rails.configuration.multisite = false
10
+ app.config.multisite = false
11
11
 
12
12
  config_file = ConnectionManagement.default_config_filename
13
13
  if File.exist?(config_file)
14
14
  ConnectionManagement.config_filename = ConnectionManagement.default_config_filename
15
- Rails.configuration.multisite = true
15
+ app.config.multisite = true
16
16
  Rails.logger.formatter = RailsMultisite::Formatter.new
17
- app.middleware.insert_after(ActionDispatch::Executor, RailsMultisite::Middleware)
18
- app.middleware.delete(ActionDispatch::Executor)
17
+
18
+ if !skip_middleware?(app.config)
19
+ app.middleware.insert_after(ActionDispatch::Executor, RailsMultisite::Middleware)
20
+ app.middleware.delete(ActionDispatch::Executor)
21
+ end
19
22
 
20
23
  if ENV['RAILS_DB'].present?
21
24
  ConnectionManagement.establish_connection(db: ENV['RAILS_DB'], raise_on_missing: true)
22
25
  end
23
26
  end
24
27
  end
28
+
29
+ def skip_middleware?(config)
30
+ return false if !config.respond_to?(:skip_multisite_middleware)
31
+ config.skip_multisite_middleware
32
+ end
25
33
  end
26
34
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
  #
3
3
  module RailsMultisite
4
- VERSION = "2.0.7"
4
+ VERSION = "2.3.0"
5
5
  end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  desc "migrate all sites in tier"
2
3
  task "multisite:migrate" => :environment do
3
4
  RailsMultisite::ConnectionManagement.each_connection do |db|
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  desc "generate multisite config file (if missing)"
2
3
  task "multisite:generate:config" => :environment do
3
4
  filename = RailsMultisite::ConnectionManagement.config_filename
@@ -14,7 +15,6 @@ task "multisite:generate:config" => :environment do
14
15
  # host: localhost
15
16
  # pool: 5
16
17
  # timeout: 5000
17
- # db_id: 1 # optionally include other settings you need
18
18
  # host_names:
19
19
  # - www.mysite.com
20
20
  # - www.anothersite.com
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rails_multisite
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.7
4
+ version: 2.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sam Saffron
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-04-29 00:00:00.000000000 Z
11
+ date: 2020-06-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -16,7 +16,7 @@ dependencies:
16
16
  requirements:
17
17
  - - ">"
18
18
  - !ruby/object:Gem::Version
19
- version: '4.2'
19
+ version: '5.0'
20
20
  - - "<"
21
21
  - !ruby/object:Gem::Version
22
22
  version: '7'
@@ -26,7 +26,7 @@ dependencies:
26
26
  requirements:
27
27
  - - ">"
28
28
  - !ruby/object:Gem::Version
29
- version: '4.2'
29
+ version: '5.0'
30
30
  - - "<"
31
31
  - !ruby/object:Gem::Version
32
32
  version: '7'
@@ -36,7 +36,7 @@ dependencies:
36
36
  requirements:
37
37
  - - ">"
38
38
  - !ruby/object:Gem::Version
39
- version: '4.2'
39
+ version: '5.0'
40
40
  - - "<"
41
41
  - !ruby/object:Gem::Version
42
42
  version: '7'
@@ -46,7 +46,7 @@ dependencies:
46
46
  requirements:
47
47
  - - ">"
48
48
  - !ruby/object:Gem::Version
49
- version: '4.2'
49
+ version: '5.0'
50
50
  - - "<"
51
51
  - !ruby/object:Gem::Version
52
52
  version: '7'
@@ -78,14 +78,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
78
78
  requirements:
79
79
  - - ">="
80
80
  - !ruby/object:Gem::Version
81
- version: 2.3.0
81
+ version: 2.4.0
82
82
  required_rubygems_version: !ruby/object:Gem::Requirement
83
83
  requirements:
84
84
  - - ">="
85
85
  - !ruby/object:Gem::Version
86
86
  version: '0'
87
87
  requirements: []
88
- rubygems_version: 3.0.3
88
+ rubygems_version: 3.1.2
89
89
  signing_key:
90
90
  specification_version: 4
91
91
  summary: Multi tenancy support for Rails