redis-key_hash 0.0.2

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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: c7dd84fcafb7fdfa166839a664d177a851ad7bf5
4
+ data.tar.gz: 496ced31fb42c55927fc739c6e5a930f6ea046f2
5
+ SHA512:
6
+ metadata.gz: 9aa7190e2b7e7f50651d8628a1b7488e864f4a11cb803f25553f2233480f37f97af38024a335502dc93e3a7c7b3d2d451676b50399b81e40ff1d75e210a0487c
7
+ data.tar.gz: 7356c4f3ecb5efe65b4c8e8fff4bc67d70da7cc4560974d06736dad5f1a171a9bbb80307dfc7f373dee23af6cbc9e8daace89ad53c5d2fa7890ea260756f05c7
@@ -0,0 +1,52 @@
1
+ *.gem
2
+ *.gem
3
+ *.rbc
4
+ /.config
5
+ /coverage/
6
+ /InstalledFiles
7
+ /pkg/
8
+ /spec/reports/
9
+ /spec/examples.txt
10
+ /test/tmp/
11
+ /test/version_tmp/
12
+ /tmp/
13
+
14
+ # Used by dotenv library to load environment variables.
15
+ # .env
16
+
17
+ ## Specific to RubyMotion:
18
+ .dat*
19
+ .repl_history
20
+ build/
21
+ *.bridgesupport
22
+ build-iPhoneOS/
23
+ build-iPhoneSimulator/
24
+
25
+ ## Specific to RubyMotion (use of CocoaPods):
26
+ #
27
+ # We recommend against adding the Pods directory to your .gitignore. However
28
+ # you should judge for yourself, the pros and cons are mentioned at:
29
+ # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
30
+ #
31
+ # vendor/Pods/
32
+
33
+ ## Documentation cache and generated files:
34
+ /.yardoc/
35
+ /_yardoc/
36
+ /doc/
37
+ /rdoc/
38
+
39
+ ## Environment normalization:
40
+ /.bundle/
41
+ /vendor/bundle
42
+ /lib/bundler/man/
43
+
44
+ # For a library or gem, you might want to ignore these files since the code is
45
+ # intended to run in multiple environments; otherwise, check them in:
46
+ #
47
+ Gemfile.lock
48
+ .ruby-version
49
+ .ruby-gemset
50
+
51
+ # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
52
+ .rvmrc
@@ -0,0 +1,5 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - 2.1.6
5
+ before_install: gem install bundler -v 1.14.6
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in redis-key_hash.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2017 ProsperWorks
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,56 @@
1
+ # Redis::KeyHash
2
+
3
+ Tests of key hash slot agreement for use with Redis Cluster and
4
+ RedisLabs Enterprise Cluster.
5
+
6
+ ## Installation
7
+
8
+ Add this line to your application's Gemfile:
9
+
10
+ ```ruby
11
+ gem 'redis-key_hash'
12
+ ```
13
+
14
+ And then execute:
15
+
16
+ $ bundle
17
+
18
+ Or install it yourself as:
19
+
20
+ $ gem install redis-key_hash
21
+
22
+ ## Usage
23
+
24
+ require 'redis/key_hash'
25
+
26
+ # As syntactic sugar, expose Redis::KeyHash methods in the Redis class.
27
+ #
28
+ Redis.include Redis::KeyHash
29
+
30
+ # Test whether several keys will hash to the same slot.
31
+ #
32
+ if Redis.all_in_one_slot?('a','b')
33
+ 'happy'
34
+ else
35
+ 'sad'
36
+ end
37
+ Redis.all_in_one_slot!('a','b') # may raise Redis::ImpendingCrossSlotError
38
+
39
+ ## Development
40
+
41
+ After checking out the repo, run `bin/setup` to install
42
+ dependencies. Then, run `rake test` to run the tests. You can also run
43
+ `bin/console` for an interactive prompt that will allow you to
44
+ experiment.
45
+
46
+ To install this gem onto your local machine, run `bundle exec rake
47
+ install`. To release a new version, update the version number in
48
+ `version.rb`, and then run `bundle exec rake release`, which will
49
+ create a git tag for the version, push git commits and tags, and push
50
+ the `.gem` file to [rubygems.org](https://rubygems.org).
51
+
52
+ ## Contributing
53
+
54
+ Bug reports and pull requests are welcome on GitHub at
55
+ https://github.com/ProsperWorks/redis-key_hash.
56
+
@@ -0,0 +1,10 @@
1
+ require "bundler/gem_tasks"
2
+ require "rake/testtask"
3
+
4
+ Rake::TestTask.new(:test) do |t|
5
+ t.libs << "test"
6
+ t.libs << "lib"
7
+ t.test_files = FileList['test/**/*_test.rb']
8
+ end
9
+
10
+ task :default => :test
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "redis/key_hash_util"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,18 @@
1
+ # Raised from Redis::KeyHash.all_in_one_slot! on a mismatch.
2
+ #
3
+ # Generally, this indicates we were about to risk a Redis operation
4
+ # which is likely to produce a Redis error result like:
5
+ #
6
+ # (error) CROSSSLOT Keys in request don't hash to the same slot
7
+ #
8
+ # TODO: rubocop
9
+ #
10
+ # TODO: rdoc
11
+ #
12
+ class Redis
13
+ class ImpendingCrossSlotError < ArgumentError # TODO: Redis::CommandError?
14
+ #
15
+ # TODO: capture the problems with the keys?
16
+ #
17
+ end
18
+ end
@@ -0,0 +1,214 @@
1
+ require 'redis/key_hash/version'
2
+ require 'redis/impending_cross_slot_error'
3
+
4
+ module Redis::KeyHash
5
+
6
+ def self.included(base)
7
+ base.extend(ClassMethods)
8
+ end
9
+
10
+ module ClassMethods
11
+ # TODO: rubocop
12
+
13
+ # TODO: rdoc
14
+
15
+ #
16
+ # TODO: KNOWN_STYLES hash, etc, move comments around
17
+ #
18
+
19
+ # The default for all_in_one_slot? and all_in_one_slot! is
20
+ # [:rc,:rlec] to encourage the of portable persistent hashing
21
+ # schemes.
22
+ #
23
+ # A scheme which works with both side-steps a potential vendor
24
+ # lock-in.
25
+ #
26
+ DEFAULT_STYLES ||= [ :rc, :rlec ].freeze
27
+
28
+ # The default style for hash_tag and hash_slot is :rc because we
29
+ # only know the hashing algorithm for Redis Cluster.
30
+ #
31
+ # We can guess that the hash for RedisLabs Enterprise Cluster is
32
+ # similar, but it is not documented.
33
+ #
34
+ DEFAULT_STYLE ||= :rc
35
+
36
+ # Tests whether all of keys will hash to the same slot in all
37
+ # specified sharding styles.
38
+ #
39
+ # @param keys String keys to be tested
40
+ #
41
+ # @param namespace String or nil if non-nil, applied as a prefix to
42
+ # all keys as per the redis-namespace gem before testing.
43
+ #
44
+ # @param styles Array of Symbols and/or Regexps as per hash_tag().
45
+ #
46
+ # @return true if all of keys provably have the same hash_slot under
47
+ # all styles by virtue of having a single hash_tag, false otherwise.
48
+ #
49
+ def all_in_one_slot?(*keys, namespace: nil, styles: DEFAULT_STYLES)
50
+ begin
51
+ all_in_one_slot!(*keys, namespace: namespace, styles: styles)
52
+ rescue Redis::ImpendingCrossSlotError
53
+ return false
54
+ else
55
+ return true
56
+ end
57
+ end
58
+
59
+ # Like all_in_one_slot?, mismatch raises Redis::ImpendingCrossSlotError.
60
+ #
61
+ # @param keys String keys to be tested
62
+ #
63
+ # @param namespace String or nil if non-nil, applied as a prefix to
64
+ # all keys as per the redis-namespace gem before testing.
65
+ #
66
+ # @param styles Array of Symbols and/or Regexps as per hash_tag().
67
+ #
68
+ # @return true if all of keys will hash to the same slot in all of
69
+ # the styles, false if there is any doubt.
70
+ #
71
+ # @return true if all of keys provably have the same hash_slot
72
+ # under all styles by virtue of having a single hash_tag.
73
+ #
74
+ # @raises Redis::ImpendingCrossSlotError if, for any styles, the
75
+ # keys have a different hash_tag hence will not provably have the
76
+ # same hash_slot
77
+ #
78
+ def all_in_one_slot!(*keys, namespace: nil, styles: DEFAULT_STYLES)
79
+ nkeys = namespace ? keys.map { |key| "#{namespace}:#{key}" } : keys
80
+ style2slot = Hash.new
81
+ problems = []
82
+ styles.each do |style|
83
+ tags = nkeys.map { |nkey| hash_tag(nkey,style: style) }.uniq
84
+ next if tags.size <= 1
85
+ problems << "style #{style} sees tags #{tags.join(',')}"
86
+ end
87
+ if 0 != problems.size
88
+ err = "CROSSSLOT"
89
+ err += " namespace=#{namespace}"
90
+ err += " keys=#{keys}"
91
+ err += " problems=#{problems}"
92
+ raise Redis::ImpendingCrossSlotError, err
93
+ end
94
+ true
95
+ end
96
+
97
+ # Computes the hash tag for a given key under a given Redis
98
+ # clustering algorithm.
99
+ #
100
+ # The :style => :rc implementation matches Redis Cluster exactly
101
+ # and is taken largely from the reference example provided in
102
+ # http://redis.io/topics/cluster-spec.
103
+ #
104
+ # The :style => :rlec implementation is partly speculative. It is
105
+ # mostly interpreted from the default RedisLabs Enterprise Cluster
106
+ # document
107
+ # https://redislabs.com/redis-enterprise-documentation/concepts-architecture/architecture/database-clustering/
108
+ # plus our experience at ProsperWorks that, out of the box, RLEC
109
+ # uses the *last* {}-expr, not the first as in RC, from :rc (which
110
+ # we would not care about), they are also structually different
111
+ # (which can cause bugs unless we take special care). :rc uses
112
+ # the first {}-expr in the, :rlec uses the last {}-expr.
113
+ #
114
+ # @param String key to be hashed
115
+ #
116
+ # @param Symbol :rc or rlec or Regexp which defines one capture group
117
+ #
118
+ # @param String the tag extracted from key as appropriate for :style.
119
+ #
120
+ def hash_tag(key, style: DEFAULT_STYLE)
121
+ regexp = nil
122
+ case style
123
+ when :rc
124
+ regexp = /{([^}]*)}/ # RC uses the first {}-expr
125
+ when :rlec
126
+ regexp = /.*\{(.*)\}.*/ # RLEC default per docs, uses last {}-expr
127
+ when Regexp
128
+ regexp = style # you can define your own
129
+ end
130
+ if !regexp
131
+ raise ArgumentError, "bogus style #{style}"
132
+ end
133
+ match = regexp.match(key)
134
+ return match ? match[1] : key
135
+ end
136
+
137
+ # Computes the Redis hash_slot for a given key.
138
+ #
139
+ # Uses :style as per hash_tag, but performs hashing as per RC
140
+ # only. We know through documentation and experimentation that RC
141
+ # uses crc16() and modulo 16384. We do not know what RLEC does,
142
+ # but until we have a better model we assume it is the same. This
143
+ # is probably a false assumption since the RLEC docs state that
144
+ # the number of shards can vary from cluster to cluster. But for
145
+ # many analyses, using the same hash as RC is still useful.
146
+ #
147
+ # @param String key to be hashed
148
+ #
149
+ # @param Symbol :rc or :rlec or Regexp which defines one capture group
150
+ #
151
+ # @param non-negative Integer the hash which Redis will use to slot key
152
+ #
153
+ def hash_slot(key, style: DEFAULT_STYLE)
154
+ tag = hash_tag(key, style: style)
155
+ crc16(tag) % 16384
156
+ end
157
+
158
+ # Computes the Redis crc16 for a given key, as per the reference
159
+ # implementation provided in http://redis.io/topics/cluster-spec.
160
+ #
161
+ # This implementation is taken largely from that reference document,
162
+ # changed only slightly to port to Ruby.
163
+ #
164
+ # @param String key
165
+ #
166
+ # @param non-negative Integer the crc16 which Redis will use to
167
+ # compute a hash_key.
168
+ #
169
+ def crc16(key)
170
+ crc = 0
171
+ key.each_char do |char|
172
+ crc = ((crc << 8) & 0xFFFF) ^ CRC16TAB[((crc >> 8) ^ char.ord) & 0x00FF]
173
+ end
174
+ crc
175
+ end
176
+
177
+ CRC16TAB ||= [
178
+ 0x0000,0x1021,0x2042,0x3063,0x4084,0x50a5,0x60c6,0x70e7,
179
+ 0x8108,0x9129,0xa14a,0xb16b,0xc18c,0xd1ad,0xe1ce,0xf1ef,
180
+ 0x1231,0x0210,0x3273,0x2252,0x52b5,0x4294,0x72f7,0x62d6,
181
+ 0x9339,0x8318,0xb37b,0xa35a,0xd3bd,0xc39c,0xf3ff,0xe3de,
182
+ 0x2462,0x3443,0x0420,0x1401,0x64e6,0x74c7,0x44a4,0x5485,
183
+ 0xa56a,0xb54b,0x8528,0x9509,0xe5ee,0xf5cf,0xc5ac,0xd58d,
184
+ 0x3653,0x2672,0x1611,0x0630,0x76d7,0x66f6,0x5695,0x46b4,
185
+ 0xb75b,0xa77a,0x9719,0x8738,0xf7df,0xe7fe,0xd79d,0xc7bc,
186
+ 0x48c4,0x58e5,0x6886,0x78a7,0x0840,0x1861,0x2802,0x3823,
187
+ 0xc9cc,0xd9ed,0xe98e,0xf9af,0x8948,0x9969,0xa90a,0xb92b,
188
+ 0x5af5,0x4ad4,0x7ab7,0x6a96,0x1a71,0x0a50,0x3a33,0x2a12,
189
+ 0xdbfd,0xcbdc,0xfbbf,0xeb9e,0x9b79,0x8b58,0xbb3b,0xab1a,
190
+ 0x6ca6,0x7c87,0x4ce4,0x5cc5,0x2c22,0x3c03,0x0c60,0x1c41,
191
+ 0xedae,0xfd8f,0xcdec,0xddcd,0xad2a,0xbd0b,0x8d68,0x9d49,
192
+ 0x7e97,0x6eb6,0x5ed5,0x4ef4,0x3e13,0x2e32,0x1e51,0x0e70,
193
+ 0xff9f,0xefbe,0xdfdd,0xcffc,0xbf1b,0xaf3a,0x9f59,0x8f78,
194
+ 0x9188,0x81a9,0xb1ca,0xa1eb,0xd10c,0xc12d,0xf14e,0xe16f,
195
+ 0x1080,0x00a1,0x30c2,0x20e3,0x5004,0x4025,0x7046,0x6067,
196
+ 0x83b9,0x9398,0xa3fb,0xb3da,0xc33d,0xd31c,0xe37f,0xf35e,
197
+ 0x02b1,0x1290,0x22f3,0x32d2,0x4235,0x5214,0x6277,0x7256,
198
+ 0xb5ea,0xa5cb,0x95a8,0x8589,0xf56e,0xe54f,0xd52c,0xc50d,
199
+ 0x34e2,0x24c3,0x14a0,0x0481,0x7466,0x6447,0x5424,0x4405,
200
+ 0xa7db,0xb7fa,0x8799,0x97b8,0xe75f,0xf77e,0xc71d,0xd73c,
201
+ 0x26d3,0x36f2,0x0691,0x16b0,0x6657,0x7676,0x4615,0x5634,
202
+ 0xd94c,0xc96d,0xf90e,0xe92f,0x99c8,0x89e9,0xb98a,0xa9ab,
203
+ 0x5844,0x4865,0x7806,0x6827,0x18c0,0x08e1,0x3882,0x28a3,
204
+ 0xcb7d,0xdb5c,0xeb3f,0xfb1e,0x8bf9,0x9bd8,0xabbb,0xbb9a,
205
+ 0x4a75,0x5a54,0x6a37,0x7a16,0x0af1,0x1ad0,0x2ab3,0x3a92,
206
+ 0xfd2e,0xed0f,0xdd6c,0xcd4d,0xbdaa,0xad8b,0x9de8,0x8dc9,
207
+ 0x7c26,0x6c07,0x5c64,0x4c45,0x3ca2,0x2c83,0x1ce0,0x0cc1,
208
+ 0xef1f,0xff3e,0xcf5d,0xdf7c,0xaf9b,0xbfba,0x8fd9,0x9ff8,
209
+ 0x6e17,0x7e36,0x4e55,0x5e74,0x2e93,0x3eb2,0x0ed1,0x1ef0
210
+ ].freeze
211
+
212
+ end
213
+
214
+ end
@@ -0,0 +1,17 @@
1
+ class Redis
2
+ module KeyHash
3
+ #
4
+ # Version plan:
5
+ #
6
+ # 0.0.1 - still in Prosperworks/ALI/vendor/gems/redis-key_hash
7
+ #
8
+ # 0.0.2 - broke out into Prosperworks/redis-key_hash
9
+ #
10
+ # 0.1.0 - big README.md and Rdoc update, open repo
11
+ #
12
+ # 0.2.0 - solicit and incorporate initial feedback from select
13
+ # beta external users
14
+ #
15
+ VERSION = "0.0.2" # broken into standalone repo, not polished
16
+ end
17
+ end
@@ -0,0 +1,57 @@
1
+ lib = File.expand_path('../lib', __FILE__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+ require 'redis/key_hash/version'
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "redis-key_hash"
7
+ spec.version = Redis::KeyHash::VERSION
8
+ spec.authors = [
9
+ "jhwillett"
10
+ ]
11
+ spec.email = [
12
+ "jhw@prosperworks.com"
13
+ ]
14
+ spec.license = 'MIT'
15
+
16
+ spec.summary = 'Tests Redis Cluster key hash slot agreement'
17
+ spec.homepage = 'https://github.com/ProsperWorks/redis-key_hash'
18
+ spec.description = %{
19
+ redis-key_hash provides tests of key hash slot agreement for use with
20
+ Redis Cluster and RedisLabs Enterprise Cluster.
21
+
22
+ Redis Cluster (RC) and RedisLabs Enterprise Cluster (RLEC) both
23
+ require that all keys in multi-key operations hash to the same node.
24
+ They use slightly different default hashing algorithms and RLEC offers
25
+ customizable hash pattersn.
26
+
27
+ It is impossible to predict which nodes will host each shard, and
28
+ difficult to predict which slot will host each key. But it is easy to
29
+ identify the key hash tag which RC or RLEC will use to select a shard.
30
+ Where key hash tags agree, we can be certain that slots and nodes will
31
+ also agree - even if hash tag disagreement does not always imply slot
32
+ or node disagreement.
33
+
34
+ By pulling this check into Ruby we can arrange to fail fast, before
35
+ sending a command to Redis which is at risk of CROSSLOT failure. We
36
+ can also validate key management schemes in unit tests which run
37
+ without support services or with a non-sharded Redis.
38
+ }
39
+
40
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
41
+ f.match(%r{^(test|spec|features)/})
42
+ end
43
+ spec.require_paths = ["lib"]
44
+
45
+ # We use "foo: bar" syntax liberally, not the older ":foo => bar".
46
+ # Possibly other Ruby 2-isms as well.
47
+ #
48
+ spec.required_ruby_version = '~> 2.0'
49
+
50
+ spec.add_development_dependency "bundler", "~> 1.14"
51
+ spec.add_development_dependency "rake", "~> 10.5"
52
+ spec.add_development_dependency "minitest", "~> 5.10"
53
+
54
+ # This gem is pure Ruby, no weird dependencies.
55
+ #
56
+ spec.platform = Gem::Platform::RUBY
57
+ end
metadata ADDED
@@ -0,0 +1,118 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: redis-key_hash
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ platform: ruby
6
+ authors:
7
+ - jhwillett
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-08-29 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.14'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.14'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.5'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.5'
41
+ - !ruby/object:Gem::Dependency
42
+ name: minitest
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '5.10'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '5.10'
55
+ description: |2
56
+
57
+ redis-key_hash provides tests of key hash slot agreement for use with
58
+ Redis Cluster and RedisLabs Enterprise Cluster.
59
+
60
+ Redis Cluster (RC) and RedisLabs Enterprise Cluster (RLEC) both
61
+ require that all keys in multi-key operations hash to the same node.
62
+ They use slightly different default hashing algorithms and RLEC offers
63
+ customizable hash pattersn.
64
+
65
+ It is impossible to predict which nodes will host each shard, and
66
+ difficult to predict which slot will host each key. But it is easy to
67
+ identify the key hash tag which RC or RLEC will use to select a shard.
68
+ Where key hash tags agree, we can be certain that slots and nodes will
69
+ also agree - even if hash tag disagreement does not always imply slot
70
+ or node disagreement.
71
+
72
+ By pulling this check into Ruby we can arrange to fail fast, before
73
+ sending a command to Redis which is at risk of CROSSLOT failure. We
74
+ can also validate key management schemes in unit tests which run
75
+ without support services or with a non-sharded Redis.
76
+ email:
77
+ - jhw@prosperworks.com
78
+ executables: []
79
+ extensions: []
80
+ extra_rdoc_files: []
81
+ files:
82
+ - ".gitignore"
83
+ - ".travis.yml"
84
+ - Gemfile
85
+ - LICENSE
86
+ - README.md
87
+ - Rakefile
88
+ - bin/console
89
+ - bin/setup
90
+ - lib/redis/impending_cross_slot_error.rb
91
+ - lib/redis/key_hash.rb
92
+ - lib/redis/key_hash/version.rb
93
+ - redis-key_hash.gemspec
94
+ homepage: https://github.com/ProsperWorks/redis-key_hash
95
+ licenses:
96
+ - MIT
97
+ metadata: {}
98
+ post_install_message:
99
+ rdoc_options: []
100
+ require_paths:
101
+ - lib
102
+ required_ruby_version: !ruby/object:Gem::Requirement
103
+ requirements:
104
+ - - "~>"
105
+ - !ruby/object:Gem::Version
106
+ version: '2.0'
107
+ required_rubygems_version: !ruby/object:Gem::Requirement
108
+ requirements:
109
+ - - ">="
110
+ - !ruby/object:Gem::Version
111
+ version: '0'
112
+ requirements: []
113
+ rubyforge_project:
114
+ rubygems_version: 2.4.8
115
+ signing_key:
116
+ specification_version: 4
117
+ summary: Tests Redis Cluster key hash slot agreement
118
+ test_files: []