tako 0.2.2 → 0.3.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 +10 -0
- data/bin/console +14 -2
- data/lib/tako/active_record_ext/association.rb +18 -0
- data/lib/tako/active_record_ext/association_relation.rb +39 -0
- data/lib/tako/active_record_ext/base.rb +61 -0
- data/lib/tako/active_record_ext/collection_association.rb +33 -0
- data/lib/tako/active_record_ext/collection_proxy.rb +41 -0
- data/lib/tako/active_record_ext/connection_handling.rb +18 -0
- data/lib/tako/active_record_ext/log_subscriber.rb +22 -0
- data/lib/tako/active_record_ext/sharded_methods.rb +19 -0
- data/lib/tako/active_record_ext/singular_association.rb +18 -0
- data/lib/tako/active_record_ext.rb +0 -28
- data/lib/tako/proxy.rb +3 -5
- data/lib/tako/proxy_stack.rb +3 -3
- data/lib/tako/query_chain.rb +24 -8
- data/lib/tako/repository.rb +2 -2
- data/lib/tako/version.rb +1 -1
- data/lib/tako.rb +10 -9
- data/tako.gemspec +1 -0
- metadata +25 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9861d9ec9b928c4ed0bbe68ada132a9335fd6077
|
4
|
+
data.tar.gz: 78351b4438784d0b40bf5a4e3b826ef5c60624eb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cbb4e884798a8dbb5d2de722ffcc196c048a82df49ce45b56c9530c878e492489bae0f8e5d3a71f577f765c8c41ff87fb90da93877b7efdc7237075838f66acc
|
7
|
+
data.tar.gz: 29f14c874dbf1d539dfbdfc263121406daee76fd53f3ca44a9c06eeec724cadcea11adfee04fde6aab5b1512d71f53164340adac25a96cc802749fe7efa7fbb9
|
data/README.md
CHANGED
@@ -53,6 +53,16 @@ ModelA.shard(:slave_two) do
|
|
53
53
|
end
|
54
54
|
```
|
55
55
|
|
56
|
+
## Vertical Sharding
|
57
|
+
|
58
|
+
Add `force_shard` definition to your Vertical-Sharding model
|
59
|
+
|
60
|
+
```ruby
|
61
|
+
class YourModel < ActiveRecord::Base
|
62
|
+
force_shard :shard01
|
63
|
+
end
|
64
|
+
```
|
65
|
+
|
56
66
|
## Development
|
57
67
|
|
58
68
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
data/bin/console
CHANGED
@@ -10,5 +10,17 @@ require "tako"
|
|
10
10
|
# require "pry"
|
11
11
|
# Pry.start
|
12
12
|
|
13
|
-
require "
|
14
|
-
|
13
|
+
require "pry"
|
14
|
+
|
15
|
+
require File.join(File.dirname(__FILE__), "../../", "spec/support/model_class")
|
16
|
+
|
17
|
+
ENV["RAILS_ENV"] ||= 'test'
|
18
|
+
ENV['TAKO_CONFIG_FILE_PATH'] ||= File.join(File.dirname(__FILE__), "../", "spec/config/shards.yml")
|
19
|
+
|
20
|
+
database_yml_path = File.join(File.dirname(__FILE__), "../", "spec/config/database.yml")
|
21
|
+
database_yml = YAML.load(ERB.new(File.read(database_yml_path)).result).with_indifferent_access[:test]
|
22
|
+
Tako.load_connections_from_yaml
|
23
|
+
ActiveRecord::Base.establish_connection(database_yml)
|
24
|
+
|
25
|
+
opts = Pry::CLI.parse_options
|
26
|
+
Pry::CLI.start(opts)
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Tako
|
2
|
+
module ActiveRecordExt
|
3
|
+
module Association
|
4
|
+
def current_shard
|
5
|
+
owner.current_shard
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.included(mod)
|
9
|
+
mod.extend(ShardedMethods)
|
10
|
+
mod.sharded_methods :target_scope
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
ActiveRecord::Associations::Association.class_eval do
|
17
|
+
include Tako::ActiveRecordExt::Association
|
18
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Tako
|
2
|
+
module ActiveRecordExt
|
3
|
+
module AssociationRelation
|
4
|
+
def self.included(mod)
|
5
|
+
mod.extend(ShardedMethods)
|
6
|
+
mod.sharded_methods :any?,
|
7
|
+
:build,
|
8
|
+
:count,
|
9
|
+
:create,
|
10
|
+
:create!,
|
11
|
+
:delete,
|
12
|
+
:delete_all,
|
13
|
+
:destroy,
|
14
|
+
:destroy_all,
|
15
|
+
:empty?,
|
16
|
+
:find,
|
17
|
+
:first,
|
18
|
+
:include?,
|
19
|
+
:last,
|
20
|
+
:length,
|
21
|
+
:many?,
|
22
|
+
:pluck,
|
23
|
+
:select,
|
24
|
+
:size,
|
25
|
+
:sum,
|
26
|
+
:to_a,
|
27
|
+
:uniq
|
28
|
+
end
|
29
|
+
|
30
|
+
def current_shard
|
31
|
+
@association.owner.current_shard
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
ActiveRecord::AssociationRelation.class_eval do
|
38
|
+
include Tako::ActiveRecordExt::AssociationRelation
|
39
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
module Tako
|
2
|
+
module ActiveRecordExt
|
3
|
+
module Base
|
4
|
+
module ClassMethods
|
5
|
+
def shard(shard_name)
|
6
|
+
if block_given?
|
7
|
+
Tako.shard(shard_name) do
|
8
|
+
yield
|
9
|
+
end
|
10
|
+
else
|
11
|
+
Tako::QueryChain.new(
|
12
|
+
Tako::Repository.create_proxy(shard_name),
|
13
|
+
self
|
14
|
+
)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def force_shard(shard_name)
|
19
|
+
@force_shard = shard_name
|
20
|
+
end
|
21
|
+
|
22
|
+
def force_shard?
|
23
|
+
@force_shard.present?
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
module InstanceMethods
|
28
|
+
attr_accessor :current_shard
|
29
|
+
|
30
|
+
def self.included(mod)
|
31
|
+
mod.extend(ShardedMethods)
|
32
|
+
mod.sharded_methods :update_attribute,
|
33
|
+
:update_attributes,
|
34
|
+
:update_attributes!,
|
35
|
+
:reload,
|
36
|
+
:delete,
|
37
|
+
:destroy,
|
38
|
+
:touch,
|
39
|
+
:update_column,
|
40
|
+
:save,
|
41
|
+
:save!
|
42
|
+
|
43
|
+
mod.class_eval do
|
44
|
+
after_initialize :set_current_shard
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
def set_current_shard
|
49
|
+
@current_shard = ::Tako::ProxyStack.top.try(:shard_name)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
ActiveRecord::Base.class_eval do
|
59
|
+
extend Tako::ActiveRecordExt::Base::ClassMethods
|
60
|
+
include Tako::ActiveRecordExt::Base::InstanceMethods
|
61
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Tako
|
2
|
+
module ActiveRecordExt
|
3
|
+
module CollectionAssociation
|
4
|
+
def self.included(mod)
|
5
|
+
mod.extend(ShardedMethods)
|
6
|
+
mod.sharded_methods :reader,
|
7
|
+
:writer,
|
8
|
+
:ids_reader,
|
9
|
+
:ids_writer,
|
10
|
+
:create,
|
11
|
+
:create!,
|
12
|
+
:build,
|
13
|
+
:any?,
|
14
|
+
:count,
|
15
|
+
:empty?,
|
16
|
+
:first,
|
17
|
+
:include?,
|
18
|
+
:last,
|
19
|
+
:length,
|
20
|
+
:load_target,
|
21
|
+
:many?,
|
22
|
+
:reload,
|
23
|
+
:size,
|
24
|
+
:select,
|
25
|
+
:uniq
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
ActiveRecord::Associations::CollectionAssociation.class_eval do
|
32
|
+
include Tako::ActiveRecordExt::CollectionAssociation
|
33
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Tako
|
2
|
+
module ActiveRecordExt
|
3
|
+
module CollectionProxy
|
4
|
+
def self.included(mod)
|
5
|
+
mod.extend(ShardedMethods)
|
6
|
+
mod.sharded_methods :any?,
|
7
|
+
:build,
|
8
|
+
:count,
|
9
|
+
:create,
|
10
|
+
:create!,
|
11
|
+
:concat,
|
12
|
+
:delete,
|
13
|
+
:delete_all,
|
14
|
+
:destroy,
|
15
|
+
:destroy_all,
|
16
|
+
:empty?,
|
17
|
+
:find,
|
18
|
+
:first,
|
19
|
+
:include?,
|
20
|
+
:last,
|
21
|
+
:length,
|
22
|
+
:many?,
|
23
|
+
:pluck,
|
24
|
+
:replace,
|
25
|
+
:select,
|
26
|
+
:size,
|
27
|
+
:sum,
|
28
|
+
:to_a,
|
29
|
+
:uniq
|
30
|
+
end
|
31
|
+
|
32
|
+
def current_shard
|
33
|
+
@association.owner.current_shard
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
ActiveRecord::Associations::CollectionProxy.class_eval do
|
40
|
+
include Tako::ActiveRecordExt::CollectionProxy
|
41
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Tako
|
2
|
+
module ActiveRecordExt
|
3
|
+
module ConnectionHandling
|
4
|
+
def connection
|
5
|
+
return Tako::Repository.create_proxy(@force_shard).connection if force_shard?
|
6
|
+
if Tako::ProxyStack.top
|
7
|
+
Tako::ProxyStack.top.connection
|
8
|
+
else
|
9
|
+
super
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
ActiveRecord::ConnectionHandling.class_eval do
|
17
|
+
prepend Tako::ActiveRecordExt::ConnectionHandling
|
18
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Tako
|
2
|
+
module ActiveRecordExt
|
3
|
+
module LogSubscriber
|
4
|
+
CLEAR = "\e[0m"
|
5
|
+
GREEN = "\e[32m"
|
6
|
+
|
7
|
+
def debug(msg)
|
8
|
+
current_shard = ::Tako::ProxyStack.top.try(:shard_name)
|
9
|
+
|
10
|
+
if current_shard
|
11
|
+
super("#{GREEN}[Shard: #{current_shard}]#{CLEAR}" + msg)
|
12
|
+
else
|
13
|
+
super
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
ActiveRecord::LogSubscriber.class_eval do
|
21
|
+
prepend Tako::ActiveRecordExt::LogSubscriber
|
22
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Tako
|
2
|
+
module ActiveRecordExt
|
3
|
+
module ShardedMethods
|
4
|
+
def sharded_methods(*method_names)
|
5
|
+
method_names.each do |method_name|
|
6
|
+
define_method(:"#{method_name}_with_tako") do |*params, &block|
|
7
|
+
if current_shard
|
8
|
+
::Tako.shard(current_shard) { send(:"#{method_name}_without_tako",*params, &block) }
|
9
|
+
else
|
10
|
+
send(:"#{method_name}_without_tako",*params, &block)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
send(:alias_method, :"#{method_name}_without_tako", method_name)
|
14
|
+
send(:alias_method, method_name, :"#{method_name}_with_tako")
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Tako
|
2
|
+
module ActiveRecordExt
|
3
|
+
module SingularAssociation
|
4
|
+
def self.included(mod)
|
5
|
+
mod.extend(ShardedMethods)
|
6
|
+
mod.sharded_methods :reader,
|
7
|
+
:writer,
|
8
|
+
:create,
|
9
|
+
:create!,
|
10
|
+
:build
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
ActiveRecord::Associations::SingularAssociation.class_eval do
|
17
|
+
include Tako::ActiveRecordExt::SingularAssociation
|
18
|
+
end
|
@@ -1,32 +1,4 @@
|
|
1
1
|
module Tako
|
2
2
|
module ActiveRecordExt
|
3
|
-
module ConnectionHandling
|
4
|
-
module Prepend
|
5
|
-
def connection
|
6
|
-
if Tako::ProxyStack.top
|
7
|
-
Tako::ProxyStack.top.connection
|
8
|
-
else
|
9
|
-
super
|
10
|
-
end
|
11
|
-
end
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
module Base
|
16
|
-
module Extend
|
17
|
-
def shard(shard_name)
|
18
|
-
if block_given?
|
19
|
-
Tako.shard(shard_name) do
|
20
|
-
yield
|
21
|
-
end
|
22
|
-
else
|
23
|
-
Tako::QueryChain.new(
|
24
|
-
Tako::Repository.shard(shard_name),
|
25
|
-
self
|
26
|
-
)
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
31
3
|
end
|
32
4
|
end
|
data/lib/tako/proxy.rb
CHANGED
@@ -2,16 +2,14 @@ module Tako
|
|
2
2
|
class Proxy
|
3
3
|
attr_reader :shard_name
|
4
4
|
attr_reader :connection
|
5
|
-
attr_accessor :base
|
6
5
|
|
7
|
-
def initialize(shard_name, connection
|
6
|
+
def initialize(shard_name, connection)
|
8
7
|
@shard_name = shard_name
|
9
8
|
@connection = connection
|
10
|
-
@base = base
|
11
9
|
end
|
12
10
|
|
13
|
-
def
|
14
|
-
Tako::ProxyStack.
|
11
|
+
def with_shard
|
12
|
+
Tako::ProxyStack.with_shard(self) do
|
15
13
|
yield
|
16
14
|
end
|
17
15
|
end
|
data/lib/tako/proxy_stack.rb
CHANGED
data/lib/tako/query_chain.rb
CHANGED
@@ -9,22 +9,38 @@ module Tako
|
|
9
9
|
end
|
10
10
|
|
11
11
|
def method_missing(method, *args)
|
12
|
-
@proxy.
|
13
|
-
if block_given?
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
12
|
+
@proxy.with_shard do
|
13
|
+
result = if block_given?
|
14
|
+
base_object.send(method, *args) do
|
15
|
+
yield
|
16
|
+
end
|
17
|
+
else
|
18
|
+
base_object.send(method, *args)
|
19
|
+
end
|
20
|
+
|
21
|
+
if chain_available?(result)
|
22
|
+
@base_object = result
|
23
|
+
return self
|
19
24
|
end
|
25
|
+
|
26
|
+
result
|
20
27
|
end
|
21
28
|
end
|
22
29
|
|
23
30
|
def shard(shard_name)
|
24
31
|
new(
|
25
|
-
Tako::Repository.
|
32
|
+
Tako::Repository.create_proxy(shard_name),
|
26
33
|
self
|
27
34
|
)
|
28
35
|
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def chain_available?(obj)
|
40
|
+
[
|
41
|
+
::ActiveRecord::Relation,
|
42
|
+
::ActiveRecord::QueryMethods::WhereChain
|
43
|
+
].any? { |anc| obj.is_a?(anc) }
|
44
|
+
end
|
29
45
|
end
|
30
46
|
end
|
data/lib/tako/repository.rb
CHANGED
@@ -21,8 +21,8 @@ module Tako
|
|
21
21
|
proxy_configs[shard_name] = conf
|
22
22
|
end
|
23
23
|
|
24
|
-
def
|
25
|
-
Proxy.new(shard_name, proxy_connections[shard_name.to_sym]
|
24
|
+
def create_proxy(shard_name)
|
25
|
+
Proxy.new(shard_name, proxy_connections[shard_name.to_sym])
|
26
26
|
end
|
27
27
|
|
28
28
|
def shard_names
|
data/lib/tako/version.rb
CHANGED
data/lib/tako.rb
CHANGED
@@ -14,7 +14,7 @@ module Tako
|
|
14
14
|
class << self
|
15
15
|
def shard(shard_name)
|
16
16
|
if block_given?
|
17
|
-
Tako::Repository.
|
17
|
+
Tako::Repository.create_proxy(shard_name).with_shard do
|
18
18
|
yield
|
19
19
|
end
|
20
20
|
else
|
@@ -39,13 +39,14 @@ module Tako
|
|
39
39
|
end
|
40
40
|
|
41
41
|
require 'active_record'
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
42
|
+
require 'tako/active_record_ext/sharded_methods'
|
43
|
+
require 'tako/active_record_ext/connection_handling'
|
44
|
+
require 'tako/active_record_ext/base'
|
45
|
+
require 'tako/active_record_ext/association'
|
46
|
+
require 'tako/active_record_ext/collection_association'
|
47
|
+
require 'tako/active_record_ext/singular_association'
|
48
|
+
require 'tako/active_record_ext/collection_proxy'
|
49
|
+
require 'tako/active_record_ext/association_relation'
|
50
|
+
require 'tako/active_record_ext/log_subscriber'
|
50
51
|
|
51
52
|
require 'tako/railtie' if defined?(::Rails)
|
data/tako.gemspec
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tako
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Masashi AKISUE
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-10-
|
11
|
+
date: 2016-10-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -80,6 +80,20 @@ dependencies:
|
|
80
80
|
- - "~>"
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '3.0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: pry
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
83
97
|
description:
|
84
98
|
email:
|
85
99
|
- masashi.akisue@aktsk.jp
|
@@ -100,6 +114,15 @@ files:
|
|
100
114
|
- circle.yml
|
101
115
|
- lib/tako.rb
|
102
116
|
- lib/tako/active_record_ext.rb
|
117
|
+
- lib/tako/active_record_ext/association.rb
|
118
|
+
- lib/tako/active_record_ext/association_relation.rb
|
119
|
+
- lib/tako/active_record_ext/base.rb
|
120
|
+
- lib/tako/active_record_ext/collection_association.rb
|
121
|
+
- lib/tako/active_record_ext/collection_proxy.rb
|
122
|
+
- lib/tako/active_record_ext/connection_handling.rb
|
123
|
+
- lib/tako/active_record_ext/log_subscriber.rb
|
124
|
+
- lib/tako/active_record_ext/sharded_methods.rb
|
125
|
+
- lib/tako/active_record_ext/singular_association.rb
|
103
126
|
- lib/tako/config.rb
|
104
127
|
- lib/tako/multi_shard_execution.rb
|
105
128
|
- lib/tako/proxy.rb
|