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 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