octoball 0.1.0 → 0.1.4
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/.circleci/Gemfile +8 -0
- data/.circleci/config.yml +3 -1
- data/README.md +0 -7
- data/lib/octoball/association.rb +28 -3
- data/lib/octoball/current_shard_tracker.rb +1 -1
- data/lib/octoball/persistence.rb +1 -1
- data/lib/octoball/relation_proxy.rb +1 -1
- data/lib/octoball/version.rb +1 -1
- data/spec/octoball/association_shard_tracking_spec.rb +2 -2
- data/spec/octoball/relation_proxy_spec.rb +14 -0
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 260d7c95bac1ba724636272cfa7ecf444124b868b2c7a3cea4d6966e0ac947a9
|
4
|
+
data.tar.gz: 5036fc1b1f6f5f0d7b24c734951ad6cbff0fd48eabc529a3f5390e55f2ad50d2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1d954e47f0a2603425d29e82669b9388d4f49abf7def04e268548554ee5ab52181a2b192a5ccfd34b288a67b34fd6cf8cac4d75b8304c918970f7523f3177285
|
7
|
+
data.tar.gz: 7b294deea783c80324d5694afd87984017411677f593d042fa9b78a35e5dba5d12584209bb36d45190c3e63d748e1a4f5096e6a6e992ef9ebfa71e7968a41c4d
|
data/.circleci/Gemfile
ADDED
data/.circleci/config.yml
CHANGED
@@ -26,8 +26,9 @@ jobs:
|
|
26
26
|
name: bundle install
|
27
27
|
command: |
|
28
28
|
gem update bundler
|
29
|
+
bundle config --local path ../vendor/bundle
|
30
|
+
bundle install --gemfile .circleci/Gemfile --jobs=4 --retry=3
|
29
31
|
bundle config --local path vendor/bundle
|
30
|
-
bundle install --jobs=4 --retry=3
|
31
32
|
- run:
|
32
33
|
name: Setup databases
|
33
34
|
command: bundle exec rake db:prepare
|
@@ -44,3 +45,4 @@ workflows:
|
|
44
45
|
parameters:
|
45
46
|
version:
|
46
47
|
- "2.7"
|
48
|
+
- "3.0"
|
data/README.md
CHANGED
@@ -45,13 +45,6 @@ Currently, its implementation is focusing on horizontal database sharding. Howev
|
|
45
45
|
gem "octoball"
|
46
46
|
```
|
47
47
|
|
48
|
-
Until first release:
|
49
|
-
```
|
50
|
-
# Bundle edge Rails
|
51
|
-
gem 'rails', github: 'rails/rails'
|
52
|
-
gem 'octoball', git: 'git@github.com:aktsk/octoball'
|
53
|
-
```
|
54
|
-
|
55
48
|
Define the database connections in `config/database.yml`, e.g.:
|
56
49
|
```
|
57
50
|
default: &default
|
data/lib/octoball/association.rb
CHANGED
@@ -5,24 +5,47 @@ class Octoball
|
|
5
5
|
attr_accessor :current_shard
|
6
6
|
end
|
7
7
|
|
8
|
+
module RelationProxyIsARelation
|
9
|
+
def ===(other)
|
10
|
+
other.is_a?(self)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
8
14
|
module ShardedCollectionAssociation
|
9
|
-
[:
|
15
|
+
[:writer, :ids_reader, :ids_writer, :create, :create!,
|
10
16
|
:build, :include?, :load_target, :reload, :size, :select].each do |method|
|
11
17
|
class_eval <<-"END", __FILE__, __LINE__ + 1
|
12
18
|
def #{method}(*args, &block)
|
13
19
|
shard = owner.current_shard
|
14
20
|
return super if !shard || shard == ActiveRecord::Base.current_shard
|
21
|
+
ret = nil
|
15
22
|
ActiveRecord::Base.connected_to(shard: shard, role: Octoball.current_role) do
|
16
23
|
ret = super
|
17
24
|
return ret unless ret.is_a?(::ActiveRecord::Relation) || ret.is_a?(::ActiveRecord::QueryMethods::WhereChain)
|
18
|
-
RelationProxy.new(ret, shard)
|
25
|
+
ret = RelationProxy.new(ret, shard)
|
26
|
+
nil # return nil to avoid loading relation
|
19
27
|
end
|
28
|
+
ret
|
20
29
|
end
|
21
30
|
ruby2_keywords(:#{method}) if respond_to?(:ruby2_keywords, true)
|
22
31
|
END
|
23
32
|
end
|
24
33
|
end
|
25
34
|
|
35
|
+
module ShardedCollectionProxyCreate
|
36
|
+
def create(klass, association)
|
37
|
+
shard = association.owner.current_shard
|
38
|
+
return super unless shard
|
39
|
+
return RelationProxy.new(super, shard) if shard == ActiveRecord::Base.current_shard
|
40
|
+
ret = nil
|
41
|
+
ActiveRecord::Base.connected_to(shard: shard, role: Octoball.current_role) do
|
42
|
+
ret = RelationProxy.new(super, shard)
|
43
|
+
nil # return nil to avoid loading relation
|
44
|
+
end
|
45
|
+
ret
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
26
49
|
module ShardedCollectionProxy
|
27
50
|
[:any?, :build, :count, :create, :create!, :concat, :delete, :delete_all,
|
28
51
|
:destroy, :destroy_all, :empty?, :find, :first, :include?, :last, :length,
|
@@ -40,7 +63,7 @@ class Octoball
|
|
40
63
|
end
|
41
64
|
|
42
65
|
module ShardedSingularAssociation
|
43
|
-
[:
|
66
|
+
[:reload, :writer, :create, :create!, :build].each do |method|
|
44
67
|
class_eval <<-"END", __FILE__, __LINE__ + 1
|
45
68
|
def #{method}(*args, &block)
|
46
69
|
return super if !owner.current_shard || owner.current_shard == ActiveRecord::Base.current_shard
|
@@ -54,8 +77,10 @@ class Octoball
|
|
54
77
|
end
|
55
78
|
|
56
79
|
::ActiveRecord::Relation.prepend(RelationCurrentShard)
|
80
|
+
::ActiveRecord::Relation.singleton_class.prepend(RelationProxyIsARelation)
|
57
81
|
::ActiveRecord::QueryMethods::WhereChain.prepend(RelationCurrentShard)
|
58
82
|
::ActiveRecord::Associations::CollectionAssociation.prepend(ShardedCollectionAssociation)
|
83
|
+
::ActiveRecord::Associations::CollectionProxy.singleton_class.prepend(ShardedCollectionProxyCreate)
|
59
84
|
::ActiveRecord::Associations::CollectionProxy.prepend(ShardedCollectionProxy)
|
60
85
|
::ActiveRecord::Associations::SingularAssociation.prepend(ShardedSingularAssociation)
|
61
86
|
end
|
@@ -19,7 +19,7 @@ class Octoball
|
|
19
19
|
|
20
20
|
def instantiate_instance_of(klass, attributes, column_types = {}, &block)
|
21
21
|
result = super
|
22
|
-
result.instance_variable_set(:@current_shard,
|
22
|
+
result.instance_variable_set(:@current_shard, current_shard)
|
23
23
|
result
|
24
24
|
end
|
25
25
|
end
|
data/lib/octoball/persistence.rb
CHANGED
@@ -62,7 +62,7 @@ class Octoball
|
|
62
62
|
if mblock
|
63
63
|
ret = #{connected_to} { @rel.to_a }.#{method}(*margs, &mblock)
|
64
64
|
else
|
65
|
-
#{connected_to} { ret = @rel.#{method}(*margs, &mblock); nil } # return nil avoid loading relation
|
65
|
+
#{connected_to} { ret = @rel.#{method}(*margs, &mblock); nil } # return nil to avoid loading relation
|
66
66
|
end
|
67
67
|
#{postamble}
|
68
68
|
EOS
|
data/lib/octoball/version.rb
CHANGED
@@ -676,7 +676,7 @@ describe Octoball::ShardedSingularAssociation, :shards => [:brazil, :master, :ca
|
|
676
676
|
|
677
677
|
it 'empty?' do
|
678
678
|
expect(@brazil_client.items.empty?).to be false
|
679
|
-
c = Client.create!(:name => 'Client1')
|
679
|
+
c = Client.using(:master).create!(:name => 'Client1')
|
680
680
|
expect(c.items.empty?).to be true
|
681
681
|
end
|
682
682
|
|
@@ -893,7 +893,7 @@ describe Octoball::ShardedSingularAssociation, :shards => [:brazil, :master, :ca
|
|
893
893
|
|
894
894
|
it 'empty?' do
|
895
895
|
expect(@brazil_client.comments.empty?).to be false
|
896
|
-
c = Client.create!(:name => 'Client1')
|
896
|
+
c = Client.using(:master).create!(:name => 'Client1')
|
897
897
|
expect(c.comments.empty?).to be true
|
898
898
|
end
|
899
899
|
|
@@ -52,6 +52,20 @@ describe Octoball::RelationProxy do
|
|
52
52
|
end
|
53
53
|
end
|
54
54
|
|
55
|
+
context 'when a relation is used in where clause' do
|
56
|
+
it 'specifies the scope without a shard' do
|
57
|
+
client = Client.where(id: @client.id)
|
58
|
+
items = Item.using(:canada).where(client: client)
|
59
|
+
expect(items.to_a).to eq(@client.items.to_a)
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'specifies the scope with a shard' do
|
63
|
+
client = Client.using(:canada).where(id: @client.id)
|
64
|
+
items = Item.using(:canada).where(client: client)
|
65
|
+
expect(items.to_a).to eq(@client.items.to_a)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
55
69
|
context 'when comparing to other Relation objects' do
|
56
70
|
before :each do
|
57
71
|
@relation.reset
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: octoball
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tomoki Sekiyama
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-12-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -116,6 +116,7 @@ executables: []
|
|
116
116
|
extensions: []
|
117
117
|
extra_rdoc_files: []
|
118
118
|
files:
|
119
|
+
- ".circleci/Gemfile"
|
119
120
|
- ".circleci/config.yml"
|
120
121
|
- ".gitignore"
|
121
122
|
- Gemfile
|
@@ -167,7 +168,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
167
168
|
- !ruby/object:Gem::Version
|
168
169
|
version: '0'
|
169
170
|
requirements: []
|
170
|
-
rubygems_version: 3.1.
|
171
|
+
rubygems_version: 3.1.6
|
171
172
|
signing_key:
|
172
173
|
specification_version: 4
|
173
174
|
summary: Octopus-like Database Sharding Helper for ActiveRecord 6.1+
|