redis 3.3.5 → 4.1.0

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.
Files changed (126) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +54 -2
  3. data/README.md +77 -76
  4. data/lib/redis.rb +779 -63
  5. data/lib/redis/client.rb +41 -20
  6. data/lib/redis/cluster.rb +286 -0
  7. data/lib/redis/cluster/command.rb +81 -0
  8. data/lib/redis/cluster/command_loader.rb +34 -0
  9. data/lib/redis/cluster/key_slot_converter.rb +72 -0
  10. data/lib/redis/cluster/node.rb +104 -0
  11. data/lib/redis/cluster/node_key.rb +35 -0
  12. data/lib/redis/cluster/node_loader.rb +37 -0
  13. data/lib/redis/cluster/option.rb +77 -0
  14. data/lib/redis/cluster/slot.rb +69 -0
  15. data/lib/redis/cluster/slot_loader.rb +49 -0
  16. data/lib/redis/connection.rb +2 -2
  17. data/lib/redis/connection/command_helper.rb +2 -8
  18. data/lib/redis/connection/hiredis.rb +2 -2
  19. data/lib/redis/connection/ruby.rb +13 -30
  20. data/lib/redis/connection/synchrony.rb +12 -4
  21. data/lib/redis/distributed.rb +32 -12
  22. data/lib/redis/errors.rb +46 -0
  23. data/lib/redis/hash_ring.rb +20 -64
  24. data/lib/redis/pipeline.rb +9 -7
  25. data/lib/redis/version.rb +1 -1
  26. metadata +53 -196
  27. data/.gitignore +0 -16
  28. data/.travis.yml +0 -89
  29. data/.travis/Gemfile +0 -11
  30. data/.yardopts +0 -3
  31. data/Gemfile +0 -4
  32. data/Rakefile +0 -87
  33. data/benchmarking/logging.rb +0 -71
  34. data/benchmarking/pipeline.rb +0 -51
  35. data/benchmarking/speed.rb +0 -21
  36. data/benchmarking/suite.rb +0 -24
  37. data/benchmarking/worker.rb +0 -71
  38. data/examples/basic.rb +0 -15
  39. data/examples/consistency.rb +0 -114
  40. data/examples/dist_redis.rb +0 -43
  41. data/examples/incr-decr.rb +0 -17
  42. data/examples/list.rb +0 -26
  43. data/examples/pubsub.rb +0 -37
  44. data/examples/sentinel.rb +0 -41
  45. data/examples/sentinel/start +0 -49
  46. data/examples/sets.rb +0 -36
  47. data/examples/unicorn/config.ru +0 -3
  48. data/examples/unicorn/unicorn.rb +0 -20
  49. data/redis.gemspec +0 -44
  50. data/test/bitpos_test.rb +0 -69
  51. data/test/blocking_commands_test.rb +0 -42
  52. data/test/client_test.rb +0 -59
  53. data/test/command_map_test.rb +0 -30
  54. data/test/commands_on_hashes_test.rb +0 -21
  55. data/test/commands_on_hyper_log_log_test.rb +0 -21
  56. data/test/commands_on_lists_test.rb +0 -20
  57. data/test/commands_on_sets_test.rb +0 -77
  58. data/test/commands_on_sorted_sets_test.rb +0 -137
  59. data/test/commands_on_strings_test.rb +0 -101
  60. data/test/commands_on_value_types_test.rb +0 -133
  61. data/test/connection_handling_test.rb +0 -277
  62. data/test/connection_test.rb +0 -57
  63. data/test/distributed_blocking_commands_test.rb +0 -46
  64. data/test/distributed_commands_on_hashes_test.rb +0 -10
  65. data/test/distributed_commands_on_hyper_log_log_test.rb +0 -33
  66. data/test/distributed_commands_on_lists_test.rb +0 -22
  67. data/test/distributed_commands_on_sets_test.rb +0 -83
  68. data/test/distributed_commands_on_sorted_sets_test.rb +0 -18
  69. data/test/distributed_commands_on_strings_test.rb +0 -59
  70. data/test/distributed_commands_on_value_types_test.rb +0 -95
  71. data/test/distributed_commands_requiring_clustering_test.rb +0 -164
  72. data/test/distributed_connection_handling_test.rb +0 -23
  73. data/test/distributed_internals_test.rb +0 -79
  74. data/test/distributed_key_tags_test.rb +0 -52
  75. data/test/distributed_persistence_control_commands_test.rb +0 -26
  76. data/test/distributed_publish_subscribe_test.rb +0 -92
  77. data/test/distributed_remote_server_control_commands_test.rb +0 -66
  78. data/test/distributed_scripting_test.rb +0 -102
  79. data/test/distributed_sorting_test.rb +0 -20
  80. data/test/distributed_test.rb +0 -58
  81. data/test/distributed_transactions_test.rb +0 -32
  82. data/test/encoding_test.rb +0 -18
  83. data/test/error_replies_test.rb +0 -59
  84. data/test/fork_safety_test.rb +0 -65
  85. data/test/helper.rb +0 -232
  86. data/test/helper_test.rb +0 -24
  87. data/test/internals_test.rb +0 -417
  88. data/test/lint/blocking_commands.rb +0 -150
  89. data/test/lint/hashes.rb +0 -162
  90. data/test/lint/hyper_log_log.rb +0 -60
  91. data/test/lint/lists.rb +0 -143
  92. data/test/lint/sets.rb +0 -140
  93. data/test/lint/sorted_sets.rb +0 -316
  94. data/test/lint/strings.rb +0 -260
  95. data/test/lint/value_types.rb +0 -122
  96. data/test/persistence_control_commands_test.rb +0 -26
  97. data/test/pipelining_commands_test.rb +0 -242
  98. data/test/publish_subscribe_test.rb +0 -282
  99. data/test/remote_server_control_commands_test.rb +0 -118
  100. data/test/scanning_test.rb +0 -413
  101. data/test/scripting_test.rb +0 -78
  102. data/test/sentinel_command_test.rb +0 -80
  103. data/test/sentinel_test.rb +0 -255
  104. data/test/sorting_test.rb +0 -59
  105. data/test/ssl_test.rb +0 -73
  106. data/test/support/connection/hiredis.rb +0 -1
  107. data/test/support/connection/ruby.rb +0 -1
  108. data/test/support/connection/synchrony.rb +0 -17
  109. data/test/support/redis_mock.rb +0 -130
  110. data/test/support/ssl/gen_certs.sh +0 -31
  111. data/test/support/ssl/trusted-ca.crt +0 -25
  112. data/test/support/ssl/trusted-ca.key +0 -27
  113. data/test/support/ssl/trusted-cert.crt +0 -81
  114. data/test/support/ssl/trusted-cert.key +0 -28
  115. data/test/support/ssl/untrusted-ca.crt +0 -26
  116. data/test/support/ssl/untrusted-ca.key +0 -27
  117. data/test/support/ssl/untrusted-cert.crt +0 -82
  118. data/test/support/ssl/untrusted-cert.key +0 -28
  119. data/test/support/wire/synchrony.rb +0 -24
  120. data/test/support/wire/thread.rb +0 -5
  121. data/test/synchrony_driver.rb +0 -88
  122. data/test/test.conf.erb +0 -9
  123. data/test/thread_safety_test.rb +0 -62
  124. data/test/transactions_test.rb +0 -264
  125. data/test/unknown_commands_test.rb +0 -14
  126. data/test/url_param_test.rb +0 -138
@@ -1,37 +0,0 @@
1
- require "redis"
2
-
3
- puts <<-EOS
4
- To play with this example use redis-cli from another terminal, like this:
5
-
6
- $ redis-cli publish one hello
7
-
8
- Finally force the example to exit sending the 'exit' message with:
9
-
10
- $ redis-cli publish two exit
11
-
12
- EOS
13
-
14
- redis = Redis.new
15
-
16
- trap(:INT) { puts; exit }
17
-
18
- begin
19
- redis.subscribe(:one, :two) do |on|
20
- on.subscribe do |channel, subscriptions|
21
- puts "Subscribed to ##{channel} (#{subscriptions} subscriptions)"
22
- end
23
-
24
- on.message do |channel, message|
25
- puts "##{channel}: #{message}"
26
- redis.unsubscribe if message == "exit"
27
- end
28
-
29
- on.unsubscribe do |channel, subscriptions|
30
- puts "Unsubscribed from ##{channel} (#{subscriptions} subscriptions)"
31
- end
32
- end
33
- rescue Redis::BaseConnectionError => error
34
- puts "#{error}, retrying in 1s"
35
- sleep 1
36
- retry
37
- end
@@ -1,41 +0,0 @@
1
- require 'redis'
2
-
3
- # This example creates a master-slave setup with a sentinel, then connects to
4
- # it and sends write commands in a loop.
5
- #
6
- # After 30 seconds, the master dies. You will be able to see how a new master
7
- # is elected and things continue to work as if nothing happened.
8
- #
9
- # To run this example:
10
- #
11
- # $ ruby -I./lib examples/sentinel.rb
12
- #
13
-
14
- at_exit do
15
- begin
16
- Process.kill(:INT, $redises)
17
- rescue Errno::ESRCH
18
- end
19
-
20
- Process.waitall
21
- end
22
-
23
- $redises = spawn("examples/sentinel/start")
24
-
25
- Sentinels = [{:host => "127.0.0.1", :port => 26379},
26
- {:host => "127.0.0.1", :port => 26380}]
27
- r = Redis.new(:url => "redis://master1", :sentinels => Sentinels, :role => :master)
28
-
29
- # Set keys into a loop.
30
- #
31
- # The example traps errors so that you can actually try to failover while
32
- # running the script to see redis-rb reconfiguring.
33
- (0..1000000).each{|i|
34
- begin
35
- r.set(i,i)
36
- $stdout.write("SET (#{i} times)\n") if i % 100 == 0
37
- rescue => e
38
- $stdout.write("E")
39
- end
40
- sleep(0.01)
41
- }
@@ -1,49 +0,0 @@
1
- #! /usr/bin/env ruby
2
-
3
- # This is a helper script used together with examples/sentinel.rb
4
- # It runs two Redis masters, two slaves for each of them, and two sentinels.
5
- # After 30 seconds, the first master dies.
6
- #
7
- # You don't need to run this script yourself. Rather, use examples/sentinel.rb.
8
-
9
- require "fileutils"
10
-
11
- $pids = []
12
-
13
- at_exit do
14
- $pids.each do |pid|
15
- begin
16
- Process.kill(:INT, pid)
17
- rescue Errno::ESRCH
18
- end
19
- end
20
-
21
- Process.waitall
22
- end
23
-
24
- base = File.expand_path(File.dirname(__FILE__))
25
-
26
- # Masters
27
- $pids << spawn("redis-server --port 6380 --loglevel warning")
28
- $pids << spawn("redis-server --port 6381 --loglevel warning")
29
-
30
- # Slaves of Master 1
31
- $pids << spawn("redis-server --port 63800 --slaveof 127.0.0.1 6380 --loglevel warning")
32
- $pids << spawn("redis-server --port 63801 --slaveof 127.0.0.1 6380 --loglevel warning")
33
-
34
- # Slaves of Master 2
35
- $pids << spawn("redis-server --port 63810 --slaveof 127.0.0.1 6381 --loglevel warning")
36
- $pids << spawn("redis-server --port 63811 --slaveof 127.0.0.1 6381 --loglevel warning")
37
-
38
- FileUtils.cp(File.join(base, "sentinel.conf"), "tmp/sentinel1.conf")
39
- FileUtils.cp(File.join(base, "sentinel.conf"), "tmp/sentinel2.conf")
40
-
41
- # Sentinels
42
- $pids << spawn("redis-server tmp/sentinel1.conf --sentinel --port 26379")
43
- $pids << spawn("redis-server tmp/sentinel2.conf --sentinel --port 26380")
44
-
45
- sleep 30
46
-
47
- Process.kill(:KILL, $pids[0])
48
-
49
- Process.waitall
@@ -1,36 +0,0 @@
1
- require 'rubygems'
2
- require 'redis'
3
-
4
- r = Redis.new
5
-
6
- r.del 'foo-tags'
7
- r.del 'bar-tags'
8
-
9
- puts
10
- p "create a set of tags on foo-tags"
11
-
12
- r.sadd 'foo-tags', 'one'
13
- r.sadd 'foo-tags', 'two'
14
- r.sadd 'foo-tags', 'three'
15
-
16
- puts
17
- p "create a set of tags on bar-tags"
18
-
19
- r.sadd 'bar-tags', 'three'
20
- r.sadd 'bar-tags', 'four'
21
- r.sadd 'bar-tags', 'five'
22
-
23
- puts
24
- p 'foo-tags'
25
-
26
- p r.smembers('foo-tags')
27
-
28
- puts
29
- p 'bar-tags'
30
-
31
- p r.smembers('bar-tags')
32
-
33
- puts
34
- p 'intersection of foo-tags and bar-tags'
35
-
36
- p r.sinter('foo-tags', 'bar-tags')
@@ -1,3 +0,0 @@
1
- run lambda { |env|
2
- [200, {"Content-Type" => "text/plain"}, [Redis.current.randomkey]]
3
- }
@@ -1,20 +0,0 @@
1
- require "redis"
2
-
3
- worker_processes 3
4
-
5
- # If you set the connection to Redis *before* forking,
6
- # you will cause forks to share a file descriptor.
7
- #
8
- # This causes a concurrency problem by which one fork
9
- # can read or write to the socket while others are
10
- # performing other operations.
11
- #
12
- # Most likely you'll be getting ProtocolError exceptions
13
- # mentioning a wrong initial byte in the reply.
14
- #
15
- # Thus we need to connect to Redis after forking the
16
- # worker processes.
17
-
18
- after_fork do |server, worker|
19
- Redis.current.disconnect!
20
- end
@@ -1,44 +0,0 @@
1
- # -*- encoding: utf-8 -*-
2
-
3
- $:.unshift File.expand_path("../lib", __FILE__)
4
-
5
- require "redis/version"
6
-
7
- Gem::Specification.new do |s|
8
- s.name = "redis"
9
-
10
- s.version = Redis::VERSION
11
-
12
- s.homepage = "https://github.com/redis/redis-rb"
13
-
14
- s.summary = "A Ruby client library for Redis"
15
-
16
- s.description = <<-EOS
17
- A Ruby client that tries to match Redis' API one-to-one, while still
18
- providing an idiomatic interface. It features thread-safety,
19
- client-side sharding, pipelining, and an obsession for performance.
20
- EOS
21
-
22
- s.license = "MIT"
23
-
24
- s.authors = [
25
- "Ezra Zygmuntowicz",
26
- "Taylor Weibley",
27
- "Matthew Clark",
28
- "Brian McKinney",
29
- "Salvatore Sanfilippo",
30
- "Luca Guidi",
31
- "Michel Martens",
32
- "Damian Janowski",
33
- "Pieter Noordhuis"
34
- ]
35
-
36
- s.email = ["redis-db@googlegroups.com"]
37
-
38
- s.files = `git ls-files`.split("\n")
39
- s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
40
- s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
41
-
42
- s.add_development_dependency("rake", "<11.0.0")
43
- s.add_development_dependency("test-unit", "3.1.5")
44
- end
@@ -1,69 +0,0 @@
1
- # encoding: UTF-8
2
-
3
- require File.expand_path("helper", File.dirname(__FILE__))
4
-
5
- unless defined?(Enumerator)
6
- Enumerator = Enumerable::Enumerator
7
- end
8
-
9
- class TestBitpos < Test::Unit::TestCase
10
-
11
- include Helper::Client
12
-
13
- def test_bitpos_empty_zero
14
- target_version "2.9.11" do
15
- r.del "foo"
16
- assert_equal 0, r.bitpos("foo", 0)
17
- end
18
- end
19
-
20
- def test_bitpos_empty_one
21
- target_version "2.9.11" do
22
- r.del "foo"
23
- assert_equal -1, r.bitpos("foo", 1)
24
- end
25
- end
26
-
27
- def test_bitpos_zero
28
- target_version "2.9.11" do
29
- r.set "foo", "\xff\xf0\x00"
30
- assert_equal 12, r.bitpos("foo", 0)
31
- end
32
- end
33
-
34
- def test_bitpos_one
35
- target_version "2.9.11" do
36
- r.set "foo", "\x00\x0f\x00"
37
- assert_equal 12, r.bitpos("foo", 1)
38
- end
39
- end
40
-
41
- def test_bitpos_zero_end_is_given
42
- target_version "2.9.11" do
43
- r.set "foo", "\xff\xff\xff"
44
- assert_equal 24, r.bitpos("foo", 0)
45
- assert_equal 24, r.bitpos("foo", 0, 0)
46
- assert_equal -1, r.bitpos("foo", 0, 0, -1)
47
- end
48
- end
49
-
50
- def test_bitpos_one_intervals
51
- target_version "2.9.11" do
52
- r.set "foo", "\x00\xff\x00"
53
- assert_equal 8, r.bitpos("foo", 1, 0, -1)
54
- assert_equal 8, r.bitpos("foo", 1, 1, -1)
55
- assert_equal -1, r.bitpos("foo", 1, 2, -1)
56
- assert_equal -1, r.bitpos("foo", 1, 2, 200)
57
- assert_equal 8, r.bitpos("foo", 1, 1, 1)
58
- end
59
- end
60
-
61
- def test_bitpos_raise_exception_if_stop_not_start
62
- target_version "2.9.11" do
63
- assert_raises(ArgumentError) do
64
- r.bitpos("foo", 0, nil, 2)
65
- end
66
- end
67
- end
68
-
69
- end
@@ -1,42 +0,0 @@
1
- # encoding: UTF-8
2
-
3
- require File.expand_path("helper", File.dirname(__FILE__))
4
- require "lint/blocking_commands"
5
-
6
- class TestBlockingCommands < Test::Unit::TestCase
7
-
8
- include Helper::Client
9
- include Lint::BlockingCommands
10
-
11
- def assert_takes_longer_than_client_timeout
12
- timeout = OPTIONS[:timeout]
13
- delay = timeout * 2
14
-
15
- mock(:delay => delay) do |r|
16
- t1 = Time.now
17
- yield(r)
18
- t2 = Time.now
19
-
20
- assert timeout == r.client.timeout
21
- assert delay <= (t2 - t1)
22
- end
23
- end
24
-
25
- def test_blpop_disable_client_timeout
26
- assert_takes_longer_than_client_timeout do |r|
27
- assert_equal ["foo", "0"], r.blpop("foo")
28
- end
29
- end
30
-
31
- def test_brpop_disable_client_timeout
32
- assert_takes_longer_than_client_timeout do |r|
33
- assert_equal ["foo", "0"], r.brpop("foo")
34
- end
35
- end
36
-
37
- def test_brpoplpush_disable_client_timeout
38
- assert_takes_longer_than_client_timeout do |r|
39
- assert_equal "0", r.brpoplpush("foo", "bar")
40
- end
41
- end
42
- end
@@ -1,59 +0,0 @@
1
- require File.expand_path("helper", File.dirname(__FILE__))
2
-
3
- class TestClient < Test::Unit::TestCase
4
-
5
- include Helper::Client
6
-
7
- def test_call
8
- result = r.call("PING")
9
- assert_equal result, "PONG"
10
- end
11
-
12
- def test_call_with_arguments
13
- result = r.call("SET", "foo", "bar")
14
- assert_equal result, "OK"
15
- end
16
-
17
- def test_call_integers
18
- result = r.call("INCR", "foo")
19
- assert_equal result, 1
20
- end
21
-
22
- def test_call_raise
23
- assert_raises(Redis::CommandError) do
24
- r.call("INCR")
25
- end
26
- end
27
-
28
- def test_queue_commit
29
- r.queue("SET", "foo", "bar")
30
- r.queue("GET", "foo")
31
- result = r.commit
32
-
33
- assert_equal result, ["OK", "bar"]
34
- end
35
-
36
- def test_commit_raise
37
- r.queue("SET", "foo", "bar")
38
- r.queue("INCR")
39
-
40
- assert_raise(Redis::CommandError) do
41
- r.commit
42
- end
43
- end
44
-
45
- def test_queue_after_error
46
- r.queue("SET", "foo", "bar")
47
- r.queue("INCR")
48
-
49
- assert_raise(Redis::CommandError) do
50
- r.commit
51
- end
52
-
53
- r.queue("SET", "foo", "bar")
54
- r.queue("INCR", "baz")
55
- result = r.commit
56
-
57
- assert_equal result, ["OK", 1]
58
- end
59
- end
@@ -1,30 +0,0 @@
1
- # encoding: UTF-8
2
-
3
- require File.expand_path("helper", File.dirname(__FILE__))
4
-
5
- class TestCommandMap < Test::Unit::TestCase
6
-
7
- include Helper::Client
8
-
9
- def test_override_existing_commands
10
- r.set("counter", 1)
11
-
12
- assert_equal 2, r.incr("counter")
13
-
14
- r.client.command_map[:incr] = :decr
15
-
16
- assert_equal 1, r.incr("counter")
17
- end
18
-
19
- def test_override_non_existing_commands
20
- r.set("key", "value")
21
-
22
- assert_raise Redis::CommandError do
23
- r.idontexist("key")
24
- end
25
-
26
- r.client.command_map[:idontexist] = :get
27
-
28
- assert_equal "value", r.idontexist("key")
29
- end
30
- end
@@ -1,21 +0,0 @@
1
- # encoding: UTF-8
2
-
3
- require File.expand_path("helper", File.dirname(__FILE__))
4
- require "lint/hashes"
5
-
6
- class TestCommandsOnHashes < Test::Unit::TestCase
7
-
8
- include Helper::Client
9
- include Lint::Hashes
10
-
11
- def test_mapped_hmget_in_a_pipeline_returns_hash
12
- r.hset("foo", "f1", "s1")
13
- r.hset("foo", "f2", "s2")
14
-
15
- result = r.pipelined do
16
- r.mapped_hmget("foo", "f1", "f2")
17
- end
18
-
19
- assert_equal result[0], { "f1" => "s1", "f2" => "s2" }
20
- end
21
- end