ar-octopus 0.7.0 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/.travis.yml +3 -1
- data/Appraisals +4 -4
- data/README.mkdn +2 -27
- data/Rakefile +1 -1
- data/ar-octopus.gemspec +3 -2
- data/gemfiles/{rails31.gemfile → rails4.gemfile} +1 -1
- data/lib/octopus.rb +5 -8
- data/lib/octopus/association.rb +31 -8
- data/lib/octopus/association_collection.rb +9 -15
- data/lib/octopus/migration.rb +3 -18
- data/lib/octopus/model.rb +6 -6
- data/lib/octopus/proxy.rb +16 -13
- data/lib/octopus/rails3/abstract_adapter.rb +6 -1
- data/lib/octopus/rails3/persistence.rb +5 -0
- data/lib/octopus/scope_proxy.rb +4 -0
- data/lib/octopus/version.rb +1 -1
- data/lib/tasks/octopus.rake +1 -5
- data/spec/config/shards.yml +0 -1
- data/spec/octopus/association_spec.rb +8 -8
- data/spec/octopus/migration_spec.rb +11 -11
- data/spec/octopus/model_spec.rb +33 -29
- data/spec/octopus/proxy_spec.rb +21 -28
- data/spec/octopus/replication_spec.rb +1 -1
- data/spec/support/database_models.rb +5 -11
- data/spec/support/shared_contexts.rb +2 -5
- data/spec/tasks/octopus.rake_spec.rb +1 -5
- metadata +7 -20
- data/lib/octopus/rails3.2/persistence.rb +0 -12
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
ZWQzNDQ0MzMzZWViNTFiYjY5MWRlODZjN2M2MGFlNDMwM2RjMTY2Mw==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
YmUzNzY2YzQ0ZWUwOWVjZDI4ZWQwOGEyMGZmOWY3NDg1MzA0MjNhZg==
|
7
7
|
!binary "U0hBNTEy":
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
ODcyN2VkMDQ3Zjk4MjVlYTEyMGMxYmU4NmFhMmI1ZmM0OGFkMDc5Mzk1MWRk
|
10
|
+
OWIyYzMwMTY5MjVhYjE1MDljOTlkMjI4N2E3OTYyMGY4YzIyMGUwZGVjZTM4
|
11
|
+
ZTI3ZGRiZWU2NjkyNGQzNDcwNTM3Y2FlNjM3MWIwNGI4MGIzMWY=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
M2M5MDVjNGU4NWU3MTcxYzljOTJmNTVlMGI5NzY5ZTliYzBmODIxZjIzNTE3
|
14
|
+
NGVlZWU3MmNkNDIwYzYxNDVhMzM1NmVlZmFkZGNkZmYwM2Y2NzY0OThhMTBm
|
15
|
+
NjYzMWM0NDAyNDMxN2ZmNzY0ZWFhNmYwN2M5NWIwNmE3MDdjNWE=
|
data/.travis.yml
CHANGED
@@ -7,8 +7,8 @@ rvm:
|
|
7
7
|
- 1.9.3
|
8
8
|
|
9
9
|
gemfile:
|
10
|
-
- gemfiles/rails31.gemfile
|
11
10
|
- gemfiles/rails32.gemfile
|
11
|
+
- gemfiles/rails4.gemfile
|
12
12
|
|
13
13
|
notifications:
|
14
14
|
recipients:
|
@@ -19,3 +19,5 @@ matrix:
|
|
19
19
|
include:
|
20
20
|
- rvm: 2.0.0
|
21
21
|
gemfile: gemfiles/rails32.gemfile
|
22
|
+
- rvm: 2.0.0
|
23
|
+
gemfile: gemfiles/rails4.gemfile
|
data/Appraisals
CHANGED
data/README.mkdn
CHANGED
@@ -5,7 +5,7 @@
|
|
5
5
|
Octopus is a better way to do Database Sharding in ActiveRecord. Sharding allows multiple databases in the same rails application. While there are several projects that implement Sharding (e.g. DbCharmer, DataFabric, MultiDb), each project has its own limitations. The main goal of octopus project is to provide a better way of doing Database Sharding.
|
6
6
|
|
7
7
|
## Feature list:
|
8
|
-
The api is designed to be simple as possible. Octopus focuses on the end user, giving the power of multiple databases but with reliable code and flexibility. Octopus is compatible with Rails 3.
|
8
|
+
The api is designed to be simple as possible. Octopus focuses on the end user, giving the power of multiple databases but with reliable code and flexibility. Octopus is compatible with Rails 3.2 and Rails 4.
|
9
9
|
|
10
10
|
Octopus supports:
|
11
11
|
|
@@ -122,14 +122,6 @@ If you want to send a specified action, or all actions from a controller, to a s
|
|
122
122
|
To see the complete list of features and syntax, please check out our <a href="http://wiki.github.com/tchandy/octopus/"> Wiki</a>
|
123
123
|
Want to see sample rails applications using octopus features? please check it out: <a href="http://github.com/tchandy/octopus_sharding_example">Sharding Example</a> and <a href="http://github.com/tchandy/octopus_replication_example">Replication Example</a>. Also, we have an example that shows how to use Octopus without Rails: <a href="http://github.com/tchandy/octopus_sinatra"> Octopus + Sinatra Example</a>.
|
124
124
|
|
125
|
-
|
126
|
-
## Important!
|
127
|
-
Occasionally, an application might lose a connection to a database; when this happens, ActiveRecord will raise an exception. Add the following line to your application configuration if you are experiencing this issue:
|
128
|
-
|
129
|
-
verify_connection: true
|
130
|
-
|
131
|
-
This will tell Octopus to verify the connection before sending the query.
|
132
|
-
|
133
125
|
## Mixing Octopus with the Rails multiple database model
|
134
126
|
If you want to set a custom connection to a specific model, use the syntax `octopus_establish_connection` syntax:
|
135
127
|
|
@@ -138,23 +130,6 @@ If you want to set a custom connection to a specific model, use the syntax `octo
|
|
138
130
|
octopus_establish_connection(:adapter => "mysql", :database => "octopus_shard2")
|
139
131
|
end
|
140
132
|
|
141
|
-
## Set table names
|
142
|
-
If you want to use specific table names, use the correct syntax for your version of Rails.
|
143
|
-
|
144
|
-
### Rails <= 3.1
|
145
|
-
|
146
|
-
class Bacon < ActiveRecord::Base
|
147
|
-
set_table_name("yummy")
|
148
|
-
end
|
149
|
-
|
150
|
-
### Rails >= 3.2
|
151
|
-
|
152
|
-
class Bacon < ActiveRecord::Base
|
153
|
-
self.table_name = "yummy"
|
154
|
-
end
|
155
|
-
|
156
|
-
Unfortunately the `self.table_name=` syntax isn't supported on versions of Rails <= 3.1.
|
157
|
-
|
158
133
|
## Contributing with Octopus
|
159
134
|
Contributors are welcome! To run the test suite, you need mysql, postgresql and sqlite3 installed. This is what you need to setup your Octopus development environment:
|
160
135
|
|
@@ -165,7 +140,7 @@ Contributors are welcome! To run the test suite, you need mysql, postgresql and
|
|
165
140
|
bundle exec rake appraisal:install
|
166
141
|
bundle exec rake spec
|
167
142
|
|
168
|
-
This command will run the spec suite for all rails versions supported
|
143
|
+
This command will run the spec suite for all rails versions supported.
|
169
144
|
To run our integrations tests inside sample_app, you need to following commands:
|
170
145
|
|
171
146
|
cd sample_app
|
data/Rakefile
CHANGED
@@ -57,7 +57,7 @@ namespace :db do
|
|
57
57
|
require "#{File.dirname(__FILE__)}/spec/support/database_connection"
|
58
58
|
|
59
59
|
shard_symbols = [:master, :brazil, :canada, :russia, :alone_shard, :postgresql_shard, :sqlite_shard]
|
60
|
-
shard_symbols << :protocol_shard
|
60
|
+
shard_symbols << :protocol_shard
|
61
61
|
shard_symbols.each do |shard_symbol|
|
62
62
|
# Rails 3.1 needs to do some introspection around the base class, which requires
|
63
63
|
# the model be a descendent of ActiveRecord::Base.
|
data/ar-octopus.gemspec
CHANGED
@@ -21,8 +21,9 @@ Gem::Specification.new do |s|
|
|
21
21
|
"Octopus now stores schema version information in each shard and migrations will not " \
|
22
22
|
"work properly unless this task is invoked."
|
23
23
|
|
24
|
-
s.add_dependency 'activerecord', '>= 3.
|
25
|
-
s.add_dependency 'activesupport', '>= 3.
|
24
|
+
s.add_dependency 'activerecord', '>= 3.2.0'
|
25
|
+
s.add_dependency 'activesupport', '>= 3.2.0'
|
26
|
+
|
26
27
|
s.add_development_dependency 'rake', '>= 0.8.7'
|
27
28
|
s.add_development_dependency 'rspec', '>= 2.0.0'
|
28
29
|
s.add_development_dependency 'mysql2', '> 0.3'
|
data/lib/octopus.rb
CHANGED
@@ -18,7 +18,7 @@ module Octopus
|
|
18
18
|
@config ||= begin
|
19
19
|
file_name = Octopus.directory() + "/config/shards.yml"
|
20
20
|
|
21
|
-
if File.exists?(file_name)
|
21
|
+
if File.exists?(file_name) || File.symlink?(file_name)
|
22
22
|
config ||= HashWithIndifferentAccess.new(YAML.load(ERB.new(File.read(file_name)).result))[Octopus.env()]
|
23
23
|
else
|
24
24
|
config ||= HashWithIndifferentAccess.new
|
@@ -64,12 +64,12 @@ module Octopus
|
|
64
64
|
@environments ||= config['environments'] || ['production']
|
65
65
|
end
|
66
66
|
|
67
|
-
def self.
|
68
|
-
ActiveRecord::VERSION::MAJOR
|
67
|
+
def self.rails3?
|
68
|
+
ActiveRecord::VERSION::MAJOR <= 3
|
69
69
|
end
|
70
70
|
|
71
|
-
def self.
|
72
|
-
ActiveRecord::VERSION::MAJOR
|
71
|
+
def self.rails4?
|
72
|
+
ActiveRecord::VERSION::MAJOR >= 4
|
73
73
|
end
|
74
74
|
|
75
75
|
def self.rails?
|
@@ -107,9 +107,6 @@ if defined?(::Rails)
|
|
107
107
|
require "octopus/railtie"
|
108
108
|
end
|
109
109
|
|
110
|
-
if Octopus.rails32?
|
111
|
-
require "octopus/rails3.2/persistence"
|
112
|
-
end
|
113
110
|
|
114
111
|
require "octopus/proxy"
|
115
112
|
require "octopus/scope_proxy"
|
data/lib/octopus/association.rb
CHANGED
@@ -6,23 +6,46 @@ module Octopus::Association
|
|
6
6
|
module InstanceMethods
|
7
7
|
def set_connection_on_association(record)
|
8
8
|
return unless ::Octopus.enabled?
|
9
|
-
return if !self.connection.respond_to?(:current_shard) || !self.respond_to?(:current_shard)
|
9
|
+
return if !self.class.connection.respond_to?(:current_shard) || !self.respond_to?(:current_shard)
|
10
10
|
if !record.current_shard.nil? && !self.current_shard.nil? && record.current_shard != self.current_shard
|
11
11
|
raise "Association Error: Records are from different shards"
|
12
12
|
end
|
13
13
|
|
14
|
-
record.current_shard = self.connection.current_shard = self.current_shard if should_set_current_shard?
|
14
|
+
record.current_shard = self.class.connection.current_shard = self.current_shard if should_set_current_shard?
|
15
15
|
end
|
16
16
|
end
|
17
17
|
|
18
|
-
|
19
|
-
|
20
|
-
|
18
|
+
if Octopus.rails4?
|
19
|
+
def has_many(association_id, scope=nil, options={}, &extension)
|
20
|
+
if options == {} && scope.is_a?(Hash)
|
21
|
+
default_octopus_opts(scope)
|
22
|
+
else
|
23
|
+
default_octopus_opts(options)
|
24
|
+
end
|
25
|
+
super
|
26
|
+
end
|
27
|
+
else
|
28
|
+
def has_many(association_id, options={}, &extension)
|
29
|
+
default_octopus_opts(options)
|
30
|
+
super
|
31
|
+
end
|
21
32
|
end
|
22
33
|
|
23
|
-
|
24
|
-
|
25
|
-
|
34
|
+
|
35
|
+
if Octopus.rails4?
|
36
|
+
def has_and_belongs_to_many(association_id, scope=nil, options={}, &extension)
|
37
|
+
if options == {} && scope.is_a?(Hash)
|
38
|
+
default_octopus_opts(scope)
|
39
|
+
else
|
40
|
+
default_octopus_opts(options)
|
41
|
+
end
|
42
|
+
super
|
43
|
+
end
|
44
|
+
else
|
45
|
+
def has_and_belongs_to_many(association_id, options={}, &extension)
|
46
|
+
default_octopus_opts(options)
|
47
|
+
super
|
48
|
+
end
|
26
49
|
end
|
27
50
|
|
28
51
|
def default_octopus_opts(options)
|
@@ -1,16 +1,14 @@
|
|
1
1
|
module Octopus::AssociationCollection
|
2
2
|
|
3
3
|
def self.included(base)
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
alias_method_chain :build, :octopus
|
13
|
-
end
|
4
|
+
base.instance_eval do
|
5
|
+
alias_method_chain :reader, :octopus
|
6
|
+
alias_method_chain :writer, :octopus
|
7
|
+
alias_method_chain :ids_reader, :octopus
|
8
|
+
alias_method_chain :ids_writer, :octopus
|
9
|
+
alias_method_chain :create, :octopus
|
10
|
+
alias_method_chain :create!, :octopus
|
11
|
+
alias_method_chain :build, :octopus
|
14
12
|
end
|
15
13
|
end
|
16
14
|
|
@@ -62,8 +60,4 @@ module Octopus::AssociationCollection
|
|
62
60
|
end
|
63
61
|
end
|
64
62
|
|
65
|
-
|
66
|
-
ActiveRecord::Associations::CollectionAssociation.send(:include, Octopus::AssociationCollection)
|
67
|
-
else
|
68
|
-
ActiveRecord::Associations::AssociationCollection.send(:include, Octopus::AssociationCollection)
|
69
|
-
end
|
63
|
+
ActiveRecord::Associations::CollectionAssociation.send(:include, Octopus::AssociationCollection)
|
data/lib/octopus/migration.rb
CHANGED
@@ -13,27 +13,16 @@ module Octopus::Migration
|
|
13
13
|
end
|
14
14
|
end
|
15
15
|
|
16
|
-
include InstanceOrClassMethods
|
16
|
+
include InstanceOrClassMethods
|
17
17
|
|
18
18
|
def self.included(base)
|
19
19
|
base.send(:extend, ClassMethods)
|
20
20
|
|
21
|
-
|
22
|
-
base.alias_method_chain :announce, :octopus
|
23
|
-
else
|
24
|
-
base.class_eval do
|
25
|
-
class << self
|
26
|
-
alias_method_chain :announce, :octopus
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
21
|
+
base.alias_method_chain :announce, :octopus
|
31
22
|
base.class_attribute :current_shard, :current_group, :instance_reader => false, :instance_writer => false
|
32
23
|
end
|
33
24
|
|
34
25
|
module ClassMethods
|
35
|
-
include InstanceOrClassMethods unless Octopus.rails31? || Octopus.rails32?
|
36
|
-
|
37
26
|
def using(*args)
|
38
27
|
return self unless connection.is_a?(Octopus::Proxy)
|
39
28
|
|
@@ -147,11 +136,7 @@ end
|
|
147
136
|
|
148
137
|
module Octopus::MigrationProxy
|
149
138
|
def shards
|
150
|
-
|
151
|
-
migration.class.shards
|
152
|
-
else
|
153
|
-
migration.shards
|
154
|
-
end
|
139
|
+
migration.class.shards
|
155
140
|
end
|
156
141
|
end
|
157
142
|
|
data/lib/octopus/model.rb
CHANGED
@@ -144,13 +144,13 @@ module Octopus::Model
|
|
144
144
|
attr_accessor :custom_octopus_connection
|
145
145
|
attr_accessor :custom_octopus_table_name
|
146
146
|
|
147
|
-
|
147
|
+
if Octopus.rails3?
|
148
|
+
alias_method_chain(:set_table_name, :octopus)
|
149
|
+
end
|
148
150
|
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
super
|
153
|
-
end
|
151
|
+
def table_name=(value = nil)
|
152
|
+
self.custom_octopus_table_name = true
|
153
|
+
super
|
154
154
|
end
|
155
155
|
end
|
156
156
|
end
|
data/lib/octopus/proxy.rb
CHANGED
@@ -15,12 +15,6 @@ class Octopus::Proxy
|
|
15
15
|
@shards[:master] = ActiveRecord::Base.connection_pool_without_octopus()
|
16
16
|
@config = ActiveRecord::Base.connection_pool_without_octopus.connection.instance_variable_get(:@config)
|
17
17
|
|
18
|
-
if !config.nil? && config.has_key?("verify_connection")
|
19
|
-
@verify_connection = config["verify_connection"]
|
20
|
-
else
|
21
|
-
@verify_connection = false
|
22
|
-
end
|
23
|
-
|
24
18
|
if !config.nil?
|
25
19
|
@entire_sharded = config['entire_sharded']
|
26
20
|
shards_config = config[Octopus.rails_env()]
|
@@ -29,7 +23,7 @@ class Octopus::Proxy
|
|
29
23
|
shards_config ||= []
|
30
24
|
|
31
25
|
shards_config.each do |key, value|
|
32
|
-
if value.is_a?(String)
|
26
|
+
if value.is_a?(String)
|
33
27
|
value = resolve_string_connection(value).merge(:octopus_shard => key)
|
34
28
|
initialize_adapter(value['adapter'])
|
35
29
|
@shards[key.to_sym] = connection_pool_for(value, "#{value['adapter']}_connection")
|
@@ -145,14 +139,11 @@ class Octopus::Proxy
|
|
145
139
|
# connection pool. Previously, that would work since the pool would just
|
146
140
|
# reconnect, but in Rails 3.1 the flag prevents this.
|
147
141
|
def safe_connection(connection_pool)
|
148
|
-
|
149
|
-
connection_pool.automatic_reconnect ||= true
|
150
|
-
end
|
142
|
+
connection_pool.automatic_reconnect ||= true
|
151
143
|
connection_pool.connection()
|
152
144
|
end
|
153
145
|
|
154
146
|
def select_connection
|
155
|
-
@shards[shard_name].verify_active_connections! if @verify_connection
|
156
147
|
safe_connection(@shards[shard_name])
|
157
148
|
end
|
158
149
|
|
@@ -244,8 +235,15 @@ class Octopus::Proxy
|
|
244
235
|
end
|
245
236
|
|
246
237
|
protected
|
238
|
+
|
247
239
|
def connection_pool_for(adapter, config)
|
248
|
-
|
240
|
+
if Octopus.rails4?
|
241
|
+
arg = ActiveRecord::ConnectionAdapters::ConnectionSpecification.new(adapter.dup, config)
|
242
|
+
else
|
243
|
+
arg = ActiveRecord::Base::ConnectionSpecification.new(adapter.dup, config)
|
244
|
+
end
|
245
|
+
|
246
|
+
ActiveRecord::ConnectionAdapters::ConnectionPool.new(arg)
|
249
247
|
end
|
250
248
|
|
251
249
|
def initialize_adapter(adapter)
|
@@ -258,7 +256,12 @@ class Octopus::Proxy
|
|
258
256
|
end
|
259
257
|
|
260
258
|
def resolve_string_connection(spec)
|
261
|
-
|
259
|
+
if Octopus.rails4?
|
260
|
+
resolver = ActiveRecord::ConnectionAdapters::ConnectionSpecification::Resolver.new(spec, {})
|
261
|
+
else
|
262
|
+
resolver = ActiveRecord::Base::ConnectionSpecification::Resolver.new(spec, {})
|
263
|
+
end
|
264
|
+
resolver.spec.config.stringify_keys
|
262
265
|
end
|
263
266
|
|
264
267
|
def should_clean_connection?(method)
|
@@ -3,7 +3,12 @@ module Octopus
|
|
3
3
|
module AbstractAdapter
|
4
4
|
module OctopusShard
|
5
5
|
|
6
|
-
|
6
|
+
parent = ActiveSupport::BasicObject
|
7
|
+
if Octopus.rails4?
|
8
|
+
parent = ActiveSupport::ProxyObject
|
9
|
+
end
|
10
|
+
|
11
|
+
class InstrumenterDecorator < parent
|
7
12
|
def initialize(adapter, instrumenter)
|
8
13
|
@adapter = adapter
|
9
14
|
@instrumenter = instrumenter
|
data/lib/octopus/scope_proxy.rb
CHANGED
@@ -37,6 +37,10 @@ class Octopus::ScopeProxy
|
|
37
37
|
result
|
38
38
|
end
|
39
39
|
|
40
|
+
def as_json(options = nil)
|
41
|
+
method_missing(:as_json, options)
|
42
|
+
end
|
43
|
+
|
40
44
|
# Delegates to method_missing (instead of @klass) so that User.using(:blah).where(:name => "Mike")
|
41
45
|
# gets run in the correct shard context when #== is evaluated.
|
42
46
|
def ==(*args)
|
data/lib/octopus/version.rb
CHANGED
data/lib/tasks/octopus.rake
CHANGED
@@ -6,11 +6,7 @@ namespace :octopus do
|
|
6
6
|
connection = ActiveRecord::Base.connection
|
7
7
|
|
8
8
|
current_version = ActiveRecord::Migrator.current_version
|
9
|
-
migrations_paths =
|
10
|
-
ActiveRecord::Migrator.migrations_paths
|
11
|
-
else
|
12
|
-
ActiveRecord::Migrator.migrations_path
|
13
|
-
end
|
9
|
+
migrations_paths = ActiveRecord::Migrator.migrations_paths
|
14
10
|
|
15
11
|
connection.send_queries_to_multiple_shards(connection.shard_names) do
|
16
12
|
ActiveRecord::Schema.initialize_schema_migrations_table
|
data/spec/config/shards.yml
CHANGED
@@ -184,9 +184,9 @@ describe Octopus::Association, :shards => [:brazil, :master, :canada] do
|
|
184
184
|
|
185
185
|
it "find" do
|
186
186
|
role = @permission_brazil_2.roles.create(:name => "Builded Role")
|
187
|
-
@permission_brazil_2.roles.
|
187
|
+
@permission_brazil_2.roles.first.should == role
|
188
188
|
@permission_brazil_2.roles.destroy_all
|
189
|
-
@permission_brazil_2.roles.
|
189
|
+
@permission_brazil_2.roles.first.should be_nil
|
190
190
|
end
|
191
191
|
|
192
192
|
it "exists?" do
|
@@ -337,9 +337,9 @@ describe Octopus::Association, :shards => [:brazil, :master, :canada] do
|
|
337
337
|
|
338
338
|
it "find" do
|
339
339
|
role = @new_brazil_programmer.projects.create(:name => "New VB App :-/")
|
340
|
-
@new_brazil_programmer.projects.
|
340
|
+
@new_brazil_programmer.projects.first.should == role
|
341
341
|
@new_brazil_programmer.projects.destroy_all
|
342
|
-
@new_brazil_programmer.projects.
|
342
|
+
@new_brazil_programmer.projects.first.should be_nil
|
343
343
|
end
|
344
344
|
|
345
345
|
it "exists?" do
|
@@ -497,9 +497,9 @@ describe Octopus::Association, :shards => [:brazil, :master, :canada] do
|
|
497
497
|
end
|
498
498
|
|
499
499
|
it "find" do
|
500
|
-
@brazil_client.items.
|
500
|
+
@brazil_client.items.first.should == @item_brazil
|
501
501
|
@brazil_client.items.destroy_all
|
502
|
-
@brazil_client.items.
|
502
|
+
@brazil_client.items.first.should be_nil
|
503
503
|
end
|
504
504
|
|
505
505
|
it "exists?" do
|
@@ -633,9 +633,9 @@ describe Octopus::Association, :shards => [:brazil, :master, :canada] do
|
|
633
633
|
end
|
634
634
|
|
635
635
|
it "find" do
|
636
|
-
@brazil_client.comments.
|
636
|
+
@brazil_client.comments.first.should == @comment_brazil
|
637
637
|
@brazil_client.comments.destroy_all
|
638
|
-
@brazil_client.comments.
|
638
|
+
@brazil_client.comments.first.should be_nil
|
639
639
|
end
|
640
640
|
|
641
641
|
it "exists?" do
|
@@ -32,27 +32,27 @@ describe Octopus::Migration do
|
|
32
32
|
|
33
33
|
it "should run once per shard" do
|
34
34
|
OctopusHelper.migrating_to_version 5 do
|
35
|
-
User.using(:canada).
|
36
|
-
User.using(:brazil).
|
37
|
-
User.using(:russia).
|
35
|
+
User.using(:canada).where(:name => 'MultipleGroup').size.should == 1
|
36
|
+
User.using(:brazil).where(:name => 'MultipleGroup').size.should == 1
|
37
|
+
User.using(:russia).where(:name => 'MultipleGroup').size.should == 1
|
38
38
|
end
|
39
39
|
end
|
40
40
|
|
41
41
|
it "should create users inside block" do
|
42
42
|
OctopusHelper.migrating_to_version 12 do
|
43
|
-
User.using(:brazil).
|
44
|
-
User.using(:brazil).
|
45
|
-
User.using(:canada).
|
46
|
-
User.using(:canada).
|
43
|
+
User.using(:brazil).where(:name => 'UsingBlock1').size.should == 1
|
44
|
+
User.using(:brazil).where(:name => 'UsingBlock2').size.should == 1
|
45
|
+
User.using(:canada).where(:name => 'UsingCanada').size.should == 1
|
46
|
+
User.using(:canada).where(:name => 'UsingCanada2').size.should == 1
|
47
47
|
end
|
48
48
|
end
|
49
49
|
|
50
50
|
it "should send the query to the correct shard" do
|
51
51
|
OctopusHelper.migrating_to_version 13 do
|
52
|
-
User.using(:brazil).
|
53
|
-
User.using(:brazil).
|
54
|
-
User.using(:canada).
|
55
|
-
User.using(:canada).
|
52
|
+
User.using(:brazil).where(:name => 'Brazil').size.should == 1
|
53
|
+
User.using(:brazil).where(:name => 'Canada').size.should == 0
|
54
|
+
User.using(:canada).where(:name => 'Brazil').size.should == 0
|
55
|
+
User.using(:canada).where(:name => 'Canada').size.should == 1
|
56
56
|
end
|
57
57
|
end
|
58
58
|
|
data/spec/octopus/model_spec.rb
CHANGED
@@ -237,17 +237,14 @@ describe Octopus::Model do
|
|
237
237
|
User.using(:brazil).find_by_name("Mike").should == u
|
238
238
|
end
|
239
239
|
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
canada1.should == canada1_dup
|
245
|
-
end
|
240
|
+
it "should check current_shard when determining equality" do
|
241
|
+
canada1.should_not == brazil1
|
242
|
+
canada1.should == canada1_dup
|
243
|
+
end
|
246
244
|
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
end
|
245
|
+
it "delegates equality check on scopes" do
|
246
|
+
u = User.using(:brazil).create!(:name => "Mike")
|
247
|
+
User.using(:brazil).where(:name => "Mike").should == [u]
|
251
248
|
end
|
252
249
|
end
|
253
250
|
end
|
@@ -375,23 +372,21 @@ describe Octopus::Model do
|
|
375
372
|
end
|
376
373
|
end
|
377
374
|
|
378
|
-
|
379
|
-
|
380
|
-
before { User.using(:brazil).create!(:name => "User1") }
|
375
|
+
describe "#pluck" do
|
376
|
+
before { User.using(:brazil).create!(:name => "User1") }
|
381
377
|
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
end
|
378
|
+
it "should works from scope proxy" do
|
379
|
+
names = User.using(:brazil).pluck(:name)
|
380
|
+
names.should eq(["User1"])
|
381
|
+
User.using(:master).pluck(:name).should eq([])
|
387
382
|
end
|
383
|
+
end
|
388
384
|
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
end
|
385
|
+
it "update_column" do
|
386
|
+
@user = User.using(:brazil).create!(:name => "User1")
|
387
|
+
@user2 = User.using(:brazil).find(@user.id)
|
388
|
+
@user2.update_column(:name, "Joaquim Shard Brazil")
|
389
|
+
User.using(:brazil).find_by_name("Joaquim Shard Brazil").should_not be_nil
|
395
390
|
end
|
396
391
|
|
397
392
|
it "update_attributes" do
|
@@ -419,6 +414,17 @@ describe Octopus::Model do
|
|
419
414
|
User.using(:brazil).find_by_name("Joaquim").should_not be_nil
|
420
415
|
end
|
421
416
|
|
417
|
+
it "as_json" do
|
418
|
+
ActiveRecord::Base.include_root_in_json = false
|
419
|
+
|
420
|
+
Octopus.using(:brazil) do
|
421
|
+
User.create!(:name => "User1")
|
422
|
+
end
|
423
|
+
|
424
|
+
user = User.using(:brazil).where(:name => "User1").first
|
425
|
+
user.as_json(:except => [:created_at, :updated_at, :id]).should eq({"admin"=>nil, "name"=>"User1", "number"=>nil})
|
426
|
+
end
|
427
|
+
|
422
428
|
it "transaction" do
|
423
429
|
u = User.create!(:name => "Thiago")
|
424
430
|
|
@@ -482,11 +488,9 @@ describe Octopus::Model do
|
|
482
488
|
end
|
483
489
|
end
|
484
490
|
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
Ham.using(:brazil).create!(:name => "YUMMMYYYY")
|
489
|
-
end
|
491
|
+
describe "when using table_name=" do
|
492
|
+
it 'should work correctly' do
|
493
|
+
Ham.using(:brazil).create!(:name => "YUMMMYYYY")
|
490
494
|
end
|
491
495
|
end
|
492
496
|
|
data/spec/octopus/proxy_spec.rb
CHANGED
@@ -9,7 +9,7 @@ describe Octopus::Proxy do
|
|
9
9
|
proxy.instance_variable_get(:@shards).should include("canada", "brazil", "master", "sqlite_shard", "russia", "alone_shard",
|
10
10
|
"aug2009", "postgresql_shard", "aug2010", "aug2011")
|
11
11
|
|
12
|
-
proxy.instance_variable_get(:@shards).should include("protocol_shard")
|
12
|
+
proxy.instance_variable_get(:@shards).should include("protocol_shard")
|
13
13
|
|
14
14
|
proxy.has_group?("country_shards").should be_true
|
15
15
|
proxy.shards_for_group("country_shards").should include(:canada, :brazil, :russia)
|
@@ -26,10 +26,6 @@ describe Octopus::Proxy do
|
|
26
26
|
proxy.instance_variable_get(:@replicated).should be_false
|
27
27
|
end
|
28
28
|
|
29
|
-
it "should not verify connections for default" do
|
30
|
-
proxy.instance_variable_get(:@verify_connection).should be_false
|
31
|
-
end
|
32
|
-
|
33
29
|
it "should work with thiking sphinx" do
|
34
30
|
config = proxy.instance_variable_get(:@config)
|
35
31
|
config[:adapter].should == "mysql2"
|
@@ -140,7 +136,6 @@ describe Octopus::Proxy do
|
|
140
136
|
Octopus.config()
|
141
137
|
|
142
138
|
proxy.instance_variable_get(:@replicated).should be_true
|
143
|
-
proxy.instance_variable_get(:@verify_connection).should be_true
|
144
139
|
Octopus.environments.should == ["staging", "production"]
|
145
140
|
end
|
146
141
|
|
@@ -239,34 +234,32 @@ describe Octopus::Proxy do
|
|
239
234
|
end
|
240
235
|
end
|
241
236
|
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
end
|
237
|
+
describe "saving multiple sharded objects at once" do
|
238
|
+
before :each do
|
239
|
+
@p = MmorpgPlayer.using(:alone_shard).create!(:player_name => 'Thiago')
|
240
|
+
end
|
247
241
|
|
248
|
-
|
242
|
+
subject { @p.save! }
|
249
243
|
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
244
|
+
context "when the objects are created with #new and saved one at a time" do
|
245
|
+
before :each do
|
246
|
+
@p.weapons.create!(:name => 'battleaxe', :hand => 'right')
|
247
|
+
@p.skills.create!(:name => 'smiting', :weapon => @p.weapons[0])
|
248
|
+
end
|
255
249
|
|
256
|
-
|
257
|
-
|
258
|
-
end
|
250
|
+
it "should save all associated objects on the correct shard" do
|
251
|
+
expect { subject }.to_not raise_error
|
259
252
|
end
|
253
|
+
end
|
260
254
|
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
255
|
+
context "when the objects are created with #new and saved at the same time" do
|
256
|
+
before :each do
|
257
|
+
@p.weapons.new(:name => 'battleaxe', :hand => 'right')
|
258
|
+
@p.skills.new(:name => 'smiting', :weapon => @p.weapons[0])
|
259
|
+
end
|
266
260
|
|
267
|
-
|
268
|
-
|
269
|
-
end
|
261
|
+
it "should save all associated objects on the correct shard" do
|
262
|
+
expect { subject }.to_not raise_error
|
270
263
|
end
|
271
264
|
end
|
272
265
|
end
|
@@ -111,7 +111,7 @@ describe "when the database is replicated and the entire application is replicat
|
|
111
111
|
Cat.create!(:name => "Slave Cat")
|
112
112
|
Cat.connection.current_shard.should eql(:master)
|
113
113
|
begin
|
114
|
-
Cat.
|
114
|
+
Cat.where(:rubbish => true)
|
115
115
|
rescue
|
116
116
|
end
|
117
117
|
Cat.connection.current_shard.should eql(:master)
|
@@ -4,11 +4,7 @@ class BlankModel < ActiveRecord::Base; end;
|
|
4
4
|
|
5
5
|
#The user class is just sharded, not replicated
|
6
6
|
class User < ActiveRecord::Base
|
7
|
-
|
8
|
-
scope :thiago, {:conditions => {:name => "Thiago"}}
|
9
|
-
else
|
10
|
-
named_scope :thiago, {:conditions => {:name => "Thiago"}}
|
11
|
-
end
|
7
|
+
scope :thiago, lambda { where(:name => 'Thiago') }
|
12
8
|
|
13
9
|
def awesome_queries
|
14
10
|
Octopus.using(:canada) do
|
@@ -83,17 +79,15 @@ end
|
|
83
79
|
|
84
80
|
|
85
81
|
class Bacon < ActiveRecord::Base
|
86
|
-
|
82
|
+
self.table_name = 'yummy'
|
87
83
|
end
|
88
84
|
|
89
85
|
class Cheese < ActiveRecord::Base
|
90
|
-
|
86
|
+
self.table_name = 'yummy'
|
91
87
|
end
|
92
88
|
|
93
|
-
|
94
|
-
|
95
|
-
self.table_name = "yummy"
|
96
|
-
end
|
89
|
+
class Ham < ActiveRecord::Base
|
90
|
+
self.table_name = 'yummy'
|
97
91
|
end
|
98
92
|
|
99
93
|
#This class sets its own connection
|
@@ -11,11 +11,8 @@ shared_context "with query cache enabled" do
|
|
11
11
|
end
|
12
12
|
|
13
13
|
around(:each) do |example|
|
14
|
-
|
15
|
-
|
16
|
-
active_support_subscribed(counter.to_proc, 'sql.active_record') do
|
17
|
-
example.run
|
18
|
-
end
|
14
|
+
active_support_subscribed(counter.to_proc, 'sql.active_record') do
|
15
|
+
example.run
|
19
16
|
end
|
20
17
|
end
|
21
18
|
end
|
@@ -14,11 +14,7 @@ describe "octopus.rake" do
|
|
14
14
|
Rake::Task["octopus:copy_schema_versions"].reenable
|
15
15
|
|
16
16
|
path = File.expand_path("../../migrations", __FILE__)
|
17
|
-
|
18
|
-
ActiveRecord::Migrator.migrations_paths = [path]
|
19
|
-
else
|
20
|
-
ActiveRecord::Migrator.stub(:migrations_path => path)
|
21
|
-
end
|
17
|
+
ActiveRecord::Migrator.migrations_paths = [path]
|
22
18
|
end
|
23
19
|
|
24
20
|
it "assumes each shard migrated to the current master version" do
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ar-octopus
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.8.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Thiago Pradi
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2013-
|
13
|
+
date: 2013-11-01 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: activerecord
|
@@ -18,40 +18,28 @@ dependencies:
|
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
20
20
|
- !ruby/object:Gem::Version
|
21
|
-
version: 3.
|
22
|
-
- - <
|
23
|
-
- !ruby/object:Gem::Version
|
24
|
-
version: '4.0'
|
21
|
+
version: 3.2.0
|
25
22
|
type: :runtime
|
26
23
|
prerelease: false
|
27
24
|
version_requirements: !ruby/object:Gem::Requirement
|
28
25
|
requirements:
|
29
26
|
- - ! '>='
|
30
27
|
- !ruby/object:Gem::Version
|
31
|
-
version: 3.
|
32
|
-
- - <
|
33
|
-
- !ruby/object:Gem::Version
|
34
|
-
version: '4.0'
|
28
|
+
version: 3.2.0
|
35
29
|
- !ruby/object:Gem::Dependency
|
36
30
|
name: activesupport
|
37
31
|
requirement: !ruby/object:Gem::Requirement
|
38
32
|
requirements:
|
39
33
|
- - ! '>='
|
40
34
|
- !ruby/object:Gem::Version
|
41
|
-
version: 3.
|
42
|
-
- - <
|
43
|
-
- !ruby/object:Gem::Version
|
44
|
-
version: '4.0'
|
35
|
+
version: 3.2.0
|
45
36
|
type: :runtime
|
46
37
|
prerelease: false
|
47
38
|
version_requirements: !ruby/object:Gem::Requirement
|
48
39
|
requirements:
|
49
40
|
- - ! '>='
|
50
41
|
- !ruby/object:Gem::Version
|
51
|
-
version: 3.
|
52
|
-
- - <
|
53
|
-
- !ruby/object:Gem::Version
|
54
|
-
version: '4.0'
|
42
|
+
version: 3.2.0
|
55
43
|
- !ruby/object:Gem::Dependency
|
56
44
|
name: rake
|
57
45
|
requirement: !ruby/object:Gem::Requirement
|
@@ -171,8 +159,8 @@ files:
|
|
171
159
|
- Rakefile
|
172
160
|
- TODO.txt
|
173
161
|
- ar-octopus.gemspec
|
174
|
-
- gemfiles/rails31.gemfile
|
175
162
|
- gemfiles/rails32.gemfile
|
163
|
+
- gemfiles/rails4.gemfile
|
176
164
|
- init.rb
|
177
165
|
- lib/ar-octopus.rb
|
178
166
|
- lib/octopus.rb
|
@@ -182,7 +170,6 @@ files:
|
|
182
170
|
- lib/octopus/migration.rb
|
183
171
|
- lib/octopus/model.rb
|
184
172
|
- lib/octopus/proxy.rb
|
185
|
-
- lib/octopus/rails3.2/persistence.rb
|
186
173
|
- lib/octopus/rails3/abstract_adapter.rb
|
187
174
|
- lib/octopus/rails3/log_subscriber.rb
|
188
175
|
- lib/octopus/rails3/persistence.rb
|