tako 0.2.2 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5d57edc16d1cde1831865a7eba1414a489cbbe1d
4
- data.tar.gz: ecc1d7552a3c079f4a45e5c44fac71352eb736c2
3
+ metadata.gz: 9861d9ec9b928c4ed0bbe68ada132a9335fd6077
4
+ data.tar.gz: 78351b4438784d0b40bf5a4e3b826ef5c60624eb
5
5
  SHA512:
6
- metadata.gz: 7ecf25dffebf58ec6f5076eb53b510a455cc14912ca78bafdd50670cf46d401af4d91d48ea2aacf72e126de4593c5521a0617a03bd6fe8467a1cef744fac7f1b
7
- data.tar.gz: 5d168488bddb04febbdd27177d927f7d095eb434b411e6981f8c7219cea588b3da3d3e318f51a32c75ee827aaef291f28e26e1842f9e7cb604a625193f2f8900
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 "irb"
14
- IRB.start
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, base)
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 in_proxy
14
- Tako::ProxyStack.in_piles(self) do
11
+ def with_shard
12
+ Tako::ProxyStack.with_shard(self) do
15
13
  yield
16
14
  end
17
15
  end
@@ -5,13 +5,13 @@ module Tako
5
5
  @current
6
6
  end
7
7
 
8
- def in_piles(proxy)
9
- proxy.base ||= @current
8
+ def with_shard(proxy)
9
+ previous ||= @current
10
10
  @current = proxy
11
11
 
12
12
  yield
13
13
  ensure
14
- @current = @current.base
14
+ @current = previous
15
15
  end
16
16
  end
17
17
  end
@@ -9,22 +9,38 @@ module Tako
9
9
  end
10
10
 
11
11
  def method_missing(method, *args)
12
- @proxy.in_proxy do
13
- if block_given?
14
- base_object.send(method, *args) do
15
- yield
16
- end
17
- else
18
- base_object.send(method, *args)
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.shard(shard_name),
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
@@ -21,8 +21,8 @@ module Tako
21
21
  proxy_configs[shard_name] = conf
22
22
  end
23
23
 
24
- def shard(shard_name, base = nil)
25
- Proxy.new(shard_name, proxy_connections[shard_name.to_sym], base)
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
@@ -1,3 +1,3 @@
1
1
  module Tako
2
- VERSION = "0.2.2"
2
+ VERSION = "0.3.0"
3
3
  end
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.shard(shard_name).in_proxy do
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
- ActiveRecord::ConnectionHandling.class_eval do
44
- prepend Tako::ActiveRecordExt::ConnectionHandling::Prepend
45
- end
46
-
47
- ActiveRecord::Base.class_eval do
48
- extend Tako::ActiveRecordExt::Base::Extend
49
- end
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
@@ -32,4 +32,5 @@ Gem::Specification.new do |spec|
32
32
  spec.add_development_dependency "bundler", "~> 1.11"
33
33
  spec.add_development_dependency "rake", "~> 10.0"
34
34
  spec.add_development_dependency "rspec", "~> 3.0"
35
+ spec.add_development_dependency "pry"
35
36
  end
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.2.2
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-04 00:00:00.000000000 Z
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