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:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f7c70c9f4005f27bb6c64ab8f666d8d6238aee84
|
4
|
+
data.tar.gz: 9c867fc8fdf0e585579c184aeb6c77ce85b90b07
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
@
|
18
|
-
|
19
|
-
|
20
|
-
|
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
|
-
|
32
|
-
|
33
|
-
|
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
|
@@ -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('
|
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
|
-
|
7
|
-
|
8
|
-
shards =
|
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
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
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
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
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.
|
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-
|
13
|
+
date: 2013-10-10 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: sequel
|