sequel-schema-sharding 0.12.1 → 0.13.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: 212e5cc355fae7e55ca55ccd722cf9be495fd602
4
- data.tar.gz: a57f593da04a1b9e1f57d9988ecfecbb74284982
3
+ metadata.gz: 925ef9b402dcf173f9cd3a79524b1abe88ff9d46
4
+ data.tar.gz: 66794b90a0898e0ea70808311acd757eb6fcb252
5
5
  SHA512:
6
- metadata.gz: a23d79950690133c3b266b0277ce70fbf8125839f404d0f9b62d7cf2e5db00609ea5ae2aad76e608d62c8d8f0cc891ecf5c2b65ddac11ad7493d327e3c090a95
7
- data.tar.gz: b36fa474f6b495eda256ef016c937895fff6bee84046afbb0738f54c8db0228abaf233c4f64f86ad49c4559d26ef38bdc69cf0858371f73346a039705574af07
6
+ metadata.gz: a94b17459afdb2d26193fe6910c6174208aa1a3e786fc53e12783e9f5714051b167d8e714b0e6b7468d7ef1dd8c8d833d975d6f0eabaa46700c2bab809747e3d
7
+ data.tar.gz: de3348153fb3c7bb6e0f7e4752662a410e38c516970b5b56d1772c87bf29476d0aa42a6815888092347d888bf4fee59482d445c90d36a485cd75dd523b8c79f7
data/README.md CHANGED
@@ -131,6 +131,13 @@ local database name.
131
131
  See http://sequel.rubyforge.org/rdoc/files/doc/sharding_rdoc.html for more
132
132
  information.
133
133
 
134
+ Note that `sequel-schema-sharding` depends on the `sequel-replica-failover`
135
+ gem. This means that when making queries to `:read_only` servers (i.e.
136
+ replicas), certain connection errors will be rescued and re-run against
137
+ another `:read_only` server. It may be advantageous to include each master
138
+ database among its replicas, to ensure that read failures on a replica are
139
+ re-run against the master.
140
+
134
141
  ### Models
135
142
 
136
143
  Models declare their table in the class definition. This allows Sequel
@@ -203,10 +210,14 @@ queries do not try to reconnect to a downed master.
203
210
 
204
211
  ```bash
205
212
  > bundle install
206
- > bundle exec rake sequel:db:test:reset
213
+ > bundle exec rake reset
207
214
  > bundle exec rspec
208
215
  ```
209
216
 
217
+ The default max file descriptor limit on Macs is tragically low. If tests
218
+ fail with `too many open files`, you can run `ulimit -n 2048` to raise the
219
+ limit.
220
+
210
221
  ## FAQ
211
222
 
212
223
  ### How should I shard my databases?
data/Rakefile CHANGED
@@ -1,2 +1,3 @@
1
1
  require "bundler/gem_tasks"
2
2
  import 'lib/sequel/tasks/test.rake'
3
+ import 'lib/sequel/tasks/reset.rake'
@@ -10,6 +10,7 @@ require 'sequel/schema-sharding/finder'
10
10
  require 'sequel/schema-sharding/monkey_patching'
11
11
  require 'sequel/schema-sharding/model'
12
12
  require 'sequel/schema-sharding/logger_proxy'
13
+ require 'sequel/schema-sharding/connection_strategies/random'
13
14
 
14
15
  module Sequel
15
16
  module SchemaSharding
@@ -21,6 +22,14 @@ module Sequel
21
22
  @config = config
22
23
  end
23
24
 
25
+ def self.replica_strategy
26
+ @replica_strategy ||= Sequel::SchemaSharding::ConnectionStrategy::Random
27
+ end
28
+
29
+ def self.replica_strategy=(strategy)
30
+ @replica_strategy = strategy
31
+ end
32
+
24
33
  def self.logger
25
34
  @logger ||= Logger.new(nil)
26
35
  end
@@ -41,7 +41,6 @@ module Sequel
41
41
  # it (ex. %s, %02d).
42
42
 
43
43
  def schema_for(table_name, shard_number)
44
- number_of_shards = config.number_of_shards(table_name)
45
44
  pattern = config.schema_name(table_name)
46
45
  sprintf pattern, shard_number
47
46
  end
@@ -76,15 +75,14 @@ module Sequel
76
75
 
77
76
  def replica_hash_for(config)
78
77
  return {} if config['replicas'].nil?
79
- size = config['replicas'].size
80
78
  {
81
- :servers => {
82
- :read_only => ->(db) do
83
- choice = rand(size)
79
+ servers: {
80
+ read_only: ->(db) {
81
+ replica_config = Sequel::SchemaSharding.replica_strategy.choose(db, config)
84
82
  probe = Sequel::SchemaSharding::DTraceProvider.provider.replica_hash_for
85
- probe.fire(choice, size) if probe.enabled?
86
- sequel_connection_config_for(config['replicas'][choice])
87
- end
83
+ probe.fire(replica_config.inspect) if probe.enabled?
84
+ sequel_connection_config_for(replica_config)
85
+ }
88
86
  }
89
87
  }
90
88
  end
@@ -0,0 +1,21 @@
1
+ # This strategy is used for choosing a :read_only server
2
+ # to connect to.
3
+ #
4
+ # It will default to the first server in the list. In the event that
5
+ # the first server is unavailable, the remaining replicas will be
6
+ # randomly chosen from.
7
+ module Sequel
8
+ module SchemaSharding
9
+ module ConnectionStrategy
10
+ class PrimaryWithFailover
11
+ def self.choose(db, config)
12
+ if db.pool.failing_over?
13
+ config['replicas'][1..-1].sample
14
+ else
15
+ config['replicas'].first
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,16 @@
1
+ # This strategy is used for choosing a :read_only server
2
+ # to connect to.
3
+ #
4
+ # A random server will be chosen from the replica list
5
+ # for this physical shard.
6
+ module Sequel
7
+ module SchemaSharding
8
+ module ConnectionStrategy
9
+ class Random
10
+ def self.choose(db, config)
11
+ config['replicas'].sample
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -14,7 +14,7 @@ module Sequel
14
14
  end
15
15
 
16
16
  def replica_hash_for
17
- @replica_hash_for ||= provider.probe(:connection_manager, :replica_hash_for, :integer, :integer)
17
+ @replica_hash_for ||= provider.probe(:connection_manager, :replica_hash_for, :string)
18
18
  end
19
19
 
20
20
  def shard_for
@@ -12,8 +12,6 @@ module Sequel
12
12
  POINTS_PER_SERVER = 1
13
13
  PRODUCTION_SHARDS = 8192
14
14
 
15
- attr_accessor :shards, :continuum
16
-
17
15
  def initialize(shards)
18
16
  @number_of_shards = shards.size
19
17
  if ENV['RACK_ENV'] == "production"
@@ -1,5 +1,5 @@
1
1
  module Sequel
2
2
  module SchemaSharding
3
- VERSION = "0.12.1"
3
+ VERSION = "0.13.0"
4
4
  end
5
5
  end
@@ -0,0 +1 @@
1
+ task :reset => 'sequel:db:test:reset'
@@ -20,7 +20,7 @@ Gem::Specification.new do |spec|
20
20
 
21
21
  spec.add_dependency 'sequel'
22
22
  spec.add_dependency 'pg'
23
- spec.add_dependency 'sequel-replica-failover'
23
+ spec.add_dependency 'sequel-replica-failover', '>= 2.0.0'
24
24
  spec.add_dependency 'ruby-usdt', '>= 0.2.2'
25
25
 
26
26
  spec.add_development_dependency 'bundler', '~> 1.3'
@@ -35,7 +35,7 @@ describe Sequel::SchemaSharding::ConnectionManager do
35
35
 
36
36
  describe "#schema_for" do
37
37
  it "returns the schema name based on env and shard number" do
38
- subject.schema_for('boof', 3).should eq 'sequel_logical_boof_03'
38
+ expect(subject.schema_for('boof', 3)).to eq 'sequel_logical_boof_03'
39
39
  end
40
40
  end
41
41
 
@@ -0,0 +1,29 @@
1
+ require 'spec_helper'
2
+ require 'sequel/schema-sharding/connection_strategies/primary_with_failover'
3
+
4
+ describe Sequel::SchemaSharding::ConnectionStrategy::PrimaryWithFailover do
5
+ let(:db) { stub(pool: stub(failing_over?: failing_over)) }
6
+ let(:primary) { stub }
7
+ let(:failover) { stub }
8
+ let(:config) { {'replicas' => [primary, failover]} }
9
+
10
+ subject(:strategy) { Sequel::SchemaSharding::ConnectionStrategy::PrimaryWithFailover }
11
+
12
+ describe '.choose' do
13
+ context 'when primary is not failing' do
14
+ let(:failing_over) { false }
15
+
16
+ it 'returns the primary config' do
17
+ expect(strategy.choose(db, config)).to eq(primary)
18
+ end
19
+ end
20
+
21
+ context 'when primary is failing' do
22
+ let(:failing_over) { true }
23
+
24
+ it 'returns a random server that is not primary' do
25
+ expect(strategy.choose(db, config)).to eq(failover)
26
+ end
27
+ end
28
+ end
29
+ end
@@ -25,11 +25,11 @@ describe Sequel::SchemaSharding::DatabaseManager, type: :manager, sharded: true
25
25
  describe '#create_database' do
26
26
  context 'database does not exist' do
27
27
  it 'creates the database for the current environment' do
28
- expect(DatabaseHelper.db_exists?('sequel_boom_shard1')).to be_false
29
- expect(DatabaseHelper.db_exists?('sequel_boom_shard2')).to be_false
28
+ expect(DatabaseHelper.db_exists?('sequel_boom_shard1')).to be false
29
+ expect(DatabaseHelper.db_exists?('sequel_boom_shard2')).to be false
30
30
  @manager.create_databases
31
- expect(DatabaseHelper.db_exists?('sequel_boom_shard1')).to be_true
32
- expect(DatabaseHelper.db_exists?('sequel_boom_shard2')).to be_true
31
+ expect(DatabaseHelper.db_exists?('sequel_boom_shard1')).to be true
32
+ expect(DatabaseHelper.db_exists?('sequel_boom_shard2')).to be true
33
33
  end
34
34
  end
35
35
 
@@ -40,12 +40,12 @@ describe Sequel::SchemaSharding::DatabaseManager, type: :manager, sharded: true
40
40
  end
41
41
 
42
42
  it 'outputs message to stderr' do
43
- expect(DatabaseHelper.db_exists?('sequel_boom_shard1')).to be_true
44
- expect(DatabaseHelper.db_exists?('sequel_boom_shard2')).to be_true
43
+ expect(DatabaseHelper.db_exists?('sequel_boom_shard1')).to be true
44
+ expect(DatabaseHelper.db_exists?('sequel_boom_shard2')).to be true
45
45
  $stderr.expects(:puts).with(regexp_matches(/already exists/)).twice
46
46
  @manager.create_databases
47
- expect(DatabaseHelper.db_exists?('sequel_boom_shard1')).to be_true
48
- expect(DatabaseHelper.db_exists?('sequel_boom_shard2')).to be_true
47
+ expect(DatabaseHelper.db_exists?('sequel_boom_shard1')).to be true
48
+ expect(DatabaseHelper.db_exists?('sequel_boom_shard2')).to be true
49
49
  end
50
50
  end
51
51
  end
@@ -53,23 +53,23 @@ describe Sequel::SchemaSharding::DatabaseManager, type: :manager, sharded: true
53
53
  describe '#drop_databases' do
54
54
  context 'databases exist' do
55
55
  it 'drops the database for the current environment' do
56
- expect(DatabaseHelper.db_exists?('sequel_boom_shard1')).to be_false
57
- expect(DatabaseHelper.db_exists?('sequel_boom_shard2')).to be_false
56
+ expect(DatabaseHelper.db_exists?('sequel_boom_shard1')).to be false
57
+ expect(DatabaseHelper.db_exists?('sequel_boom_shard2')).to be false
58
58
 
59
59
  @manager.create_databases
60
- expect(DatabaseHelper.db_exists?('sequel_boom_shard1')).to be_true
61
- expect(DatabaseHelper.db_exists?('sequel_boom_shard2')).to be_true
60
+ expect(DatabaseHelper.db_exists?('sequel_boom_shard1')).to be true
61
+ expect(DatabaseHelper.db_exists?('sequel_boom_shard2')).to be true
62
62
 
63
63
  @manager.drop_databases
64
- expect(DatabaseHelper.db_exists?('sequel_boom_shard1')).to be_false
65
- expect(DatabaseHelper.db_exists?('sequel_boom_shard2')).to be_false
64
+ expect(DatabaseHelper.db_exists?('sequel_boom_shard1')).to be false
65
+ expect(DatabaseHelper.db_exists?('sequel_boom_shard2')).to be false
66
66
  end
67
67
  end
68
68
 
69
69
  context 'databases dont exist' do
70
70
  it 'raises an error' do
71
- expect(DatabaseHelper.db_exists?('sequel_boom_shard1')).to be_false
72
- expect(DatabaseHelper.db_exists?('sequel_boom_shard2')).to be_false
71
+ expect(DatabaseHelper.db_exists?('sequel_boom_shard1')).to be false
72
+ expect(DatabaseHelper.db_exists?('sequel_boom_shard2')).to be false
73
73
 
74
74
  $stderr.expects(:puts).with(regexp_matches(/database doesnt exist/)).times(2)
75
75
 
@@ -85,20 +85,20 @@ describe Sequel::SchemaSharding::DatabaseManager, type: :manager, sharded: true
85
85
 
86
86
  describe '#create_shards' do
87
87
  it 'creates the database structure' do
88
- expect(DatabaseHelper.schema_exists?('shard1', 'sequel_explosions_boof_01')).to be_false
89
- expect(DatabaseHelper.schema_exists?('shard1', 'sequel_explosions_artists_01')).to be_false
88
+ expect(DatabaseHelper.schema_exists?('shard1', 'sequel_explosions_boof_01')).to be false
89
+ expect(DatabaseHelper.schema_exists?('shard1', 'sequel_explosions_artists_01')).to be false
90
90
  @manager.create_shards
91
- expect(DatabaseHelper.schema_exists?('shard1', 'sequel_explosions_boof_01')).to be_true
92
- expect(DatabaseHelper.schema_exists?('shard1', 'sequel_explosions_artists_01')).to be_true
91
+ expect(DatabaseHelper.schema_exists?('shard1', 'sequel_explosions_boof_01')).to be true
92
+ expect(DatabaseHelper.schema_exists?('shard1', 'sequel_explosions_artists_01')).to be true
93
93
  end
94
94
 
95
95
  context 'shards already exist' do
96
96
  it 'prints that shards already exist' do
97
- expect(DatabaseHelper.schema_exists?('shard1', 'sequel_explosions_boof_01')).to be_false
98
- expect(DatabaseHelper.schema_exists?('shard1', 'sequel_explosions_artists_01')).to be_false
97
+ expect(DatabaseHelper.schema_exists?('shard1', 'sequel_explosions_boof_01')).to be false
98
+ expect(DatabaseHelper.schema_exists?('shard1', 'sequel_explosions_artists_01')).to be false
99
99
  @manager.create_shards
100
- expect(DatabaseHelper.schema_exists?('shard1', 'sequel_explosions_boof_01')).to be_true
101
- expect(DatabaseHelper.schema_exists?('shard1', 'sequel_explosions_artists_01')).to be_true
100
+ expect(DatabaseHelper.schema_exists?('shard1', 'sequel_explosions_boof_01')).to be true
101
+ expect(DatabaseHelper.schema_exists?('shard1', 'sequel_explosions_artists_01')).to be true
102
102
 
103
103
  $stderr.expects(:puts).with(regexp_matches(/already exists/)).at_least_once
104
104
  @manager.create_shards
@@ -109,14 +109,14 @@ describe Sequel::SchemaSharding::DatabaseManager, type: :manager, sharded: true
109
109
  describe '#drop_schemas' do
110
110
  context 'schemas exist' do
111
111
  it 'drops the schemas' do
112
- expect(DatabaseHelper.schema_exists?('shard1', 'sequel_explosions_boof_01')).to be_false
113
- expect(DatabaseHelper.schema_exists?('shard1', 'sequel_explosions_artists_01')).to be_false
112
+ expect(DatabaseHelper.schema_exists?('shard1', 'sequel_explosions_boof_01')).to be false
113
+ expect(DatabaseHelper.schema_exists?('shard1', 'sequel_explosions_artists_01')).to be false
114
114
  @manager.create_shards
115
- expect(DatabaseHelper.schema_exists?('shard1', 'sequel_explosions_boof_01')).to be_true
116
- expect(DatabaseHelper.schema_exists?('shard1', 'sequel_explosions_artists_01')).to be_true
115
+ expect(DatabaseHelper.schema_exists?('shard1', 'sequel_explosions_boof_01')).to be true
116
+ expect(DatabaseHelper.schema_exists?('shard1', 'sequel_explosions_artists_01')).to be true
117
117
  @manager.drop_shards
118
- expect(DatabaseHelper.schema_exists?('shard1', 'sequel_explosions_boof_01')).to be_false
119
- expect(DatabaseHelper.schema_exists?('shard1', 'sequel_explosions_artists_01')).to be_false
118
+ expect(DatabaseHelper.schema_exists?('shard1', 'sequel_explosions_boof_01')).to be false
119
+ expect(DatabaseHelper.schema_exists?('shard1', 'sequel_explosions_artists_01')).to be false
120
120
  end
121
121
  end
122
122
  end
@@ -25,7 +25,7 @@ describe Sequel::SchemaSharding::DTraceProvider do
25
25
  end
26
26
 
27
27
  it 'takes a string argument' do
28
- expect(provider.replica_hash_for.arguments).to eq([:integer, :integer])
28
+ expect(provider.replica_hash_for.arguments).to eq([:string])
29
29
  end
30
30
  end
31
31
 
data/spec/spec_helper.rb CHANGED
@@ -8,7 +8,6 @@ require 'support/database_helper'
8
8
  require 'mocha/api'
9
9
 
10
10
  RSpec.configure do |config|
11
- config.treat_symbols_as_metadata_keys_with_true_values = true
12
11
  config.run_all_when_everything_filtered = true
13
12
  config.filter_run :focus
14
13
  config.alias_example_to :fit, focus: true
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sequel-schema-sharding
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.12.1
4
+ version: 0.13.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Paul Henry
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2014-05-23 00:00:00.000000000 Z
13
+ date: 2014-06-20 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: sequel
@@ -46,14 +46,14 @@ dependencies:
46
46
  requirements:
47
47
  - - ">="
48
48
  - !ruby/object:Gem::Version
49
- version: '0'
49
+ version: 2.0.0
50
50
  type: :runtime
51
51
  prerelease: false
52
52
  version_requirements: !ruby/object:Gem::Requirement
53
53
  requirements:
54
54
  - - ">="
55
55
  - !ruby/object:Gem::Version
56
- version: '0'
56
+ version: 2.0.0
57
57
  - !ruby/object:Gem::Dependency
58
58
  name: ruby-usdt
59
59
  requirement: !ruby/object:Gem::Requirement
@@ -122,6 +122,8 @@ files:
122
122
  - lib/sequel/schema-sharding.rb
123
123
  - lib/sequel/schema-sharding/configuration.rb
124
124
  - lib/sequel/schema-sharding/connection_manager.rb
125
+ - lib/sequel/schema-sharding/connection_strategies/primary_with_failover.rb
126
+ - lib/sequel/schema-sharding/connection_strategies/random.rb
125
127
  - lib/sequel/schema-sharding/database_manager.rb
126
128
  - lib/sequel/schema-sharding/database_manager/schema_iterator.rb
127
129
  - lib/sequel/schema-sharding/dtrace_provider.rb
@@ -134,6 +136,7 @@ files:
134
136
  - lib/sequel/schema-sharding/monkey_patching.rb
135
137
  - lib/sequel/schema-sharding/ring.rb
136
138
  - lib/sequel/schema-sharding/version.rb
139
+ - lib/sequel/tasks/reset.rake
137
140
  - lib/sequel/tasks/test.rake
138
141
  - sequel-schema-sharding.gemspec
139
142
  - spec/fixtures/db/migrate/artists/001_create_test_table.rb
@@ -142,6 +145,7 @@ files:
142
145
  - spec/fixtures/test_db_config.yml
143
146
  - spec/schema-sharding/configuration_spec.rb
144
147
  - spec/schema-sharding/connection_manager_spec.rb
148
+ - spec/schema-sharding/connection_strategies/primary_with_failover_spec.rb
145
149
  - spec/schema-sharding/database_manager/schema_iterator_spec.rb
146
150
  - spec/schema-sharding/database_manager_spec.rb
147
151
  - spec/schema-sharding/dtrace_provider_spec.rb
@@ -170,7 +174,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
170
174
  version: '0'
171
175
  requirements: []
172
176
  rubyforge_project:
173
- rubygems_version: 2.2.0
177
+ rubygems_version: 2.2.2
174
178
  signing_key:
175
179
  specification_version: 4
176
180
  summary: Create horizontally sharded Sequel models with Postgres
@@ -181,6 +185,7 @@ test_files:
181
185
  - spec/fixtures/test_db_config.yml
182
186
  - spec/schema-sharding/configuration_spec.rb
183
187
  - spec/schema-sharding/connection_manager_spec.rb
188
+ - spec/schema-sharding/connection_strategies/primary_with_failover_spec.rb
184
189
  - spec/schema-sharding/database_manager/schema_iterator_spec.rb
185
190
  - spec/schema-sharding/database_manager_spec.rb
186
191
  - spec/schema-sharding/dtrace_provider_spec.rb