sequel-schema-sharding 0.12.1 → 0.13.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: 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