sequel-schema-sharding 0.3.0 → 0.4.1

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: 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