switch_point 0.4.2 → 0.4.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/CHANGELOG.md +3 -0
- data/README.md +5 -0
- data/lib/switch_point/model.rb +25 -0
- data/lib/switch_point/proxy.rb +12 -4
- data/lib/switch_point/version.rb +1 -1
- data/spec/models.rb +26 -1
- data/spec/spec_helper.rb +11 -0
- data/spec/switch_point/model_spec.rb +108 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7e586669d11f096afeeb93a78957547b262583dd
|
4
|
+
data.tar.gz: 72070196c4ca9a4ace102c2e70e24924eac98859
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bcd62b44be847b7466f31083b10eb9662061e27f33855d75bc5867ba5c12b43ac6fd57e2fb539e5a3234755540e397b9c5a3c1b30a036cbb09b60ef63d6ed282
|
7
|
+
data.tar.gz: 56249e61ef7b33a5b170680a1fd9350e8fdc42a54d051790e2c6bbb53b2056661e93c9fed7a66d9cdc1a9b4b49ef6926073f12d5dc2ba7764e27a8fbbac4ef2c
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -40,6 +40,11 @@ Suppose `after_save` callback is set to User model. When `User.create` is called
|
|
40
40
|
- At this point, the connection is READONLY and in a transaction.
|
41
41
|
6. COMMIT TRANSACTION is sent to READONLY connection.
|
42
42
|
|
43
|
+
### connection-related methods of model
|
44
|
+
Model has several connection-related methods: `connection_handler`, `connection_pool`, `connected?` and so on.
|
45
|
+
Since only `connection` method is monkey-patched, other connection-related methods doesn't work properly.
|
46
|
+
If you'd like to use those methods, send it to `Model.switch_point_proxy.model_for_connection`.
|
47
|
+
|
43
48
|
## Internals
|
44
49
|
There's a proxy which holds two connections: readonly one and writable one.
|
45
50
|
A proxy has a thread-local state indicating the current mode: readonly or writable.
|
data/lib/switch_point/model.rb
CHANGED
@@ -47,11 +47,36 @@ module SwitchPoint
|
|
47
47
|
end
|
48
48
|
end
|
49
49
|
|
50
|
+
def transaction_with(*models, &block)
|
51
|
+
unless can_transaction_with?(*models)
|
52
|
+
raise RuntimeError.new("switch_point's model names must be consistent")
|
53
|
+
end
|
54
|
+
|
55
|
+
with_writable do
|
56
|
+
self.transaction(&block)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
50
60
|
private
|
51
61
|
|
52
62
|
def assert_existing_switch_point!(name)
|
53
63
|
SwitchPoint.config.fetch(name)
|
54
64
|
end
|
65
|
+
|
66
|
+
def can_transaction_with?(*models)
|
67
|
+
writable_switch_points = [self, *models].map do |model|
|
68
|
+
if model.instance_variable_defined?(:@switch_point_name)
|
69
|
+
SwitchPoint.config.model_name(
|
70
|
+
model.instance_variable_get(:@switch_point_name),
|
71
|
+
:writable
|
72
|
+
)
|
73
|
+
else
|
74
|
+
nil
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
writable_switch_points.uniq.size == 1
|
79
|
+
end
|
55
80
|
end
|
56
81
|
end
|
57
82
|
end
|
data/lib/switch_point/proxy.rb
CHANGED
@@ -120,19 +120,27 @@ module SwitchPoint
|
|
120
120
|
@current_name = @initial_name
|
121
121
|
end
|
122
122
|
|
123
|
-
def
|
123
|
+
def model_for_connection
|
124
124
|
ProxyRepository.checkout(@current_name) # Ensure the target proxy is created
|
125
125
|
model_name = SwitchPoint.config.model_name(@current_name, mode)
|
126
126
|
if model_name
|
127
|
-
Proxy.const_get(model_name)
|
127
|
+
Proxy.const_get(model_name)
|
128
128
|
elsif mode == :readonly
|
129
129
|
# When only writable is specified, re-use writable connection.
|
130
130
|
with_writable do
|
131
|
-
|
131
|
+
model_for_connection
|
132
132
|
end
|
133
133
|
else
|
134
|
-
ActiveRecord::Base
|
134
|
+
ActiveRecord::Base
|
135
135
|
end
|
136
136
|
end
|
137
|
+
|
138
|
+
def connection
|
139
|
+
model_for_connection.connection
|
140
|
+
end
|
141
|
+
|
142
|
+
def connected?
|
143
|
+
model_for_connection.connected?
|
144
|
+
end
|
137
145
|
end
|
138
146
|
end
|
data/lib/switch_point/version.rb
CHANGED
data/spec/models.rb
CHANGED
@@ -2,6 +2,9 @@ SwitchPoint.configure do |config|
|
|
2
2
|
config.define_switch_point :main,
|
3
3
|
readonly: :main_readonly,
|
4
4
|
writable: :main_writable
|
5
|
+
config.define_switch_point :main2,
|
6
|
+
readonly: :main2_readonly,
|
7
|
+
writable: :main2_writable
|
5
8
|
config.define_switch_point :user,
|
6
9
|
readonly: :user,
|
7
10
|
writable: :user
|
@@ -31,6 +34,14 @@ class Book < ActiveRecord::Base
|
|
31
34
|
end
|
32
35
|
end
|
33
36
|
|
37
|
+
class Book2 < ActiveRecord::Base
|
38
|
+
use_switch_point :main
|
39
|
+
end
|
40
|
+
|
41
|
+
class Book3 < ActiveRecord::Base
|
42
|
+
use_switch_point :main2
|
43
|
+
end
|
44
|
+
|
34
45
|
class Publisher < ActiveRecord::Base
|
35
46
|
use_switch_point :main
|
36
47
|
end
|
@@ -66,6 +77,8 @@ base = { adapter: 'sqlite3' }
|
|
66
77
|
ActiveRecord::Base.configurations = {
|
67
78
|
'main_readonly' => base.merge(database: 'main_readonly.sqlite3'),
|
68
79
|
'main_writable' => base.merge(database: 'main_writable.sqlite3'),
|
80
|
+
'main2_readonly' => base.merge(database: 'main2_readonly.sqlite3'),
|
81
|
+
'main2_writable' => base.merge(database: 'main2_writable.sqlite3'),
|
69
82
|
'main_readonly_special' => base.merge(database: 'main_readonly_special.sqlite3'),
|
70
83
|
'user' => base.merge(database: 'user.sqlite3'),
|
71
84
|
'comment_readonly' => base.merge(database: 'comment_readonly.sqlite3'),
|
@@ -76,8 +89,20 @@ ActiveRecord::Base.establish_connection(:default)
|
|
76
89
|
|
77
90
|
# XXX: Check connection laziness
|
78
91
|
[Book, User, Note, Nanika1, ActiveRecord::Base].each do |model|
|
92
|
+
if model.connected?
|
93
|
+
raise "ActiveRecord::Base didn't establish connection lazily!"
|
94
|
+
end
|
95
|
+
end
|
96
|
+
ActiveRecord::Base.connection # Create connection
|
97
|
+
|
98
|
+
[Book, User, Nanika3].each do |model|
|
79
99
|
model.with_writable do
|
80
|
-
if model.connected?
|
100
|
+
if model.switch_point_proxy.connected?
|
101
|
+
raise "#{model.name} didn't establish connection lazily!"
|
102
|
+
end
|
103
|
+
end
|
104
|
+
model.with_readonly do
|
105
|
+
if model.switch_point_proxy.connected?
|
81
106
|
raise "#{model.name} didn't establish connection lazily!"
|
82
107
|
end
|
83
108
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -38,8 +38,19 @@ RSpec.configure do |config|
|
|
38
38
|
Book.with_writable do
|
39
39
|
Book.connection.execute('CREATE TABLE books (id integer primary key autoincrement)')
|
40
40
|
end
|
41
|
+
|
42
|
+
Book2.with_writable do
|
43
|
+
Book2.connection.execute('CREATE TABLE book2s (id integer primary key autoincrement)')
|
44
|
+
end
|
45
|
+
|
41
46
|
FileUtils.cp('main_writable.sqlite3', 'main_readonly.sqlite3')
|
42
47
|
|
48
|
+
Book3.with_writable do
|
49
|
+
Book3.connection.execute('CREATE TABLE book3s (id integer primary key autoincrement)')
|
50
|
+
end
|
51
|
+
|
52
|
+
FileUtils.cp('main2_writable.sqlite3', 'main2_readonly.sqlite3')
|
53
|
+
|
43
54
|
Note.connection.execute('CREATE TABLE notes (id integer primary key autoincrement)')
|
44
55
|
|
45
56
|
Nanika3.connection.execute('CREATE TABLE nanika3s (id integer primary key)')
|
@@ -261,4 +261,112 @@ RSpec.describe SwitchPoint::Model do
|
|
261
261
|
end
|
262
262
|
end
|
263
263
|
end
|
264
|
+
|
265
|
+
describe '.transaction_with' do
|
266
|
+
context "when each model has a same writable" do
|
267
|
+
before do
|
268
|
+
@before_book_count = Book.count
|
269
|
+
@before_book2_count = Book2.count
|
270
|
+
|
271
|
+
Book.transaction_with(Book2) do
|
272
|
+
new_book = Book.create
|
273
|
+
new_book2 = Book2.create
|
274
|
+
end
|
275
|
+
|
276
|
+
@after_book_count = Book.with_writable do
|
277
|
+
Book.count
|
278
|
+
end
|
279
|
+
@after_book2_count = Book2.with_writable do
|
280
|
+
Book2.count
|
281
|
+
end
|
282
|
+
end
|
283
|
+
|
284
|
+
it 'should create a new record' do
|
285
|
+
expect(
|
286
|
+
Book.with_writable do
|
287
|
+
Book.count
|
288
|
+
end
|
289
|
+
).to be > @before_book_count
|
290
|
+
|
291
|
+
expect(
|
292
|
+
Book2.with_writable do
|
293
|
+
Book2.count
|
294
|
+
end
|
295
|
+
).to be > @before_book2_count
|
296
|
+
end
|
297
|
+
end
|
298
|
+
|
299
|
+
context "when each model has a other writable" do
|
300
|
+
it {
|
301
|
+
expect {
|
302
|
+
Book.transaction_with(Book3) do
|
303
|
+
new_book = Book.create
|
304
|
+
new_book3 = Book3.create
|
305
|
+
end
|
306
|
+
}.to raise_error RuntimeError
|
307
|
+
}
|
308
|
+
end
|
309
|
+
|
310
|
+
context "when raise exception in transaction that include some model, and models each have other writable" do
|
311
|
+
before do
|
312
|
+
@before_book_count = Book.count
|
313
|
+
@before_book3_count = Book3.count
|
314
|
+
|
315
|
+
Book.transaction_with(Book2) do
|
316
|
+
new_book = Book.create
|
317
|
+
new_book3 = Book3.with_writable do
|
318
|
+
Book3.create
|
319
|
+
end
|
320
|
+
raise ActiveRecord::Rollback
|
321
|
+
end
|
322
|
+
end
|
323
|
+
|
324
|
+
it 'Book should not create a new record (rollbacked)' do
|
325
|
+
expect(
|
326
|
+
Book.with_writable do
|
327
|
+
Book.count
|
328
|
+
end
|
329
|
+
).to eq @before_book_count
|
330
|
+
end
|
331
|
+
|
332
|
+
it 'Book3 should create a new record (not rollbacked)' do
|
333
|
+
expect(
|
334
|
+
Book3.with_writable do
|
335
|
+
Book3.count
|
336
|
+
end
|
337
|
+
).to be > @before_book3_count
|
338
|
+
end
|
339
|
+
end
|
340
|
+
|
341
|
+
context "when nested transaction_with then parent transaction rollbacked" do
|
342
|
+
before do
|
343
|
+
@before_book_count = Book.count
|
344
|
+
@before_book3_count = Book3.count
|
345
|
+
|
346
|
+
Book.transaction_with do
|
347
|
+
Book.create
|
348
|
+
|
349
|
+
Book3.transaction_with do
|
350
|
+
Book3.create
|
351
|
+
end
|
352
|
+
|
353
|
+
raise ActiveRecord::Rollback
|
354
|
+
end
|
355
|
+
|
356
|
+
it {
|
357
|
+
expect(
|
358
|
+
Book.with_writable do
|
359
|
+
Book.count
|
360
|
+
end
|
361
|
+
).to be = @before_book_count
|
362
|
+
|
363
|
+
expect(
|
364
|
+
Book3.with_writable do
|
365
|
+
Book3.count
|
366
|
+
end
|
367
|
+
).to be > @before_book3_count
|
368
|
+
}
|
369
|
+
end
|
370
|
+
end
|
371
|
+
end
|
264
372
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: switch_point
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.
|
4
|
+
version: 0.4.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kohei Suzuki
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-06-
|
11
|
+
date: 2014-06-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: appraisal
|