sequel-schema-sharding 0.11.1 → 0.12.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: 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