sengiri 0.0.2 → 0.1.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/README.md +39 -10
- data/lib/sengiri.rb +1 -1
- data/lib/sengiri/model/base.rb +81 -5
- data/lib/sengiri/railties/sharding.rake +14 -2
- data/lib/sengiri/version.rb +1 -1
- metadata +17 -19
- data/db/sengiri_shards_1.sqlite3 +0 -0
- data/db/sengiri_shards_2.sqlite3 +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 67662e531d8b2b6162bc5c40345d2a2c8483cb86
|
4
|
+
data.tar.gz: 33fd768534533e6fee349213b71cac79dd3aa523
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: af81bf63aab412b0ead03aa961f4c3885013ac2b3a4d65dc43c04832c2d8b12e7ea5fe16dbee40a12f53ed141f78a688e0d549bbaf9f25c36a7460b7fd2d42e5
|
7
|
+
data.tar.gz: 25de11297f6a2e58bf254363b6d36288f3e58dd096d8eff47522934273234fbec666d165b708a3568a5663aced39a3264ca8018d14d53a7956db130f7864c32d
|
data/README.md
CHANGED
@@ -4,10 +4,13 @@ Flexible sharding access for Ruby on Rails with ActiveRecord
|
|
4
4
|
|
5
5
|
## Sharding model generator
|
6
6
|
|
7
|
+
```
|
7
8
|
rails g sengiri:model mygroup user name:string
|
9
|
+
```
|
8
10
|
|
9
11
|
## database.yml
|
10
12
|
|
13
|
+
```ruby
|
11
14
|
mysql: &mysql
|
12
15
|
adapter: mysql2
|
13
16
|
encoding: utf8
|
@@ -17,60 +20,86 @@ Flexible sharding access for Ruby on Rails with ActiveRecord
|
|
17
20
|
password:
|
18
21
|
host: localhost
|
19
22
|
|
20
|
-
|
23
|
+
mygroup_shard_first: # define shard as 'first'
|
21
24
|
<<: *mysql
|
22
25
|
database: mygroup_1
|
23
26
|
host: hosta
|
24
|
-
|
27
|
+
mygroup_shard_second: # define shard as 'second'
|
25
28
|
<<: *mysql
|
26
29
|
database: mygroup_2
|
27
30
|
host: hostb
|
28
|
-
|
31
|
+
mygroup_shard_third: # define shard as 'third'
|
29
32
|
<<: *mysql
|
30
33
|
database: mygroup_3
|
31
34
|
host: hostc
|
32
35
|
.
|
33
36
|
.
|
34
37
|
.
|
38
|
+
```
|
35
39
|
|
36
40
|
## Sharding migration
|
37
41
|
|
42
|
+
ActiveRecord task is available on every shard.
|
43
|
+
|
44
|
+
```ruby
|
38
45
|
rake sengiri:mygroup:db:create
|
39
46
|
rake sengiri:mygroup:db:migrate
|
40
|
-
|
47
|
+
rake sengiri:mygroup:db:rollback
|
48
|
+
...
|
49
|
+
```
|
41
50
|
|
42
51
|
## Sharding access
|
43
52
|
|
53
|
+
On a shard, ActiveRecord class is given.
|
54
|
+
|
55
|
+
```ruby
|
44
56
|
User.shard('second') do |shard|
|
45
|
-
shard.all.limit(10)
|
57
|
+
shard.all.limit(10) # query on db 'mygroup_2'
|
58
|
+
shard.find(1) # query on db 'mygroup_2'
|
46
59
|
end
|
60
|
+
```
|
47
61
|
|
62
|
+
Every shard.
|
48
63
|
|
64
|
+
```ruby
|
49
65
|
User.shards do |shard|
|
50
|
-
shard.all.limit(10) # query on all
|
66
|
+
shard.all.limit(10) # query on all shards 'mygroup_1', 'mygroup_2', 'mygroup_3'
|
51
67
|
end
|
68
|
+
```
|
69
|
+
|
70
|
+
All records from all shards.
|
71
|
+
|
72
|
+
```ruby
|
73
|
+
all_records = User.all.broadcast
|
74
|
+
```
|
52
75
|
|
53
76
|
## Transaction
|
54
77
|
|
78
|
+
In a shard transaction.
|
79
|
+
|
80
|
+
```ruby
|
55
81
|
User.shard('second').transaction do
|
56
82
|
# in mygroup_2 transaction
|
57
83
|
end
|
84
|
+
```
|
58
85
|
|
86
|
+
In all shards transaction.
|
59
87
|
|
88
|
+
```ruby
|
60
89
|
User.transaction do
|
61
90
|
# in mygroup_1, mygroup_2 and mygroup_3 transaction
|
62
91
|
end
|
92
|
+
```
|
63
93
|
|
94
|
+
This is same as below
|
64
95
|
|
65
|
-
|
66
|
-
|
67
|
-
|
96
|
+
```ruby
|
68
97
|
User.shard('first').transaction do
|
69
98
|
User.shard('second').transaction do
|
70
99
|
User.shard('third').transaction do
|
71
100
|
end
|
72
101
|
end
|
73
102
|
end
|
74
|
-
|
103
|
+
```
|
75
104
|
|
76
105
|
This project rocks and uses MIT-LICENSE.
|
data/lib/sengiri.rb
CHANGED
data/lib/sengiri/model/base.rb
CHANGED
@@ -17,6 +17,11 @@ module Sengiri
|
|
17
17
|
self.class.instance_variable_get :@shard_name
|
18
18
|
end
|
19
19
|
|
20
|
+
def narrowcast(association)
|
21
|
+
foreign_key = self.class.table_name.singularize.foreign_key
|
22
|
+
association.to_s.classify.constantize.shard(shard_name).where(foreign_key => id)
|
23
|
+
end
|
24
|
+
|
20
25
|
class << self
|
21
26
|
def shard_name ; @shard_name end
|
22
27
|
def sharding_group_name; @sharding_group_name end
|
@@ -26,17 +31,23 @@ module Sengiri
|
|
26
31
|
[]
|
27
32
|
end
|
28
33
|
|
29
|
-
def sharding_group(name, confs
|
34
|
+
def sharding_group(name, confs: nil, suffix: nil)
|
30
35
|
@dbconfs = confs if confs
|
31
36
|
@sharding_group_name = name
|
32
37
|
@shard_class_hash = {}
|
38
|
+
@sharding_database_suffix = if suffix.present? then "_#{suffix}" else nil end
|
33
39
|
first = true
|
40
|
+
raise "Databases are not found" if shard_names.blank?
|
34
41
|
shard_names.each do |s|
|
35
42
|
klass = Class.new(self)
|
36
|
-
|
43
|
+
module_name = self.name.deconstantize
|
44
|
+
module_name = "Object" if module_name.blank?
|
45
|
+
module_name.constantize.const_set self.name.demodulize + s, klass
|
37
46
|
klass.instance_variable_set :@shard_name, s
|
38
47
|
klass.instance_variable_set :@dbconfs, dbconfs
|
39
48
|
klass.instance_variable_set :@sharding_group_name, name
|
49
|
+
klass.instance_variable_set :@sharding_database_suffix, @sharding_database_suffix
|
50
|
+
|
40
51
|
#
|
41
52
|
# first shard shares connection with base class
|
42
53
|
#
|
@@ -55,7 +66,11 @@ module Sengiri
|
|
55
66
|
|
56
67
|
def dbconfs
|
57
68
|
if defined? Rails
|
58
|
-
@dbconfs ||= Rails.application.config.database_configuration.select {|name|
|
69
|
+
@dbconfs ||= Rails.application.config.database_configuration.select {|name|
|
70
|
+
/^#{@sharding_group_name}/ =~ name
|
71
|
+
}.select {|name|
|
72
|
+
/#{env}#{@sharding_database_suffix}$/ =~ name
|
73
|
+
}
|
59
74
|
|
60
75
|
end
|
61
76
|
@dbconfs
|
@@ -63,7 +78,7 @@ module Sengiri
|
|
63
78
|
|
64
79
|
def shard_names
|
65
80
|
@shard_names ||= dbconfs.map do |k,v|
|
66
|
-
k.gsub("#{@sharding_group_name}
|
81
|
+
k.gsub("#{@sharding_group_name}_shard_", '').gsub(/_#{env}#{@sharding_database_suffix}$/, '')
|
67
82
|
end
|
68
83
|
@shard_names
|
69
84
|
end
|
@@ -98,9 +113,70 @@ module Sengiri
|
|
98
113
|
end
|
99
114
|
end
|
100
115
|
|
116
|
+
def env
|
117
|
+
ENV["SENGIRI_ENV"] ||= ENV["RAILS_ENV"] || 'development'
|
118
|
+
end
|
119
|
+
|
101
120
|
def establish_shard_connection(name)
|
102
|
-
establish_connection dbconfs["#{@sharding_group_name}
|
121
|
+
establish_connection dbconfs["#{@sharding_group_name}_shard_#{name}_#{env}#{@sharding_database_suffix}"]
|
122
|
+
end
|
123
|
+
|
124
|
+
def has_many_with_sharding(name, scope = nil, options = {}, &extension)
|
125
|
+
class_name, scope, options = *prepare_association(name, scope, options)
|
126
|
+
shard_classes.each do |klass|
|
127
|
+
new_options = options.merge({
|
128
|
+
class_name: class_name.to_s.classify + klass.shard_name,
|
129
|
+
foreign_key: options[:foreign_key] || self.to_s.foreign_key
|
130
|
+
})
|
131
|
+
klass.has_many_without_sharding(name, scope, new_options, extension) if block_given?
|
132
|
+
klass.has_many_without_sharding(name, scope, new_options) unless block_given?
|
133
|
+
end
|
134
|
+
has_many_without_sharding(name, scope, options, extension) if block_given?
|
135
|
+
has_many_without_sharding(name, scope, options) unless block_given?
|
136
|
+
end
|
137
|
+
|
138
|
+
def has_one_with_sharding(name, scope = nil, options = {})
|
139
|
+
class_name, scope, options = *prepare_association(name, scope, options)
|
140
|
+
shard_classes.each do |klass|
|
141
|
+
new_options = options.merge({
|
142
|
+
class_name: class_name.to_s.classify + klass.shard_name,
|
143
|
+
foreign_key: options[:foreign_key] || self.to_s.foreign_key
|
144
|
+
})
|
145
|
+
klass.has_one_without_sharding(name, scope, new_options)
|
146
|
+
end
|
147
|
+
has_one_without_sharding(name, scope, options)
|
103
148
|
end
|
149
|
+
|
150
|
+
def belongs_to_with_sharding(name, scope = nil, options = {})
|
151
|
+
class_name, scope, options = *prepare_association(name, scope, options)
|
152
|
+
shard_classes.each do |klass|
|
153
|
+
new_options = options.merge({
|
154
|
+
class_name: class_name.to_s.classify + klass.shard_name,
|
155
|
+
foreign_key: options[:foreign_key] || name.to_s.foreign_key
|
156
|
+
})
|
157
|
+
klass.belongs_to_without_sharding(name, scope, new_options)
|
158
|
+
end
|
159
|
+
belongs_to_without_sharding(name, scope, options)
|
160
|
+
end
|
161
|
+
|
162
|
+
def constantize(name)
|
163
|
+
name.to_s.singularize.classify.constantize
|
164
|
+
end
|
165
|
+
|
166
|
+
def prepare_association(name, scope, options)
|
167
|
+
if scope.is_a?(Hash)
|
168
|
+
options = scope
|
169
|
+
scope = nil
|
170
|
+
end
|
171
|
+
class_name = options[:class_name] || name
|
172
|
+
constantize(class_name)
|
173
|
+
[class_name, scope, options]
|
174
|
+
end
|
175
|
+
|
176
|
+
alias_method_chain :has_many, :sharding
|
177
|
+
alias_method_chain :has_one, :sharding
|
178
|
+
alias_method_chain :belongs_to, :sharding
|
179
|
+
|
104
180
|
end
|
105
181
|
end
|
106
182
|
end
|
@@ -1,6 +1,12 @@
|
|
1
1
|
require 'active_record'
|
2
2
|
|
3
3
|
shard = ENV['SHARD']
|
4
|
+
rails_env = ENV['RAILS_ENV']
|
5
|
+
if rails_env
|
6
|
+
rails_env_list = [rails_env]
|
7
|
+
else
|
8
|
+
rails_env_list = ['development', 'test']
|
9
|
+
end
|
4
10
|
|
5
11
|
namespace :sengiri do
|
6
12
|
db_ns = namespace :db do
|
@@ -12,9 +18,15 @@ namespace :sengiri do
|
|
12
18
|
|
13
19
|
namespace :db do
|
14
20
|
|
15
|
-
dbconfs = Rails.application.config.database_configuration.select {|name|
|
21
|
+
dbconfs = Rails.application.config.database_configuration.select {|name|
|
22
|
+
/^#{shard}/ =~ name
|
23
|
+
}.select {|name|
|
24
|
+
rails_env_list.select {|env|
|
25
|
+
/_#{env}$/ =~ name
|
26
|
+
}.present?
|
27
|
+
}
|
16
28
|
switch_db_config = lambda do
|
17
|
-
puts "now on '#{shard}'
|
29
|
+
puts "now on '#{shard}' shard."
|
18
30
|
|
19
31
|
shard_group_dir = "db/sengiri/#{shard}"
|
20
32
|
ActiveRecord::Base.configurations = dbconfs
|
data/lib/sengiri/version.rb
CHANGED
metadata
CHANGED
@@ -1,55 +1,55 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sengiri
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- mewlist
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2015-07-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - ~>
|
17
|
+
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 4.1
|
19
|
+
version: 4.2.1
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - ~>
|
24
|
+
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 4.1
|
26
|
+
version: 4.2.1
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: sqlite3
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- -
|
31
|
+
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: '0'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- -
|
38
|
+
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: rspec
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- -
|
45
|
+
- - ">="
|
46
46
|
- !ruby/object:Gem::Version
|
47
47
|
version: '0'
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
|
-
- -
|
52
|
+
- - ">="
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '0'
|
55
55
|
description: Database sharding for Ruby on Rails. Supports sharding migration, access
|
@@ -60,8 +60,10 @@ executables: []
|
|
60
60
|
extensions: []
|
61
61
|
extra_rdoc_files: []
|
62
62
|
files:
|
63
|
-
-
|
64
|
-
-
|
63
|
+
- MIT-LICENSE
|
64
|
+
- README.md
|
65
|
+
- Rakefile
|
66
|
+
- lib/sengiri.rb
|
65
67
|
- lib/sengiri/generators/migration_generator.rb
|
66
68
|
- lib/sengiri/generators/model_generator.rb
|
67
69
|
- lib/sengiri/generators/sharding_generator.rb
|
@@ -73,11 +75,7 @@ files:
|
|
73
75
|
- lib/sengiri/railtie.rb
|
74
76
|
- lib/sengiri/railties/sharding.rake
|
75
77
|
- lib/sengiri/version.rb
|
76
|
-
- lib/sengiri.rb
|
77
78
|
- lib/tasks/sengiri.rake
|
78
|
-
- MIT-LICENSE
|
79
|
-
- Rakefile
|
80
|
-
- README.md
|
81
79
|
homepage: https://github.com/mewlist
|
82
80
|
licenses: []
|
83
81
|
metadata: {}
|
@@ -87,17 +85,17 @@ require_paths:
|
|
87
85
|
- lib
|
88
86
|
required_ruby_version: !ruby/object:Gem::Requirement
|
89
87
|
requirements:
|
90
|
-
- -
|
88
|
+
- - ">="
|
91
89
|
- !ruby/object:Gem::Version
|
92
90
|
version: '0'
|
93
91
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
94
92
|
requirements:
|
95
|
-
- -
|
93
|
+
- - ">="
|
96
94
|
- !ruby/object:Gem::Version
|
97
95
|
version: '0'
|
98
96
|
requirements: []
|
99
97
|
rubyforge_project:
|
100
|
-
rubygems_version: 2.
|
98
|
+
rubygems_version: 2.4.5
|
101
99
|
signing_key:
|
102
100
|
specification_version: 4
|
103
101
|
summary: Database sharding for Ruby on Rails
|
data/db/sengiri_shards_1.sqlite3
DELETED
Binary file
|
data/db/sengiri_shards_2.sqlite3
DELETED
Binary file
|