sequel-schema-sharding 0.3.0 → 0.4.1

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: 2c3fdaa18a8bee064030a25babedc4e261c3e160
4
- data.tar.gz: 5b40cc67b014aa243ae76ef915a53cafcfc82c16
3
+ metadata.gz: f7c70c9f4005f27bb6c64ab8f666d8d6238aee84
4
+ data.tar.gz: 9c867fc8fdf0e585579c184aeb6c77ce85b90b07
5
5
  SHA512:
6
- metadata.gz: c8bd4a45ea47e496a888abceda16c09c482402f6561c0c4e52053e8e36c1b3618af268cd8a406ac47ba86a414391b7ab42b0e2144dc8c6a8406fa4a877172877
7
- data.tar.gz: d2c4673374e061cc9d9466f4f06709e8d5518daaa85a7d88465904121a78ebb5e190549ed26cda47248b4adefdcb634eeb3841201837a01dd5bb3fd82c58228e
6
+ metadata.gz: 257e3ea91ff1851bad52e02b57c546a9897ea7d8a6ba46d5d865a638aa796a26e90be4e207270dcac16291727218e85a27916ba24bc2b1b62d9e5ab9cad334b3
7
+ data.tar.gz: 39efe5f19987104abac8f8688306c38821a0d751e2bc04df65b7f8f74f1db8971d74dcb882daf94f77f554c102be173852efa7d4a8c16c8f14f0a3facc9d3d03
@@ -10,114 +10,23 @@ module Sequel
10
10
  # This implementation is borrowed from Dali memcached library.
11
11
  class Ring
12
12
  POINTS_PER_SERVER = 1
13
+ PRODUCTION_SHARDS = 8192
13
14
 
14
15
  attr_accessor :shards, :continuum
15
16
 
16
17
  def initialize(shards)
17
- @shards = shards
18
- @continuum = nil
19
- if shards.size > 1
20
- continuum = []
21
- shards.each do |shard|
22
- hash = Digest::SHA1.hexdigest("#{shard}")
23
- value = Integer("0x#{hash[0..7]}")
24
- continuum << Entry.new(value, shard)
25
- end
26
- @continuum = continuum.sort { |a, b| a.value <=> b.value }
18
+ @number_of_shards = shards.size
19
+ if ENV['RACK_ENV'] == "production"
20
+ raise "Expecting production shards to be #{PRODUCTION_SHARDS}, got #{@number_of_shards}" \
21
+ if @number_of_shards != PRODUCTION_SHARDS
27
22
  end
28
23
  end
29
24
 
30
25
  def shard_for_id(id)
31
- if @continuum
32
- hkey = hash_for(id)
33
- entryidx = binary_search(@continuum, hkey)
34
- return @continuum[entryidx].server
35
- else
36
- server = @servers.first
37
- return server if server
38
- end
39
-
40
- raise StandardError, "No server available"
41
- end
42
-
43
- private
44
-
45
- def hash_for(key)
46
- Zlib.crc32(key.to_s)
47
- end
48
-
49
- def entry_count
50
- ((shards.size * POINTS_PER_SERVER)).floor
51
- end
52
-
53
- # Native extension to perform the binary search within the continuum
54
- # space. Fallback to a pure Ruby version if the compilation doesn't work.
55
- # optional for performance and only necessary if you are using multiple
56
- # memcached servers.
57
- begin
58
- require 'inline'
59
- inline do |builder|
60
- builder.c <<-EOM
61
- int binary_search(VALUE ary, unsigned int r) {
62
- long upper = RARRAY_LEN(ary) - 1;
63
- long lower = 0;
64
- long idx = 0;
65
- ID value = rb_intern("value");
66
- VALUE continuumValue;
67
- unsigned int l;
68
-
69
- while (lower <= upper) {
70
- idx = (lower + upper) / 2;
71
-
72
- continuumValue = rb_funcall(RARRAY_PTR(ary)[idx], value, 0);
73
- l = NUM2UINT(continuumValue);
74
- if (l == r) {
75
- return idx;
76
- }
77
- else if (l > r) {
78
- upper = idx - 1;
79
- }
80
- else {
81
- lower = idx + 1;
82
- }
83
- }
84
- return upper;
85
- }
86
- EOM
87
- end
88
- rescue LoadError
89
- # Find the closest index in the Ring with value <= the given value
90
- def binary_search(ary, value)
91
- upper = ary.size - 1
92
- lower = 0
93
- idx = 0
94
-
95
- while (lower <= upper) do
96
- idx = (lower + upper) / 2
97
- comp = ary[idx].value <=> value
98
-
99
- if comp == 0
100
- return idx
101
- elsif comp > 0
102
- upper = idx - 1
103
- else
104
- lower = idx + 1
105
- end
106
- end
107
- return upper
108
- end
26
+ id = id.to_i
27
+ raise "id is passed as zero" if id == 0
28
+ id % @number_of_shards + 1
109
29
  end
110
-
111
- class Entry
112
- attr_reader :value
113
- attr_reader :server
114
-
115
- def initialize(val, srv)
116
- @value = val
117
- @server = srv
118
- end
119
- end
120
-
121
30
  end
122
31
  end
123
32
  end
@@ -1,5 +1,5 @@
1
1
  module Sequel
2
2
  module SchemaSharding
3
- VERSION = "0.3.0"
3
+ VERSION = "0.4.1"
4
4
  end
5
5
  end
@@ -20,7 +20,7 @@ module Sequel
20
20
  end
21
21
 
22
22
  def self.logger
23
- @logger ||= Logger.new(StringIO.new)
23
+ @logger ||= Logger.new(nil)
24
24
  end
25
25
 
26
26
  def self.logger=(logger)
@@ -8,7 +8,7 @@ describe Sequel::SchemaSharding::Finder do
8
8
  it 'returns an object with a valid connection and schema' do
9
9
  result = Sequel::SchemaSharding::Finder.instance.lookup('boof', 60)
10
10
  expect(result.connection).to be_a(Sequel::Postgres::Database)
11
- expect(result.schema).to eq('sequel_logical_boof_02')
11
+ expect(result.schema).to eq('sequel_logical_boof_01')
12
12
  end
13
13
 
14
14
  xit 'is fast' do
@@ -2,24 +2,38 @@ require 'spec_helper'
2
2
  require 'sequel/schema-sharding'
3
3
 
4
4
  describe Sequel::SchemaSharding::Ring do
5
-
6
- describe 'a ring of servers' do
7
- it 'have the continuum sorted by value' do
8
- shards = [1, 2, 3, 4, 5, 6, 7, 8]
5
+ describe '#shard_for_id' do
6
+ it 'returns a server for a given id' do
7
+ @shards = 16
8
+ shards = (1..@shards).to_a
9
9
  ring = Sequel::SchemaSharding::Ring.new(shards)
10
- previous_value = 0
11
- ring.continuum.each do |entry|
12
- expect(entry.value).to be > previous_value
13
- previous_value = entry.value
10
+
11
+ hash = {}
12
+ (1..10_000).to_a.each do |i|
13
+ shard = ring.shard_for_id(i)
14
+ hash[shard] ||= 0;
15
+ hash[shard] += 1;
16
+ end
17
+
18
+ expect(hash.size).to eq(@shards)
19
+ hash.values.each do |value|
20
+ expect(value).to eq(10_000 / @shards)
14
21
  end
15
22
  end
16
23
  end
17
24
 
18
- describe '#shard_for_id' do
19
- it 'returns a server for a given id' do
20
- shards = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]
21
- ring = Sequel::SchemaSharding::Ring.new(shards)
22
- expect(ring.shard_for_id(3489409)).to eq(4)
25
+ describe "#initialize" do
26
+ context "production" do
27
+ it "raises an exception if the number of shards is not 8192" do
28
+ env = ENV['RACK_ENV']
29
+ ENV['RACK_ENV'] = 'production'
30
+
31
+ expect do
32
+ Sequel::SchemaSharding::Ring.new((1..10).to_a)
33
+ end.to raise_error(RuntimeError)
34
+
35
+ ENV['RACK_ENV'] = env
36
+ end
23
37
  end
24
38
  end
25
39
  end
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.3.0
4
+ version: 0.4.1
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: 2013-10-01 00:00:00.000000000 Z
13
+ date: 2013-10-10 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: sequel