activerecord-turntable 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/.gitignore +25 -0
- data/.rspec +3 -0
- data/Gemfile +25 -0
- data/Guardfile +9 -0
- data/LICENSE.txt +20 -0
- data/README.rdoc +290 -0
- data/Rakefile +101 -0
- data/activerecord-turntable.gemspec +47 -0
- data/lib/active_record/turntable.rb +58 -0
- data/lib/active_record/turntable/active_record_ext.rb +26 -0
- data/lib/active_record/turntable/active_record_ext/.gitkeep +0 -0
- data/lib/active_record/turntable/active_record_ext/abstract_adapter.rb +50 -0
- data/lib/active_record/turntable/active_record_ext/clever_load.rb +90 -0
- data/lib/active_record/turntable/active_record_ext/fixtures.rb +131 -0
- data/lib/active_record/turntable/active_record_ext/log_subscriber.rb +64 -0
- data/lib/active_record/turntable/active_record_ext/persistence.rb +95 -0
- data/lib/active_record/turntable/active_record_ext/schema_dumper.rb +107 -0
- data/lib/active_record/turntable/active_record_ext/sequencer.rb +28 -0
- data/lib/active_record/turntable/active_record_ext/transactions.rb +33 -0
- data/lib/active_record/turntable/algorithm.rb +7 -0
- data/lib/active_record/turntable/algorithm/.gitkeep +0 -0
- data/lib/active_record/turntable/algorithm/base.rb +11 -0
- data/lib/active_record/turntable/algorithm/range_algorithm.rb +37 -0
- data/lib/active_record/turntable/algorithm/range_bsearch_algorithm.rb +41 -0
- data/lib/active_record/turntable/base.rb +130 -0
- data/lib/active_record/turntable/cluster.rb +70 -0
- data/lib/active_record/turntable/compatible.rb +19 -0
- data/lib/active_record/turntable/config.rb +24 -0
- data/lib/active_record/turntable/connection_proxy.rb +218 -0
- data/lib/active_record/turntable/connection_proxy/mixable.rb +39 -0
- data/lib/active_record/turntable/error.rb +8 -0
- data/lib/active_record/turntable/helpers.rb +5 -0
- data/lib/active_record/turntable/helpers/test_helper.rb +25 -0
- data/lib/active_record/turntable/master_shard.rb +28 -0
- data/lib/active_record/turntable/migration.rb +132 -0
- data/lib/active_record/turntable/mixer.rb +203 -0
- data/lib/active_record/turntable/mixer/fader.rb +34 -0
- data/lib/active_record/turntable/mixer/fader/calculate_shards_sum_result.rb +15 -0
- data/lib/active_record/turntable/mixer/fader/insert_shards_merge_result.rb +24 -0
- data/lib/active_record/turntable/mixer/fader/select_shards_merge_result.rb +22 -0
- data/lib/active_record/turntable/mixer/fader/specified_shard.rb +12 -0
- data/lib/active_record/turntable/mixer/fader/update_shards_merge_result.rb +17 -0
- data/lib/active_record/turntable/pool_proxy.rb +56 -0
- data/lib/active_record/turntable/rack.rb +5 -0
- data/lib/active_record/turntable/rack/connection_management.rb +18 -0
- data/lib/active_record/turntable/railtie.rb +14 -0
- data/lib/active_record/turntable/railties/databases.rake +205 -0
- data/lib/active_record/turntable/seq_shard.rb +14 -0
- data/lib/active_record/turntable/sequencer.rb +46 -0
- data/lib/active_record/turntable/sequencer/api.rb +36 -0
- data/lib/active_record/turntable/sequencer/mysql.rb +32 -0
- data/lib/active_record/turntable/shard.rb +48 -0
- data/lib/active_record/turntable/sql_tree_patch.rb +199 -0
- data/lib/active_record/turntable/version.rb +5 -0
- data/lib/activerecord-turntable.rb +2 -0
- data/lib/generators/active_record/turntable/install_generator.rb +14 -0
- data/lib/generators/templates/turntable.yml +40 -0
- data/sample_app/.gitignore +16 -0
- data/sample_app/Gemfile +41 -0
- data/sample_app/README.rdoc +261 -0
- data/sample_app/Rakefile +7 -0
- data/sample_app/app/assets/images/rails.png +0 -0
- data/sample_app/app/assets/javascripts/application.js +15 -0
- data/sample_app/app/assets/stylesheets/application.css +13 -0
- data/sample_app/app/controllers/application_controller.rb +3 -0
- data/sample_app/app/helpers/application_helper.rb +2 -0
- data/sample_app/app/mailers/.gitkeep +0 -0
- data/sample_app/app/models/.gitkeep +0 -0
- data/sample_app/app/models/user.rb +4 -0
- data/sample_app/app/views/layouts/application.html.erb +14 -0
- data/sample_app/config.ru +4 -0
- data/sample_app/config/application.rb +65 -0
- data/sample_app/config/boot.rb +6 -0
- data/sample_app/config/database.yml +70 -0
- data/sample_app/config/environment.rb +5 -0
- data/sample_app/config/environments/development.rb +37 -0
- data/sample_app/config/environments/production.rb +67 -0
- data/sample_app/config/environments/test.rb +37 -0
- data/sample_app/config/initializers/backtrace_silencers.rb +7 -0
- data/sample_app/config/initializers/inflections.rb +15 -0
- data/sample_app/config/initializers/mime_types.rb +5 -0
- data/sample_app/config/initializers/secret_token.rb +7 -0
- data/sample_app/config/initializers/session_store.rb +8 -0
- data/sample_app/config/initializers/wrap_parameters.rb +14 -0
- data/sample_app/config/locales/en.yml +5 -0
- data/sample_app/config/routes.rb +58 -0
- data/sample_app/config/turntable.yml +64 -0
- data/sample_app/db/migrate/20120316073058_create_users.rb +11 -0
- data/sample_app/db/seeds.rb +7 -0
- data/sample_app/lib/assets/.gitkeep +0 -0
- data/sample_app/lib/tasks/.gitkeep +0 -0
- data/sample_app/log/.gitkeep +0 -0
- data/sample_app/public/404.html +26 -0
- data/sample_app/public/422.html +26 -0
- data/sample_app/public/500.html +25 -0
- data/sample_app/public/favicon.ico +0 -0
- data/sample_app/public/index.html +241 -0
- data/sample_app/public/robots.txt +5 -0
- data/sample_app/script/rails +6 -0
- data/sample_app/vendor/assets/javascripts/.gitkeep +0 -0
- data/sample_app/vendor/assets/stylesheets/.gitkeep +0 -0
- data/sample_app/vendor/plugins/.gitkeep +0 -0
- data/script/performance/algorithm +32 -0
- data/spec/active_record/turntable/active_record_ext/clever_load_spec.rb +81 -0
- data/spec/active_record/turntable/active_record_ext/persistence_spec.rb +151 -0
- data/spec/active_record/turntable/algorithm/range_algorithm_spec.rb +35 -0
- data/spec/active_record/turntable/algorithm_spec.rb +69 -0
- data/spec/active_record/turntable/base_spec.rb +13 -0
- data/spec/active_record/turntable/cluster_spec.rb +18 -0
- data/spec/active_record/turntable/config_spec.rb +17 -0
- data/spec/active_record/turntable/connection_proxy_spec.rb +186 -0
- data/spec/active_record/turntable/finder_spec.rb +27 -0
- data/spec/active_record/turntable/mixer/fader_spec.rb +4 -0
- data/spec/active_record/turntable/mixer_spec.rb +114 -0
- data/spec/active_record/turntable/shard_spec.rb +21 -0
- data/spec/active_record/turntable_spec.rb +30 -0
- data/spec/config/database.yml +45 -0
- data/spec/config/turntable.yml +17 -0
- data/spec/fabricators/.gitkeep +0 -0
- data/spec/fabricators/turntable_fabricator.rb +14 -0
- data/spec/migrations/.gitkeep +0 -0
- data/spec/migrations/001_create_users.rb +16 -0
- data/spec/migrations/002_create_user_statuses.rb +16 -0
- data/spec/migrations/003_create_cards.rb +14 -0
- data/spec/migrations/004_create_cards_users.rb +15 -0
- data/spec/spec_helper.rb +23 -0
- data/spec/test_models.rb +27 -0
- data/spec/turntable_helper.rb +29 -0
- metadata +367 -0
data/.document
ADDED
data/.gitignore
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
*.gem
|
2
|
+
.bundle
|
3
|
+
Gemfile.lock
|
4
|
+
pkg/*
|
5
|
+
.DS_Store
|
6
|
+
doc
|
7
|
+
.yardoc
|
8
|
+
|
9
|
+
# For TextMate
|
10
|
+
#*.tmproj
|
11
|
+
#tmtags
|
12
|
+
|
13
|
+
# For emacs:
|
14
|
+
*~
|
15
|
+
\#*
|
16
|
+
.\#*
|
17
|
+
|
18
|
+
# For vim:
|
19
|
+
*.swp
|
20
|
+
|
21
|
+
# For redcar:
|
22
|
+
#.redcar
|
23
|
+
|
24
|
+
# For rubinius:
|
25
|
+
#*.rbc
|
data/.rspec
ADDED
data/Gemfile
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
source :rubygems
|
2
|
+
# Add dependencies required to use your gem here.
|
3
|
+
# Example:
|
4
|
+
# gem "activesupport", ">= 2.3.5"
|
5
|
+
|
6
|
+
gem 'activerecord', ">= 3.1.0"
|
7
|
+
gem 'activesupport', ">=3.1.0"
|
8
|
+
gem "sql_tree", "=0.2.0"
|
9
|
+
gem "bsearch", "~>1.5"
|
10
|
+
gem "httpclient"
|
11
|
+
|
12
|
+
# Add dependencies to develop your gem here.
|
13
|
+
# Include everything needed to run rake, tests, features, etc.
|
14
|
+
group :development, :test do
|
15
|
+
gem "rake", "~>0.9.2"
|
16
|
+
gem "rspec"
|
17
|
+
gem "rr"
|
18
|
+
gem "mysql2"
|
19
|
+
gem "fabrication"
|
20
|
+
gem "faker"
|
21
|
+
gem "activerecord-import"
|
22
|
+
gem "pry"
|
23
|
+
gem "guard-rspec"
|
24
|
+
gem "growl"
|
25
|
+
end
|
data/Guardfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2012 Drecom Co.,Ltd.
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,290 @@
|
|
1
|
+
= ActiveRecord::Turntable
|
2
|
+
|
3
|
+
ActiveRecord::Turntable is a database sharding extension for ActiveRecord.
|
4
|
+
|
5
|
+
== Dependencies
|
6
|
+
activerecord(>=3.0.0)
|
7
|
+
|
8
|
+
== Supported Database
|
9
|
+
Currently supports mysql only.
|
10
|
+
|
11
|
+
== Installation
|
12
|
+
|
13
|
+
Add 'activerecord-turntable' to Gemfile:
|
14
|
+
|
15
|
+
gem 'activerecord-turntable', '1.0.0'
|
16
|
+
|
17
|
+
Run a bundle install:
|
18
|
+
|
19
|
+
bundle install
|
20
|
+
|
21
|
+
Run install generator:
|
22
|
+
|
23
|
+
bundle exec rails g active_record:turntable:install
|
24
|
+
|
25
|
+
generator creates Rails.root/config/turntable.yml
|
26
|
+
|
27
|
+
== ActiveRecord::Turntable terms
|
28
|
+
|
29
|
+
*Shard
|
30
|
+
*Cluster - a cluster of shards.
|
31
|
+
*Master - default ActiveRecord::Base's connection
|
32
|
+
*Sequencer - a module that creates global sequence number
|
33
|
+
|
34
|
+
== Example
|
35
|
+
|
36
|
+
=== Example Databases Structure
|
37
|
+
one main database(default ActiveRecord::Base connection) and
|
38
|
+
three user databases sharded by user_id.
|
39
|
+
|
40
|
+
+-------+
|
41
|
+
| App |
|
42
|
+
+-------+
|
43
|
+
|
|
44
|
+
+---------+-----------+---------+---------+
|
45
|
+
| | | | |
|
46
|
+
+--------+ +---------+ +-------+ +-------+ +-------+
|
47
|
+
| Master | |Sequencer| |UserDB1| |UserDB2| |UserDB3|
|
48
|
+
+--------+ +---------+ +-------+ +-------+ +-------+
|
49
|
+
|
50
|
+
=== Example Configuration
|
51
|
+
|
52
|
+
Edit turntable.yml and database.yml. See below example config.
|
53
|
+
|
54
|
+
example turntable.yml:
|
55
|
+
|
56
|
+
development:
|
57
|
+
clusters:
|
58
|
+
user_cluster: # <-- cluster name
|
59
|
+
algorithm: range # <-- only range or range_bsearch sharding is supported currently.
|
60
|
+
shards:
|
61
|
+
- connection: user_shard_1 # <-- shard name
|
62
|
+
less_than: 100 # <-- shard range(like mysql partitioning)
|
63
|
+
- connection: user_shard_2
|
64
|
+
less_than: 200
|
65
|
+
- connection: user_shard_3
|
66
|
+
less_than: 2000000000
|
67
|
+
|
68
|
+
database.yml:
|
69
|
+
connection_spec: &spec
|
70
|
+
adapter: mysql2
|
71
|
+
encoding: utf8
|
72
|
+
reconnect: false
|
73
|
+
pool: 5
|
74
|
+
username: root
|
75
|
+
password: root
|
76
|
+
socket: /tmp/mysql.sock
|
77
|
+
|
78
|
+
development:
|
79
|
+
<<: *spec
|
80
|
+
database: sample_app_development
|
81
|
+
seq: # <-- sequence definition
|
82
|
+
user_seq_1:
|
83
|
+
<<: *spec
|
84
|
+
database: sample_app_user_seq_development
|
85
|
+
shards: # <-- shards definition
|
86
|
+
user_shard_1:
|
87
|
+
<<: *spec
|
88
|
+
database: sample_app_user1_development
|
89
|
+
user_shard_2:
|
90
|
+
<<: *spec
|
91
|
+
database: sample_app_user2_development
|
92
|
+
user_shard_3:
|
93
|
+
<<: *spec
|
94
|
+
database: sample_app_user3_development
|
95
|
+
|
96
|
+
|
97
|
+
=== Migration Example
|
98
|
+
|
99
|
+
Generate a model:
|
100
|
+
|
101
|
+
bundle exec rails g model user name:string
|
102
|
+
|
103
|
+
Edit migration file:
|
104
|
+
|
105
|
+
class CreateUsers < ActiveRecord::Migration
|
106
|
+
clusters :user_cluster # <-- the cluster that executes migration
|
107
|
+
|
108
|
+
def change
|
109
|
+
create_table :users do |t|
|
110
|
+
t.string :name
|
111
|
+
t.timestamps
|
112
|
+
end
|
113
|
+
create_sequence_for(:users)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
then please execute rake tasks:
|
118
|
+
|
119
|
+
bundle exec rake db:create
|
120
|
+
bundle exec rake db:migrate
|
121
|
+
|
122
|
+
Those rake tasks would be executed to shards too.
|
123
|
+
|
124
|
+
=== Model Example
|
125
|
+
add turntable [shard_key_name] to the model class:
|
126
|
+
|
127
|
+
class User < ActiveRecord::Base
|
128
|
+
turntable :user_cluster, :id
|
129
|
+
sequencer
|
130
|
+
has_one :status
|
131
|
+
end
|
132
|
+
|
133
|
+
class Status < ActiveRecord::Base
|
134
|
+
turntable :user_cluster, :user_id
|
135
|
+
sequencer
|
136
|
+
belongs_to :user
|
137
|
+
end
|
138
|
+
|
139
|
+
== Usage
|
140
|
+
|
141
|
+
=== Create
|
142
|
+
> User.create(name: "hoge")
|
143
|
+
(0.0ms) [Shard: user_seq_1] BEGIN
|
144
|
+
(0.3ms) [Shard: user_seq_1] UPDATE `users_id_seq` SET id=LAST_INSERT_ID(id+1)
|
145
|
+
(0.8ms) [Shard: user_seq_1] COMMIT
|
146
|
+
(0.1ms) [Shard: user_seq_1] SELECT LAST_INSERT_ID()
|
147
|
+
(0.1ms) [Shard: user_shard_1] BEGIN
|
148
|
+
[ActiveRecord::Turntable] Sending method: insert, sql: #<Arel::InsertManager:0x007f8503685b48>, shards: ["user_shard_1"]
|
149
|
+
SQL (0.8ms) [Shard: user_shard_1] INSERT INTO `users` (`created_at`, `id`, `name`, `updated_at`) VALUES ('2012-04-10 03:59:42', 2, 'hoge', '2012-04-10 03:59:42')
|
150
|
+
(0.4ms) [Shard: user_shard_1] COMMIT
|
151
|
+
=> #<User id: 2, name: "hoge", created_at: "2012-04-10 03:59:42", updated_at: "2012-04-10 03:59:42">
|
152
|
+
|
153
|
+
=== Retrieve
|
154
|
+
> user = User.find(2)
|
155
|
+
[ActiveRecord::Turntable] Sending method: select_all, sql: #<Arel::SelectManager:0x007f850466e668>, shards: ["user_shard_1"]
|
156
|
+
User Load (0.3ms) [Shard: user_shard_1] SELECT `users`.* FROM `users` WHERE `users`.`id` = 2 LIMIT 1
|
157
|
+
=> #<User id: 2, name: "hoge", created_at: "2012-04-10 03:59:42", updated_at: "2012-04-10 03:59:42">
|
158
|
+
|
159
|
+
=== Update
|
160
|
+
> user.update_attributes(name: "hogefoo")
|
161
|
+
(0.1ms) [Shard: user_shard_1] BEGIN
|
162
|
+
[ActiveRecord::Turntable] Sending method: update, sql: UPDATE `users` SET `name` = 'hogefoo', `updated_at` = '2012-04-10 04:07:52' WHERE `users`.`id` = 2, shards: ["user_shard_1"]
|
163
|
+
(0.3ms) [Shard: user_shard_1] UPDATE `users` SET `name` = 'hogefoo', `updated_at` = '2012-04-10 04:07:52' WHERE `users`.`id` = 2
|
164
|
+
(0.8ms) [Shard: user_shard_1] COMMIT
|
165
|
+
=> true
|
166
|
+
|
167
|
+
=== Delete
|
168
|
+
> user.destroy
|
169
|
+
(0.2ms) [Shard: user_shard_1] BEGIN
|
170
|
+
[ActiveRecord::Turntable] Sending method: delete, sql: #<Arel::DeleteManager:0x007f8503677ea8>, shards: ["user_shard_1"]
|
171
|
+
SQL (0.3ms) [Shard: user_shard_1] DELETE FROM `users` WHERE `users`.`id` = 2
|
172
|
+
(1.7ms) [Shard: user_shard_1] COMMIT
|
173
|
+
=> #<User id: 2, name: "hogefoo", created_at: "2012-04-10 03:59:42", updated_at: "2012-04-10 04:07:52">
|
174
|
+
|
175
|
+
=== Count
|
176
|
+
|
177
|
+
> User.count
|
178
|
+
[ActiveRecord::Turntable] Sending method: select_value, sql: #<Arel::SelectManager:0x007f9e82ccebb0>, shards: ["user_shard_1", "user_shard_2", "user_shard_3"]
|
179
|
+
(0.8ms) [Shard: user_shard_1] SELECT COUNT(*) FROM `users`
|
180
|
+
(0.3ms) [Shard: user_shard_2] SELECT COUNT(*) FROM `users`
|
181
|
+
(0.2ms) [Shard: user_shard_3] SELECT COUNT(*) FROM `users`
|
182
|
+
=> 1
|
183
|
+
|
184
|
+
=== Sequencer
|
185
|
+
Sequencer provides generating global IDs.
|
186
|
+
|
187
|
+
Add below to the migration:
|
188
|
+
|
189
|
+
create_sequence_for(:users) # <-- this line creates sequence table
|
190
|
+
|
191
|
+
This will creates sequence table.
|
192
|
+
|
193
|
+
Next, add sequencer to the model:
|
194
|
+
|
195
|
+
class User < ActiveRecord::Base
|
196
|
+
turntable :id
|
197
|
+
sequencer # <-- this line enables sequencer module
|
198
|
+
has_one :status
|
199
|
+
end
|
200
|
+
|
201
|
+
|
202
|
+
=== Transaction
|
203
|
+
> user = User.find(2)
|
204
|
+
> user3 = User.create(name: "hoge3")
|
205
|
+
> User.shards_transaction([user, user3]) do
|
206
|
+
> user.name = "hogehoge"
|
207
|
+
> user3.name = "hogehoge3"
|
208
|
+
> user.save!
|
209
|
+
> user3.save!
|
210
|
+
> end
|
211
|
+
|
212
|
+
=== Send query to a specific shard.
|
213
|
+
use with_shard method:
|
214
|
+
|
215
|
+
AR::Base.connection.with_shard(shard1) do
|
216
|
+
# something queries to shard1
|
217
|
+
end
|
218
|
+
|
219
|
+
To access shard objects, use below:
|
220
|
+
* AR::Base.connection.shards # \\{shard_name => shard_obj,....}
|
221
|
+
* AR::Base#turntable_shard
|
222
|
+
* AR::Base.connection.select_shard(shard_key_value) #=> shard
|
223
|
+
|
224
|
+
=== Send query to all shards
|
225
|
+
use with_all method:
|
226
|
+
|
227
|
+
User.connection.with_all do
|
228
|
+
User.order("created_at DESC").limit(3).all
|
229
|
+
end
|
230
|
+
|
231
|
+
|
232
|
+
=== Migration
|
233
|
+
If you specify cluster or shard, migration will be executed to the cluster(or shard) and master database.
|
234
|
+
|
235
|
+
to specify cluster:
|
236
|
+
|
237
|
+
class CreateUsers < ActiveRecord::Migration
|
238
|
+
clusters :user_cluster
|
239
|
+
....
|
240
|
+
end
|
241
|
+
|
242
|
+
to specify shard:
|
243
|
+
|
244
|
+
class CreateUsers < ActiveRecord::Migration
|
245
|
+
shards :user_shard_01
|
246
|
+
....
|
247
|
+
end
|
248
|
+
|
249
|
+
if you would like to execute a migration to all databases in the environments, use :all symbol:
|
250
|
+
|
251
|
+
class CreateUsers < ActiveRecord::Migration
|
252
|
+
clusters :all
|
253
|
+
....
|
254
|
+
end
|
255
|
+
|
256
|
+
== Connection Management
|
257
|
+
Rails's ConnectionManagement middleware keeps ActiveRecord's connection during the process is alive, but Turntable keeps more connections.
|
258
|
+
This may cause flooding max connections on your database. So, we made a middleware that disconnects on each request.
|
259
|
+
To use turntable's ConnectionManagement middleware, add below line to your initializer.
|
260
|
+
|
261
|
+
app.middleware.swap ActiveRecord::ConnectionAdapters::ConnectionManagement, ActiveRecord::Turntable::Rack::ConnectionManagement
|
262
|
+
|
263
|
+
== Inability
|
264
|
+
* Queries includes "ORDER BY", "GROUP BY" and "LIMIT" clauses cannot be distributed.
|
265
|
+
* "has many through" and "habtm" relationships causes wrong results. ex) User-Friend-User relation
|
266
|
+
|
267
|
+
== Thanks to
|
268
|
+
ConnectionProxy, Distributed Migration implementation is inspired by Octopus and DataFabric.
|
269
|
+
|
270
|
+
== LICENSE
|
271
|
+
Copyright (c) 2012 Drecom Co.,Ltd.
|
272
|
+
|
273
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
274
|
+
a copy of this software and associated documentation files (the
|
275
|
+
"Software"), to deal in the Software without restriction, including
|
276
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
277
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
278
|
+
permit persons to whom the Software is furnished to do so, subject to
|
279
|
+
the following conditions:
|
280
|
+
|
281
|
+
The above copyright notice and this permission notice shall be
|
282
|
+
included in all copies or substantial portions of the Software.
|
283
|
+
|
284
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
285
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
286
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
287
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
288
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
289
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
290
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
ADDED
@@ -0,0 +1,101 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
2
|
+
require 'rubygems'
|
3
|
+
|
4
|
+
require 'rspec/core'
|
5
|
+
require 'rspec/core/rake_task'
|
6
|
+
RSpec::Core::RakeTask.new(:spec) do |spec|
|
7
|
+
spec.pattern = FileList['spec/**/*_spec.rb']
|
8
|
+
end
|
9
|
+
|
10
|
+
namespace :turntable do
|
11
|
+
namespace :db do
|
12
|
+
task :rails_env do
|
13
|
+
unless defined? RAILS_ENV
|
14
|
+
RAILS_ENV = ENV['RAILS_ENV'] ||= 'test'
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
task :load_config => :rails_env do
|
19
|
+
require 'active_record'
|
20
|
+
ActiveRecord::Base.configurations = YAML.load_file(File.join(File.dirname(__FILE__), 'spec/config/database.yml'))
|
21
|
+
end
|
22
|
+
|
23
|
+
desc "create turntable test database"
|
24
|
+
task :create => :load_config do
|
25
|
+
database_configs = [ActiveRecord::Base.configurations[RAILS_ENV]] + ActiveRecord::Base.configurations[RAILS_ENV]["shards"].values + ActiveRecord::Base.configurations[RAILS_ENV]["seq"].values
|
26
|
+
database_configs.each do |dbconf|
|
27
|
+
%x{ echo "CREATE DATABASE #{dbconf["database"]}" | mysql -u #{dbconf["username"]} -p#{dbconf["password"]} -h #{dbconf["host"]} }
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
desc "migrate turntable test tables"
|
32
|
+
task :migrate => :load_config do
|
33
|
+
ActiveRecord::Base.establish_connection RAILS_ENV
|
34
|
+
require 'active_record/turntable'
|
35
|
+
ActiveRecord::Base.send(:include, ActiveRecord::Turntable)
|
36
|
+
ActiveRecord::ConnectionAdapters::SchemaStatements.send(:include, Turntable::Migration::SchemaStatementsExt)
|
37
|
+
database_configs = [ActiveRecord::Base.configurations[RAILS_ENV]] + ActiveRecord::Base.configurations[RAILS_ENV]["shards"].values + ActiveRecord::Base.configurations[RAILS_ENV]["seq"].values
|
38
|
+
|
39
|
+
database_configs.each do |dbconf|
|
40
|
+
ActiveRecord::Base.establish_connection dbconf
|
41
|
+
|
42
|
+
ActiveRecord::Base.connection.create_table :users do |t|
|
43
|
+
t.string :nickname
|
44
|
+
t.string :thumbnail_url
|
45
|
+
t.datetime :joined_at
|
46
|
+
t.datetime :deleted_at
|
47
|
+
t.timestamps
|
48
|
+
end
|
49
|
+
ActiveRecord::Base.connection.create_sequence_for :users
|
50
|
+
|
51
|
+
ActiveRecord::Base.connection.create_table :user_statuses do |t|
|
52
|
+
t.belongs_to :user, :null => false
|
53
|
+
t.integer :hp, :null => false, :default => 0
|
54
|
+
t.integer :mp, :null => false, :default => 0
|
55
|
+
t.datetime :deleted_at, :default => nil
|
56
|
+
t.timestamps
|
57
|
+
end
|
58
|
+
ActiveRecord::Base.connection.create_sequence_for :user_statuses
|
59
|
+
|
60
|
+
ActiveRecord::Base.connection.create_table :cards do |t|
|
61
|
+
t.string :name, :null => false
|
62
|
+
t.integer :hp, :null => false, :default => 0
|
63
|
+
t.integer :mp, :null => false, :default => 0
|
64
|
+
t.timestamps
|
65
|
+
end
|
66
|
+
ActiveRecord::Base.connection.create_table :archived_cards do |t|
|
67
|
+
t.string :name, :null => false
|
68
|
+
t.integer :hp, :null => false, :default => 0
|
69
|
+
t.integer :mp, :null => false, :default => 0
|
70
|
+
t.timestamps
|
71
|
+
t.datetime :deleted_at, :default => nil
|
72
|
+
end
|
73
|
+
|
74
|
+
ActiveRecord::Base.connection.create_table :cards_users do |t|
|
75
|
+
t.belongs_to :card, :null => false
|
76
|
+
t.belongs_to :user, :null => false
|
77
|
+
t.timestamps
|
78
|
+
end
|
79
|
+
ActiveRecord::Base.connection.create_sequence_for :cards_users
|
80
|
+
|
81
|
+
ActiveRecord::Base.connection.create_table :archived_cards_users do |t|
|
82
|
+
t.belongs_to :card, :null => false
|
83
|
+
t.belongs_to :user, :null => false
|
84
|
+
t.timestamps
|
85
|
+
t.datetime :deleted_at, :default => nil
|
86
|
+
end
|
87
|
+
ActiveRecord::Base.connection.create_sequence_for :archived_cards_users
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
desc "drop turntable test database"
|
92
|
+
task :drop => :load_config do
|
93
|
+
database_configs = [ActiveRecord::Base.configurations[RAILS_ENV]] + ActiveRecord::Base.configurations[RAILS_ENV]["shards"].values + ActiveRecord::Base.configurations[RAILS_ENV]["seq"].values
|
94
|
+
database_configs.each do |dbconf|
|
95
|
+
%x{ echo "DROP DATABASE #{dbconf["database"]}" | mysql -u #{dbconf["username"]} -p#{dbconf["password"]} -h #{dbconf["host"]} }
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
task :reset => ["turntable:db:drop", "turntable:db:create", "turntable:db:migrate"]
|
100
|
+
end
|
101
|
+
end
|