sequel-schema-sharding 0.11.1 → 0.12.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: 856de612ab94179af8d327fab5aa6b6f0cd77e5c
4
- data.tar.gz: 76cff6fb49277e3f8526980e68cbb165943c1349
3
+ metadata.gz: e9d2a8dea7d18fc038c01e427503dc01aa6b24f0
4
+ data.tar.gz: 8033c5b54ac76371fe1f0f3074f75d10d33e14fe
5
5
  SHA512:
6
- metadata.gz: 9a1e1bcc2b1b010375be855c567ea52f5f776e76f90f64c6fca2f6c3af6a511d639fdeb26016834ec49b94dbb659af30deedec103858f4f1f35a83597e327163
7
- data.tar.gz: a0f59b3a1d3344f752997aa15017a5f65fe99d92fa0e89282872259777a73e79019eb801dd4570d12e3558bfd167c3d44bb7b18722224c90459e81cd72289c7b
6
+ metadata.gz: 56f54ffdeb952181d59b683e74312c3387bc0edeb037c11b2d658d5a653b0e5eef867d44139c56c2ce6f6179d4d0275c1c70efe7abfd7696cfcbe837605547cb
7
+ data.tar.gz: 3d980233dd79fd9eac01f56550885d3a02589f1b0b95718dbad2d47aa5d5750b7225f134819a871759e3d9a3f4e4805f4e496ca82b4ee35688f63e9fc76c4ab4
data/Gemfile CHANGED
@@ -8,7 +8,4 @@ group :test do
8
8
  gem 'mocha', require: false
9
9
  gem 'pry-nav'
10
10
  gem 'guard-rspec'
11
-
12
- # for testing purposes until pull request is accepted
13
- gem 'ruby-usdt', github: 'sax/ruby-usdt', ref: 'probe-introspection', submodules: true
14
11
  end
data/README.md CHANGED
@@ -1,7 +1,9 @@
1
1
  sequel-schema-sharding
2
2
  ======================
3
3
 
4
+ [![Gem Version](https://badge.fury.io/rb/sequel-schema-sharding.png)](http://badge.fury.io/rb/sequel-schema-sharding)
4
5
  [![Build Status](https://travis-ci.org/wanelo/sequel-schema-sharding.png?branch=master)](https://travis-ci.org/wanelo/sequel-schema-sharding)
6
+ [![Code Climate](https://codeclimate.com/github/wanelo/sequel-schema-sharding.png)](https://codeclimate.com/github/wanelo/sequel-schema-sharding)
5
7
 
6
8
  Horizontally shard PostgreSQL tables with the Sequel gem, where each shard
7
9
  lives in its own PostgreSQL schema.
@@ -201,7 +203,7 @@ queries do not try to reconnect to a downed master.
201
203
 
202
204
  ```bash
203
205
  > bundle install
204
- > bundle exec rake sequel:db:create
206
+ > bundle exec rake sequel:db:test:reset
205
207
  > bundle exec rspec
206
208
  ```
207
209
 
@@ -325,6 +327,18 @@ mapping, but any attempt to read a record inserted via the old mapping
325
327
  will pick the wrong shard and return an empty set. DON'T EVER DO THIS.
326
328
  It's really embarrassing.
327
329
 
330
+ ### Any problems with other services?
331
+
332
+ When integrating with NewRelic, *do not* enable the SQL query plan
333
+ instrumentation. It can grab a connection that your application is also
334
+ trying to use... libpq is thread safe, so long as two threads do not
335
+ try to manipulate the same PGonn object
336
+ (http://www.postgresql.org/docs/9.3/static/libpq-threading.html).
337
+ If you see errors such as `PG::UnableToSend: insufficient data in "T" message`
338
+ or `PG::UnableToSend: extraneous data in "T" message`, this can indicate that
339
+ multiple threads are accessing the same connection, and data (or random bytes)
340
+ may have been transposed between queries.
341
+
328
342
 
329
343
  ## Contributing
330
344
 
@@ -0,0 +1,21 @@
1
+ module Sequel
2
+ module Plugins
3
+ module DatasetShardId
4
+ module InstanceMethods
5
+ def shard_number
6
+ @values[:shard_number] if @values
7
+ end
8
+ end
9
+
10
+ module DatasetMethods
11
+ def shard_number
12
+ @shard_number
13
+ end
14
+
15
+ def shard_number=(id)
16
+ @shard_number=id
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -77,16 +77,13 @@ module Sequel
77
77
  def replica_hash_for(config)
78
78
  return {} if config['replicas'].nil?
79
79
  size = config['replicas'].size
80
- i = rand(size)
81
80
  {
82
81
  :servers => {
83
82
  :read_only => ->(db) do
84
- choice = i % size
83
+ choice = rand(size)
85
84
  probe = Sequel::SchemaSharding::DTraceProvider.provider.replica_hash_for
86
85
  probe.fire(choice, size) if probe.enabled?
87
- sequel_connection_config_for(config['replicas'][choice]).tap do
88
- i += 1
89
- end
86
+ sequel_connection_config_for(config['replicas'][choice])
90
87
  end
91
88
  }
92
89
  }
@@ -0,0 +1,16 @@
1
+ module Sequel
2
+ module Postgres
3
+ class Dataset
4
+ alias_method :adapter_fetch_rows, :fetch_rows
5
+
6
+ def fetch_rows(sql, &block)
7
+ adapter_fetch_rows(sql) do |r|
8
+ if self.respond_to?(:shard_number)
9
+ r[:shard_number] = self.shard_number
10
+ end
11
+ block.call r
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -1,16 +1,20 @@
1
1
  module Sequel
2
- module SchemaSharding
3
- module Extensions
4
- module SequelExt
5
- module ClassMethods
6
- def db
7
- return @db if @db
8
- end
2
+ class Database
3
+ class << self
4
+ alias_method :sequel_adapter_class, :adapter_class
5
+
6
+ def adapter_class(scheme)
7
+ klass = sequel_adapter_class(scheme)
8
+
9
+ begin
10
+ require "sequel/schema-sharding/extensions/#{scheme}/dataset"
11
+ rescue LoadError => e
9
12
  end
13
+
14
+ klass
10
15
  end
11
16
  end
12
17
  end
13
18
  end
14
19
 
15
- Sequel::Model.plugin Sequel::SchemaSharding::Extensions::SequelExt
16
20
  Sequel::Model.plugin :validation_helpers
@@ -4,11 +4,12 @@ module Sequel
4
4
  module SchemaSharding
5
5
  class Finder
6
6
  class Result
7
- attr_reader :connection, :schema
7
+ attr_reader :connection, :schema, :shard_number
8
8
 
9
- def initialize(connection, schema)
9
+ def initialize(connection, schema, shard_number)
10
10
  @connection = connection
11
11
  @schema = schema
12
+ @shard_number = shard_number
12
13
  end
13
14
  end
14
15
 
@@ -21,7 +22,7 @@ module Sequel
21
22
  conn = Sequel::SchemaSharding.connection_manager[physical_shard]
22
23
  schema = Sequel::SchemaSharding.connection_manager.schema_for(table_name, shard_number)
23
24
 
24
- Result.new(conn, schema)
25
+ Result.new(conn, schema, shard_number)
25
26
  end
26
27
 
27
28
  private
@@ -28,6 +28,7 @@ module Sequel
28
28
 
29
29
  def self.included(base)
30
30
  base.extend(ClassMethods)
31
+ base.plugin(:dataset_shard_id)
31
32
  end
32
33
 
33
34
  module ClassMethods
@@ -53,6 +54,7 @@ module Sequel
53
54
  ds = result.connection[schema_and_table(result)]
54
55
  ds.row_proc = self
55
56
  dataset_method_modules.each { |m| ds.instance_eval { extend(m) } }
57
+ ds.shard_number = result.shard_number
56
58
  ds.model = self
57
59
  ds
58
60
  end
@@ -71,6 +73,14 @@ module Sequel
71
73
  def schema_and_table(result)
72
74
  :"#{result.schema}__#{self.implicit_table_name}"
73
75
  end
76
+
77
+ def create(values = {}, &block)
78
+ sharded_column_value = values[sharded_column]
79
+ shard_number = result_for(sharded_column_value).shard_number
80
+ super.tap do |m|
81
+ m.values[:shard_number] = shard_number
82
+ end
83
+ end
74
84
  end
75
85
 
76
86
  # The database connection that has the logical shard.
@@ -1,5 +1,5 @@
1
1
  module Sequel
2
2
  module SchemaSharding
3
- VERSION = "0.11.1"
3
+ VERSION = "0.12.0"
4
4
  end
5
5
  end
@@ -20,5 +20,14 @@ namespace :sequel do
20
20
  manager = Sequel::SchemaSharding::DatabaseManager.new
21
21
  manager.drop_databases
22
22
  end
23
+
24
+ namespace :test do
25
+ desc 'Reset test database'
26
+ task :reset do
27
+ ENV['RACK_ENV'] = 'test'
28
+ Rake::Task['sequel:db:drop'].invoke
29
+ Rake::Task['sequel:db:create'].invoke
30
+ end
31
+ end
23
32
  end
24
33
  end
@@ -21,7 +21,7 @@ Gem::Specification.new do |spec|
21
21
  spec.add_dependency 'sequel'
22
22
  spec.add_dependency 'pg'
23
23
  spec.add_dependency 'sequel-replica-failover'
24
- spec.add_dependency 'ruby-usdt'
24
+ spec.add_dependency 'ruby-usdt', '>= 0.2.1'
25
25
 
26
26
  spec.add_development_dependency 'bundler', '~> 1.3'
27
27
  spec.add_development_dependency 'rake'
@@ -9,6 +9,7 @@ describe Sequel::SchemaSharding::Finder do
9
9
  result = Sequel::SchemaSharding::Finder.instance.lookup('boof', 60)
10
10
  expect(result.connection).to be_a(Sequel::Postgres::Database)
11
11
  expect(result.schema).to eq('sequel_logical_boof_01')
12
+ expect(result.shard_number).to eq(1)
12
13
  end
13
14
 
14
15
  xit 'is fast' do
@@ -25,8 +25,8 @@ describe Sequel::SchemaSharding, 'Model' do
25
25
  klass
26
26
  end
27
27
 
28
- describe '#by_id' do
29
- it 'returns a valid artist by id' do
28
+ describe 'reading from database' do
29
+ it 'can return a valid record' do
30
30
  artist = model.create(artist_id: 14, name: 'Paul')
31
31
  expect(artist.id).to_not be_nil
32
32
  read_back_artist = model.by_id(14).first
@@ -36,15 +36,28 @@ describe Sequel::SchemaSharding, 'Model' do
36
36
  read_back_artist = model.by_id(14).first
37
37
  expect(read_back_artist).to be_nil
38
38
  end
39
+
40
+ it 'includes shard number on model instances' do
41
+ shard_number = model.shard_for(456).shard_number
42
+
43
+ model.create(artist_id: 456, name: 'Randy')
44
+ record = model.by_id(456).first
45
+ expect(record.shard_number).to eq(shard_number)
46
+ end
39
47
  end
40
48
 
41
- describe '#create' do
42
- it 'creates a valid artist' do
49
+ describe 'writing to database' do
50
+ it 'can create a valid record' do
43
51
  artist = model.create(artist_id: 234, name: 'Paul')
44
52
  expect(artist).to be_a(model)
45
53
  expect(artist.name).to eql('Paul')
46
54
  artist.destroy
47
55
  end
56
+
57
+ it 'includes shard number on model instances' do
58
+ shard_number = model.shard_for(5432).shard_number
59
+ expect(model.create(artist_id: 5432, name: 'WOW').shard_number).to eq(shard_number)
60
+ end
48
61
  end
49
62
 
50
63
  describe '#shard_for' do
@@ -58,6 +71,10 @@ describe Sequel::SchemaSharding, 'Model' do
58
71
  expect(dataset.db.opts[:database]).to eq('sequel_test_shard2')
59
72
  expect(dataset.first_source).to eq(:sequel_logical_artists_17__artists)
60
73
  end
74
+
75
+ it 'includes shard_number on dataset' do
76
+ expect(dataset.shard_number).to eq(17)
77
+ end
61
78
  end
62
79
 
63
80
  describe '#read_only_shard_for' do
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.11.1
4
+ version: 0.12.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Paul Henry
@@ -10,90 +10,90 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2013-11-05 00:00:00.000000000 Z
13
+ date: 2014-01-24 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: sequel
17
17
  requirement: !ruby/object:Gem::Requirement
18
18
  requirements:
19
- - - '>='
19
+ - - ">="
20
20
  - !ruby/object:Gem::Version
21
21
  version: '0'
22
22
  type: :runtime
23
23
  prerelease: false
24
24
  version_requirements: !ruby/object:Gem::Requirement
25
25
  requirements:
26
- - - '>='
26
+ - - ">="
27
27
  - !ruby/object:Gem::Version
28
28
  version: '0'
29
29
  - !ruby/object:Gem::Dependency
30
30
  name: pg
31
31
  requirement: !ruby/object:Gem::Requirement
32
32
  requirements:
33
- - - '>='
33
+ - - ">="
34
34
  - !ruby/object:Gem::Version
35
35
  version: '0'
36
36
  type: :runtime
37
37
  prerelease: false
38
38
  version_requirements: !ruby/object:Gem::Requirement
39
39
  requirements:
40
- - - '>='
40
+ - - ">="
41
41
  - !ruby/object:Gem::Version
42
42
  version: '0'
43
43
  - !ruby/object:Gem::Dependency
44
44
  name: sequel-replica-failover
45
45
  requirement: !ruby/object:Gem::Requirement
46
46
  requirements:
47
- - - '>='
47
+ - - ">="
48
48
  - !ruby/object:Gem::Version
49
49
  version: '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
56
  version: '0'
57
57
  - !ruby/object:Gem::Dependency
58
58
  name: ruby-usdt
59
59
  requirement: !ruby/object:Gem::Requirement
60
60
  requirements:
61
- - - '>='
61
+ - - ">="
62
62
  - !ruby/object:Gem::Version
63
- version: '0'
63
+ version: 0.2.1
64
64
  type: :runtime
65
65
  prerelease: false
66
66
  version_requirements: !ruby/object:Gem::Requirement
67
67
  requirements:
68
- - - '>='
68
+ - - ">="
69
69
  - !ruby/object:Gem::Version
70
- version: '0'
70
+ version: 0.2.1
71
71
  - !ruby/object:Gem::Dependency
72
72
  name: bundler
73
73
  requirement: !ruby/object:Gem::Requirement
74
74
  requirements:
75
- - - ~>
75
+ - - "~>"
76
76
  - !ruby/object:Gem::Version
77
77
  version: '1.3'
78
78
  type: :development
79
79
  prerelease: false
80
80
  version_requirements: !ruby/object:Gem::Requirement
81
81
  requirements:
82
- - - ~>
82
+ - - "~>"
83
83
  - !ruby/object:Gem::Version
84
84
  version: '1.3'
85
85
  - !ruby/object:Gem::Dependency
86
86
  name: rake
87
87
  requirement: !ruby/object:Gem::Requirement
88
88
  requirements:
89
- - - '>='
89
+ - - ">="
90
90
  - !ruby/object:Gem::Version
91
91
  version: '0'
92
92
  type: :development
93
93
  prerelease: false
94
94
  version_requirements: !ruby/object:Gem::Requirement
95
95
  requirements:
96
- - - '>='
96
+ - - ">="
97
97
  - !ruby/object:Gem::Version
98
98
  version: '0'
99
99
  description: ''
@@ -103,9 +103,9 @@ executables: []
103
103
  extensions: []
104
104
  extra_rdoc_files: []
105
105
  files:
106
- - .gitignore
107
- - .rspec
108
- - .travis.yml
106
+ - ".gitignore"
107
+ - ".rspec"
108
+ - ".travis.yml"
109
109
  - CONTRIBUTORS.md
110
110
  - Gemfile
111
111
  - Guardfile
@@ -118,6 +118,7 @@ files:
118
118
  - examples/sharding.rb
119
119
  - examples/sharding.yml
120
120
  - lib/sequel-schema-sharding.rb
121
+ - lib/sequel/plugins/dataset_shard_id.rb
121
122
  - lib/sequel/schema-sharding.rb
122
123
  - lib/sequel/schema-sharding/configuration.rb
123
124
  - lib/sequel/schema-sharding/connection_manager.rb
@@ -125,6 +126,7 @@ files:
125
126
  - lib/sequel/schema-sharding/database_manager/schema_iterator.rb
126
127
  - lib/sequel/schema-sharding/dtrace_provider.rb
127
128
  - lib/sequel/schema-sharding/extensions/migrations_ext.rb
129
+ - lib/sequel/schema-sharding/extensions/postgres/dataset.rb
128
130
  - lib/sequel/schema-sharding/extensions/sequel_ext.rb
129
131
  - lib/sequel/schema-sharding/finder.rb
130
132
  - lib/sequel/schema-sharding/logger_proxy.rb
@@ -158,17 +160,17 @@ require_paths:
158
160
  - lib
159
161
  required_ruby_version: !ruby/object:Gem::Requirement
160
162
  requirements:
161
- - - '>='
163
+ - - ">="
162
164
  - !ruby/object:Gem::Version
163
165
  version: '0'
164
166
  required_rubygems_version: !ruby/object:Gem::Requirement
165
167
  requirements:
166
- - - '>='
168
+ - - ">="
167
169
  - !ruby/object:Gem::Version
168
170
  version: '0'
169
171
  requirements: []
170
172
  rubyforge_project:
171
- rubygems_version: 2.0.7
173
+ rubygems_version: 2.2.0
172
174
  signing_key:
173
175
  specification_version: 4
174
176
  summary: Create horizontally sharded Sequel models with Postgres