rails-sharding 0.1.1 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +4 -3
- data/lib/rails/sharding/connection_handler.rb +17 -38
- data/lib/rails/sharding/core.rb +24 -1
- data/lib/rails/sharding/shard_thread_registry.rb +8 -5
- data/lib/rails/sharding/shardable_model.rb +2 -0
- data/lib/rails/sharding/version.rb +1 -1
- data/lib/tasks/rails-sharding.rake +72 -68
- data/rails-sharding.gemspec +1 -1
- metadata +4 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cbec123e1537bac8bf7f3b6d2e711cfefa156f41
|
4
|
+
data.tar.gz: 4fae6ab76f8b687746436585a74d618c5f4a2308
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f8488d56f2e5eb38df46f138d4ad7ac28bc12008ee08383f984268fd3201629bb3eebeb54c96120bddf846e2e1f39f171e38fc4ab52457bbcdbcafa805b0e72c
|
7
|
+
data.tar.gz: 95a78672f724efa645c911d0d824b57be1dcf43d96257be54aab15e92ba544b81ce370e3a9131ee5abdd27f4605a8a49a5e45dd66dd00f4e4f58b3c7dfc48f28
|
data/README.md
CHANGED
@@ -27,7 +27,8 @@ You can also use the block syntax, where all your queries inside will be directe
|
|
27
27
|
You can also pick and choose which models will be shardable, so that all the models that are not shardable will still be retrieved from the master database, even if inside a using_shard block.
|
28
28
|
|
29
29
|
## Compatibility
|
30
|
-
|
30
|
+
Gem version 0.1.1 -> compatible with Rails 4.2
|
31
|
+
Gem version 1.0.0 -> compatible with Rails 5.0
|
31
32
|
|
32
33
|
## Installation
|
33
34
|
|
@@ -83,7 +84,7 @@ rake shards:create
|
|
83
84
|
Go to the directory `db/shards_migrations/shard_group1` and add all migrations that you want to run on the shards of `shard_group1`. By design, all shards in a same group should always have the same schema. For example, add the following migration to your `db/shards_migrations/shard_group1`:
|
84
85
|
```ruby
|
85
86
|
# 20160808000000_create_users.rb
|
86
|
-
class CreateClients < ActiveRecord::Migration
|
87
|
+
class CreateClients < ActiveRecord::Migration[5.0]
|
87
88
|
def up
|
88
89
|
create_table :users do |t|
|
89
90
|
t.string :username, :limit => 100
|
@@ -154,4 +155,4 @@ The gem is available as open source under the terms of the [MIT License](http://
|
|
154
155
|
|
155
156
|
## Acknowledgements
|
156
157
|
|
157
|
-
This gem was inspired
|
158
|
+
This gem was inspired on several other gems like: [octopus](https://github.com/thiagopradi/octopus), [shard_handler](https://github.com/locaweb/shard_handler) and [active_record_shards](https://github.com/zendesk/active_record_shards).
|
@@ -17,40 +17,43 @@ module Rails::Sharding
|
|
17
17
|
def self.establish_connection(shard_group, shard_name, environment=nil)
|
18
18
|
self.setup unless defined? @@connection_handler
|
19
19
|
|
20
|
-
|
20
|
+
configurations = (environment.nil? ? Core.configurations : Core.configurations(environment))
|
21
|
+
if configurations.nil?
|
21
22
|
raise Errors::ConfigNotFoundError, "Cannot find configuration for environment '#{environment}' in #{Config.shards_config_file}"
|
22
23
|
end
|
23
24
|
|
24
|
-
|
25
|
+
shard_group_configurations = configurations[shard_group.to_s]
|
26
|
+
if shard_group_configurations.nil?
|
25
27
|
raise Errors::ConfigNotFoundError, "Cannot find configuration for shard_group '#{shard_group}' in environment '#{environment}' in #{Config.shards_config_file}"
|
26
28
|
end
|
27
29
|
|
28
30
|
resolver = ActiveRecord::ConnectionAdapters::ConnectionSpecification::Resolver.new(shard_group_configurations)
|
29
31
|
begin
|
30
|
-
|
31
|
-
|
32
|
+
connection_name = connection_name(shard_group, shard_name)
|
33
|
+
connection_spec = resolver.spec(shard_name.to_sym, connection_name)
|
34
|
+
rescue ActiveRecord::AdapterNotSpecified
|
32
35
|
raise Errors::ConfigNotFoundError, "Cannot find configuration for shard '#{shard_group}:#{shard_name}' in environment '#{environment}' in #{Config.shards_config_file}"
|
33
36
|
end
|
34
37
|
|
35
|
-
|
36
|
-
# an instance of the ConnectionPoolOwner class, that responds to the #name method
|
37
|
-
connection_handler.establish_connection(connection_pool_owner(shard_group, shard_name), connection_spec)
|
38
|
+
connection_handler.establish_connection(connection_spec)
|
38
39
|
end
|
39
40
|
|
40
41
|
def self.connection_pool(shard_group, shard_name)
|
41
|
-
connection_handler.retrieve_connection_pool(
|
42
|
-
|
42
|
+
if connection_pool = connection_handler.retrieve_connection_pool(connection_name(shard_group, shard_name))
|
43
|
+
return connection_pool
|
44
|
+
end
|
45
|
+
|
43
46
|
# mimicking behavior of rails at:
|
44
|
-
# https://github.com/rails/rails/blob/
|
45
|
-
raise ActiveRecord::ConnectionNotEstablished, "No connection pool for shard #{connection_name(shard_group, shard_name)}"
|
47
|
+
# https://github.com/rails/rails/blob/v5.0.0.1/activerecord/lib/active_record/connection_handling.rb#124
|
48
|
+
raise ActiveRecord::ConnectionNotEstablished, "No connection pool for shard #{connection_name(shard_group, shard_name)}" if connection_pool.nil?
|
46
49
|
end
|
47
50
|
|
48
51
|
def self.retrieve_connection(shard_group, shard_name)
|
49
|
-
connection_handler.retrieve_connection(
|
52
|
+
connection_handler.retrieve_connection(connection_name(shard_group, shard_name))
|
50
53
|
end
|
51
54
|
|
52
55
|
def self.connected?(shard_group, shard_name)
|
53
|
-
connection_handler.connected?(
|
56
|
+
connection_handler.connected?(connection_name(shard_group, shard_name))
|
54
57
|
end
|
55
58
|
|
56
59
|
def self.with_connection(shard_group, shard_name, &block)
|
@@ -58,7 +61,7 @@ module Rails::Sharding
|
|
58
61
|
end
|
59
62
|
|
60
63
|
def self.remove_connection(shard_group, shard_name)
|
61
|
-
connection_handler.remove_connection(
|
64
|
+
connection_handler.remove_connection(connection_name(shard_group, shard_name))
|
62
65
|
end
|
63
66
|
|
64
67
|
private
|
@@ -70,35 +73,11 @@ module Rails::Sharding
|
|
70
73
|
|
71
74
|
def self.setup
|
72
75
|
@@connection_handler = ActiveRecord::ConnectionAdapters::ConnectionHandler.new
|
73
|
-
@@connection_pool_owners = {}
|
74
|
-
end
|
75
|
-
|
76
|
-
def self.connection_pool_owner(shard_group, shard_name)
|
77
|
-
connection_name = self.connection_name(shard_group, shard_name)
|
78
|
-
@@connection_pool_owners[connection_name] ||= ConnectionPoolOwner.new(connection_name)
|
79
76
|
end
|
80
77
|
|
81
78
|
# Assembles connection name in the format "shard_group:shard_name"
|
82
79
|
def self.connection_name(shard_group, shard_name)
|
83
80
|
shard_group.to_s + ':' + shard_name.to_s
|
84
81
|
end
|
85
|
-
|
86
|
-
class ConnectionPoolOwner
|
87
|
-
attr_reader :name
|
88
|
-
|
89
|
-
def initialize(name)
|
90
|
-
@name = name
|
91
|
-
end
|
92
|
-
|
93
|
-
# Safeguard in case pool cannot be retrieved for owner. This makes the error clear
|
94
|
-
def superclass
|
95
|
-
raise Errors::ConnectionPoolRetrievalError, "ConnectionPool could not be retrieved for #{self}. See https://github.com/rails/rails/blob/4-2-stable/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb#607"
|
96
|
-
end
|
97
|
-
|
98
|
-
# in case owner ends up printed by rails in an error message when retrieving connection
|
99
|
-
def to_s
|
100
|
-
"ConnectionPoolOwner with name #{self.name}"
|
101
|
-
end
|
102
|
-
end
|
103
82
|
end
|
104
83
|
end
|
data/lib/rails/sharding/core.rb
CHANGED
@@ -14,8 +14,14 @@ module Rails::Sharding
|
|
14
14
|
|
15
15
|
ShardThreadRegistry.current_shard_group = shard_group
|
16
16
|
ShardThreadRegistry.current_shard_name = shard_name
|
17
|
+
ShardThreadRegistry.shard_connection_used = false
|
17
18
|
yield
|
18
19
|
ensure
|
20
|
+
# shows warning to user
|
21
|
+
if !ShardThreadRegistry.shard_connection_used
|
22
|
+
puts "Warning: no connection to shard '#{ShardThreadRegistry.current_shard_group}:#{ShardThreadRegistry.current_shard_name}' was made inside the using_shard block. Make sure you don't forget to include Rails::Sharding::ShardableModel to the models you want to be sharded"
|
23
|
+
end
|
24
|
+
|
19
25
|
# Releases connections in case user left some connection in the reserved state
|
20
26
|
# (by calling retrieve_connection instead of with_connection). Also, using
|
21
27
|
# normal activerecord queries leaves a connection in the reserved state
|
@@ -26,7 +32,7 @@ module Rails::Sharding
|
|
26
32
|
def self.configurations(environment=Rails.env)
|
27
33
|
@@db_configs ||= YAML.load_file(Config.shards_config_file)
|
28
34
|
@@db_configs[environment]
|
29
|
-
rescue Errno::ENOENT
|
35
|
+
rescue Errno::ENOENT
|
30
36
|
raise Errors::ConfigNotFoundError, Config.shards_config_file.to_s + ' file was not found'
|
31
37
|
end
|
32
38
|
|
@@ -46,6 +52,23 @@ module Rails::Sharding
|
|
46
52
|
self.configurations[shard_group.to_s].keys
|
47
53
|
end
|
48
54
|
|
55
|
+
# yields a block for each shard in each shard group, with its configurations
|
56
|
+
# shard_group_filter: if passed yields only shards of this group
|
57
|
+
# shard_name_filter: if passed yields only shards with this name
|
58
|
+
def self.for_each_shard(shard_group_filter=nil, shard_name_filter=nil)
|
59
|
+
shard_group_filter.to_s if shard_group_filter
|
60
|
+
shard_name_filter.to_s if shard_name_filter
|
61
|
+
|
62
|
+
configurations.each do |shard_group, shards_configurations|
|
63
|
+
next if shard_group_filter && shard_group_filter != shard_group.to_s
|
64
|
+
|
65
|
+
shards_configurations.each do |shard, configuration|
|
66
|
+
next if shard_name_filter && shard_name_filter != shard.to_s
|
67
|
+
yield shard_group, shard, configuration
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
49
72
|
# Method that should be called on a rails initializer
|
50
73
|
def self.setup
|
51
74
|
if block_given?
|
@@ -1,11 +1,13 @@
|
|
1
|
-
require 'active_support/per_thread_registry'
|
2
1
|
|
3
2
|
module Rails::Sharding
|
4
3
|
class ShardThreadRegistry
|
5
|
-
# creates two thread-specific variables
|
6
|
-
|
7
|
-
|
8
|
-
|
4
|
+
# creates two thread-specific variables to store the current shard of connection
|
5
|
+
thread_mattr_accessor :_current_shard_group
|
6
|
+
thread_mattr_accessor :_current_shard_name
|
7
|
+
|
8
|
+
# auxiliary variable used to check if shard connectio was used inside an
|
9
|
+
# using_shard block (so we can print an alert if not)
|
10
|
+
thread_mattr_accessor :shard_connection_used
|
9
11
|
|
10
12
|
def self.connecting_to_master?
|
11
13
|
current_shard_group.nil? || current_shard_name.nil?
|
@@ -18,6 +20,7 @@ module Rails::Sharding
|
|
18
20
|
def self.connect_back_to_master!
|
19
21
|
self.current_shard_group = nil
|
20
22
|
self.current_shard_name = nil
|
23
|
+
self.shard_connection_used = false
|
21
24
|
end
|
22
25
|
|
23
26
|
# Returns the current shard group (for the current Thread)
|
@@ -35,6 +35,7 @@ module Rails::Sharding
|
|
35
35
|
if ShardThreadRegistry.connecting_to_master?
|
36
36
|
return original_connection_pool
|
37
37
|
else
|
38
|
+
ShardThreadRegistry.shard_connection_used = true # records that shard connection was used at least once
|
38
39
|
return ConnectionHandler.connection_pool(*ShardThreadRegistry.current_shard_group_and_name)
|
39
40
|
end
|
40
41
|
end
|
@@ -44,6 +45,7 @@ module Rails::Sharding
|
|
44
45
|
if ShardThreadRegistry.connecting_to_master?
|
45
46
|
return original_retrieve_connection
|
46
47
|
else
|
48
|
+
ShardThreadRegistry.shard_connection_used = true # records that shard connection was used at least once
|
47
49
|
return ConnectionHandler.retrieve_connection(*ShardThreadRegistry.current_shard_group_and_name)
|
48
50
|
end
|
49
51
|
end
|
@@ -8,29 +8,36 @@ shards_namespace = namespace :shards do
|
|
8
8
|
ActiveRecord::Base.include(Rails::Sharding::ShardableModel) unless ActiveRecord::Base.ancestors.include? Rails::Sharding::ShardableModel
|
9
9
|
end
|
10
10
|
|
11
|
-
|
12
|
-
|
11
|
+
# for each of the shards, check that 1) the environment set in the ar_internal_metadata
|
12
|
+
# table matches the current rails env and 2) it is not a protected environment
|
13
|
+
# (defined in ActiveRecord::Base.protected_environments)
|
14
|
+
desc "Checks if the environment is not protected and if the shards match the current environment (options: RAILS_ENV=x SHARD_GROUP=x SHARD=x)"
|
15
|
+
task check_protected_environments: [:_make_activerecord_base_shardable] do
|
13
16
|
Rails::Sharding.configurations.each do |shard_group, shards_configurations|
|
14
17
|
next if ENV["SHARD_GROUP"] && ENV["SHARD_GROUP"] != shard_group.to_s
|
15
18
|
|
16
|
-
shards_configurations.each do |shard,
|
19
|
+
shards_configurations.each do |shard, _|
|
17
20
|
next if ENV["SHARD"] && ENV["SHARD"] != shard.to_s
|
18
|
-
|
19
|
-
|
21
|
+
Rails::Sharding.using_shard(shard_group, shard) do
|
22
|
+
ActiveRecord::Tasks::DatabaseTasks.check_protected_environments!
|
23
|
+
end
|
20
24
|
end
|
21
25
|
end
|
22
26
|
end
|
23
27
|
|
24
|
-
desc "
|
25
|
-
task
|
26
|
-
Rails::Sharding.
|
27
|
-
|
28
|
+
desc "Creates database shards (options: RAILS_ENV=x SHARD_GROUP=x SHARD=x)"
|
29
|
+
task create: [:environment] do
|
30
|
+
Rails::Sharding.for_each_shard(ENV["SHARD_GROUP"], ENV["SHARD"]) do |shard_group, shard, configuration|
|
31
|
+
puts "== Creating shard #{shard_group}:#{shard}"
|
32
|
+
ActiveRecord::Tasks::DatabaseTasks.create(configuration)
|
33
|
+
end
|
34
|
+
end
|
28
35
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
36
|
+
desc "Drops database shards (options: RAILS_ENV=x SHARD_GROUP=x SHARD=x)"
|
37
|
+
task drop: [:environment, :check_protected_environments] do
|
38
|
+
Rails::Sharding.for_each_shard(ENV["SHARD_GROUP"], ENV["SHARD"]) do |shard_group, shard, configuration|
|
39
|
+
puts "== Dropping shard #{shard_group}:#{shard}"
|
40
|
+
ActiveRecord::Tasks::DatabaseTasks.drop(configuration)
|
34
41
|
end
|
35
42
|
end
|
36
43
|
|
@@ -40,11 +47,9 @@ shards_namespace = namespace :shards do
|
|
40
47
|
next if ENV["SHARD_GROUP"] && ENV["SHARD_GROUP"] != shard_group.to_s
|
41
48
|
|
42
49
|
# configures path for migrations of this shard group and creates dir if necessary
|
43
|
-
|
44
|
-
ActiveRecord::Tasks::DatabaseTasks.migrations_paths = shard_group_migrations_dir
|
45
|
-
FileUtils.mkdir_p(shard_group_migrations_dir)
|
50
|
+
setup_migrations_path(shard_group)
|
46
51
|
|
47
|
-
shards_configurations.each do |shard,
|
52
|
+
shards_configurations.each do |shard, _|
|
48
53
|
next if ENV["SHARD"] && ENV["SHARD"] != shard.to_s
|
49
54
|
puts "== Migrating shard #{shard_group}:#{shard}"
|
50
55
|
Rails::Sharding.using_shard(shard_group, shard) do
|
@@ -78,18 +83,13 @@ shards_namespace = namespace :shards do
|
|
78
83
|
task dump: [:_make_activerecord_base_shardable] do
|
79
84
|
require "active_record/schema_dumper"
|
80
85
|
|
81
|
-
Rails::Sharding.
|
82
|
-
|
86
|
+
Rails::Sharding.for_each_shard(ENV["SHARD_GROUP"], ENV["SHARD"]) do |shard_group, shard, _configuration|
|
87
|
+
puts "== Dumping schema of #{shard_group}:#{shard}"
|
83
88
|
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
schema_filename = shard_schema_path(shard_group, shard)
|
89
|
-
File.open(schema_filename, "w:utf-8") do |file|
|
90
|
-
Rails::Sharding.using_shard(shard_group, shard) do
|
91
|
-
ActiveRecord::SchemaDumper.dump(Rails::Sharding::ConnectionHandler.retrieve_connection(shard_group, shard), file)
|
92
|
-
end
|
89
|
+
schema_filename = shard_schema_path(shard_group, shard)
|
90
|
+
File.open(schema_filename, "w:utf-8") do |file|
|
91
|
+
Rails::Sharding.using_shard(shard_group, shard) do
|
92
|
+
ActiveRecord::SchemaDumper.dump(Rails::Sharding::ConnectionHandler.retrieve_connection(shard_group, shard), file)
|
93
93
|
end
|
94
94
|
end
|
95
95
|
end
|
@@ -100,13 +100,14 @@ shards_namespace = namespace :shards do
|
|
100
100
|
end
|
101
101
|
|
102
102
|
desc "Loads schema.rb file into the shards (options: RAILS_ENV=x, SHARD_GROUP=x, SHARD=x)"
|
103
|
-
task load: [:_make_activerecord_base_shardable] do
|
103
|
+
task load: [:_make_activerecord_base_shardable, :check_protected_environments] do
|
104
104
|
Rails::Sharding.configurations.each do |shard_group, shards_configurations|
|
105
105
|
next if ENV["SHARD_GROUP"] && ENV["SHARD_GROUP"] != shard_group.to_s
|
106
106
|
|
107
|
+
# configures path for migrations of this shard group and creates dir if necessary
|
107
108
|
setup_migrations_path(shard_group)
|
108
109
|
|
109
|
-
shards_configurations.each do |shard,
|
110
|
+
shards_configurations.each do |shard, _|
|
110
111
|
next if ENV["SHARD"] && ENV["SHARD"] != shard.to_s
|
111
112
|
puts "== Loading schema of #{shard_group}:#{shard}"
|
112
113
|
|
@@ -125,7 +126,7 @@ shards_namespace = namespace :shards do
|
|
125
126
|
end
|
126
127
|
|
127
128
|
namespace :migrate do
|
128
|
-
desc
|
129
|
+
desc 'Rollbacks the shards one migration and re migrate up (options: RAILS_ENV=x, VERSION=x, STEP=x, SHARD_GROUP=x, SHARD=x).'
|
129
130
|
task redo: [:environment] do
|
130
131
|
if ENV["VERSION"]
|
131
132
|
shards_namespace["migrate:down"].invoke
|
@@ -141,15 +142,15 @@ shards_namespace = namespace :shards do
|
|
141
142
|
|
142
143
|
desc 'Runs the "up" for a given migration VERSION.'
|
143
144
|
task up: [:_make_activerecord_base_shardable] do
|
144
|
-
version =
|
145
|
-
raise "VERSION is required" unless version
|
145
|
+
version = get_version_or_else "VERSION is required"
|
146
146
|
|
147
147
|
Rails::Sharding.configurations.each do |shard_group, shards_configurations|
|
148
148
|
next if ENV["SHARD_GROUP"] && ENV["SHARD_GROUP"] != shard_group.to_s
|
149
149
|
|
150
|
+
# configures path for migrations of this shard group and creates dir if necessary
|
150
151
|
setup_migrations_path(shard_group)
|
151
152
|
|
152
|
-
shards_configurations.each do |shard,
|
153
|
+
shards_configurations.each do |shard, _|
|
153
154
|
next if ENV["SHARD"] && ENV["SHARD"] != shard.to_s
|
154
155
|
puts "== Migrating up shard #{shard_group}:#{shard}"
|
155
156
|
Rails::Sharding.using_shard(shard_group, shard) do
|
@@ -163,15 +164,15 @@ shards_namespace = namespace :shards do
|
|
163
164
|
|
164
165
|
desc 'Runs the "down" for a given migration VERSION.'
|
165
166
|
task down: [:_make_activerecord_base_shardable] do
|
166
|
-
version =
|
167
|
-
raise "VERSION is required - To go down one migration, run db:rollback" unless version
|
167
|
+
version = get_version_or_else "VERSION is required - To go down one migration, run db:rollback"
|
168
168
|
|
169
169
|
Rails::Sharding.configurations.each do |shard_group, shards_configurations|
|
170
170
|
next if ENV["SHARD_GROUP"] && ENV["SHARD_GROUP"] != shard_group.to_s
|
171
171
|
|
172
|
+
# configures path for migrations of this shard group and creates dir if necessary
|
172
173
|
setup_migrations_path(shard_group)
|
173
174
|
|
174
|
-
shards_configurations.each do |shard,
|
175
|
+
shards_configurations.each do |shard, _|
|
175
176
|
next if ENV["SHARD"] && ENV["SHARD"] != shard.to_s
|
176
177
|
puts "== Migrating down shard #{shard_group}:#{shard}"
|
177
178
|
Rails::Sharding.using_shard(shard_group, shard) do
|
@@ -190,9 +191,10 @@ shards_namespace = namespace :shards do
|
|
190
191
|
Rails::Sharding.configurations.each do |shard_group, shards_configurations|
|
191
192
|
next if ENV["SHARD_GROUP"] && ENV["SHARD_GROUP"] != shard_group.to_s
|
192
193
|
|
194
|
+
# configures path for migrations of this shard group and creates dir if necessary
|
193
195
|
setup_migrations_path(shard_group)
|
194
196
|
|
195
|
-
shards_configurations.each do |shard,
|
197
|
+
shards_configurations.each do |shard, _|
|
196
198
|
next if ENV["SHARD"] && ENV["SHARD"] != shard.to_s
|
197
199
|
puts "== Rolling back shard #{shard_group}:#{shard}"
|
198
200
|
Rails::Sharding.using_shard(shard_group, shard) do
|
@@ -206,15 +208,9 @@ shards_namespace = namespace :shards do
|
|
206
208
|
|
207
209
|
desc "Retrieves the current schema version number"
|
208
210
|
task version: [:_make_activerecord_base_shardable] do
|
209
|
-
Rails::Sharding.
|
210
|
-
|
211
|
-
|
212
|
-
shards_configurations.each do |shard, configuration|
|
213
|
-
next if ENV["SHARD"] && ENV["SHARD"] != shard.to_s
|
214
|
-
|
215
|
-
Rails::Sharding.using_shard(shard_group, shard) do
|
216
|
-
puts "Shard #{shard_group}:#{shard} version: #{ActiveRecord::Migrator.current_version}"
|
217
|
-
end
|
211
|
+
Rails::Sharding.for_each_shard(ENV["SHARD_GROUP"], ENV["SHARD"]) do |shard_group, shard, _configuration|
|
212
|
+
Rails::Sharding.using_shard(shard_group, shard) do
|
213
|
+
puts "Shard #{shard_group}:#{shard} version: #{ActiveRecord::Migrator.current_version}"
|
218
214
|
end
|
219
215
|
end
|
220
216
|
end
|
@@ -226,9 +222,10 @@ shards_namespace = namespace :shards do
|
|
226
222
|
Rails::Sharding.test_configurations.each do |shard_group, shards_configurations|
|
227
223
|
next if ENV["SHARD_GROUP"] && ENV["SHARD_GROUP"] != shard_group.to_s
|
228
224
|
|
225
|
+
# configures path for migrations of this shard group and creates dir if necessary
|
229
226
|
setup_migrations_path(shard_group)
|
230
227
|
|
231
|
-
shards_configurations.each do |shard,
|
228
|
+
shards_configurations.each do |shard, _|
|
232
229
|
next if ENV["SHARD"] && ENV["SHARD"] != shard.to_s
|
233
230
|
|
234
231
|
puts "== Loading test schema on shard #{shard_group}:#{shard}"
|
@@ -237,6 +234,10 @@ shards_namespace = namespace :shards do
|
|
237
234
|
should_reconnect = Rails::Sharding::ConnectionHandler.connection_pool(shard_group, shard).active_connection?
|
238
235
|
Rails::Sharding::ConnectionHandler.establish_connection(shard_group, shard, 'test')
|
239
236
|
|
237
|
+
# saves the current RAILS_ENV (we must change it so the environment is set correcly on the metadata table)
|
238
|
+
initial_rails_env = Rails.env
|
239
|
+
Rails.env = 'test'
|
240
|
+
|
240
241
|
schema_filename = shard_schema_path(shard_group, shard)
|
241
242
|
ActiveRecord::Tasks::DatabaseTasks.check_schema_file(schema_filename)
|
242
243
|
Rails::Sharding.using_shard(shard_group, shard) do
|
@@ -244,6 +245,9 @@ shards_namespace = namespace :shards do
|
|
244
245
|
load(schema_filename)
|
245
246
|
end
|
246
247
|
ensure
|
248
|
+
# restores rails env
|
249
|
+
Rails.env = initial_rails_env
|
250
|
+
|
247
251
|
if should_reconnect
|
248
252
|
# reestablishes connection for RAILS_ENV environment (whatever that is)
|
249
253
|
Rails::Sharding::ConnectionHandler.establish_connection(shard_group, shard)
|
@@ -262,26 +266,20 @@ shards_namespace = namespace :shards do
|
|
262
266
|
|
263
267
|
desc "Empty the test shards (drops all tables) (options: SHARD_GROUP=x, SHARD=x)"
|
264
268
|
task :purge => [:_make_activerecord_base_shardable] do
|
265
|
-
Rails::Sharding.
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
puts "== Purging test shard #{shard_group}:#{shard}"
|
272
|
-
begin
|
273
|
-
# establishes connection with test shard, saving if it was connected before (rails 4.2 doesn't do this, but should)
|
274
|
-
should_reconnect = Rails::Sharding::ConnectionHandler.connection_pool(shard_group, shard).active_connection?
|
275
|
-
Rails::Sharding::ConnectionHandler.establish_connection(shard_group, shard, 'test')
|
269
|
+
Rails::Sharding.for_each_shard(ENV["SHARD_GROUP"], ENV["SHARD"]) do |shard_group, shard, configuration|
|
270
|
+
puts "== Purging test shard #{shard_group}:#{shard}"
|
271
|
+
begin
|
272
|
+
# establishes connection with test shard, saving if it was connected before (rails 4.2 doesn't do this, but should)
|
273
|
+
should_reconnect = Rails::Sharding::ConnectionHandler.connection_pool(shard_group, shard).active_connection?
|
274
|
+
Rails::Sharding::ConnectionHandler.establish_connection(shard_group, shard, 'test')
|
276
275
|
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
end
|
276
|
+
Rails::Sharding.using_shard(shard_group, shard) do
|
277
|
+
ActiveRecord::Tasks::DatabaseTasks.purge(configuration)
|
278
|
+
end
|
279
|
+
ensure
|
280
|
+
if should_reconnect
|
281
|
+
# reestablishes connection for RAILS_ENV environment (whatever that is)
|
282
|
+
Rails::Sharding::ConnectionHandler.establish_connection(shard_group, shard)
|
285
283
|
end
|
286
284
|
end
|
287
285
|
end
|
@@ -304,4 +302,10 @@ shards_namespace = namespace :shards do
|
|
304
302
|
FileUtils.mkdir_p(shard_group_schemas_dir)
|
305
303
|
File.join(shard_group_schemas_dir, shard_name + "_schema.rb")
|
306
304
|
end
|
305
|
+
|
306
|
+
def get_version_or_else(error_message='VERSION is required')
|
307
|
+
version = ENV["VERSION"] ? ENV["VERSION"].to_i : nil
|
308
|
+
raise error_message unless version
|
309
|
+
version
|
310
|
+
end
|
307
311
|
end
|
data/rails-sharding.gemspec
CHANGED
@@ -23,7 +23,7 @@ Gem::Specification.new do |spec|
|
|
23
23
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
24
24
|
spec.require_paths = ["lib"]
|
25
25
|
|
26
|
-
spec.add_runtime_dependency 'rails', '
|
26
|
+
spec.add_runtime_dependency 'rails', '~> 5.0'
|
27
27
|
|
28
28
|
spec.add_development_dependency "bundler", "~> 1.12"
|
29
29
|
spec.add_development_dependency "rake", "~> 10.0"
|
metadata
CHANGED
@@ -1,33 +1,27 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rails-sharding
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Henrique Gubert
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-10-
|
11
|
+
date: 2016-10-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
18
|
-
- !ruby/object:Gem::Version
|
19
|
-
version: '4.2'
|
20
|
-
- - "<"
|
17
|
+
- - "~>"
|
21
18
|
- !ruby/object:Gem::Version
|
22
19
|
version: '5.0'
|
23
20
|
type: :runtime
|
24
21
|
prerelease: false
|
25
22
|
version_requirements: !ruby/object:Gem::Requirement
|
26
23
|
requirements:
|
27
|
-
- - "
|
28
|
-
- !ruby/object:Gem::Version
|
29
|
-
version: '4.2'
|
30
|
-
- - "<"
|
24
|
+
- - "~>"
|
31
25
|
- !ruby/object:Gem::Version
|
32
26
|
version: '5.0'
|
33
27
|
- !ruby/object:Gem::Dependency
|