redis2-namespaced 3.0.7

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 (99) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +11 -0
  3. data/.order +170 -0
  4. data/.travis/Gemfile +11 -0
  5. data/.travis.yml +55 -0
  6. data/.yardopts +3 -0
  7. data/CHANGELOG.md +285 -0
  8. data/LICENSE +20 -0
  9. data/README.md +251 -0
  10. data/Rakefile +403 -0
  11. data/benchmarking/logging.rb +71 -0
  12. data/benchmarking/pipeline.rb +51 -0
  13. data/benchmarking/speed.rb +21 -0
  14. data/benchmarking/suite.rb +24 -0
  15. data/benchmarking/worker.rb +71 -0
  16. data/examples/basic.rb +15 -0
  17. data/examples/dist_redis.rb +43 -0
  18. data/examples/incr-decr.rb +17 -0
  19. data/examples/list.rb +26 -0
  20. data/examples/pubsub.rb +37 -0
  21. data/examples/sets.rb +36 -0
  22. data/examples/unicorn/config.ru +3 -0
  23. data/examples/unicorn/unicorn.rb +20 -0
  24. data/lib/redis2/client.rb +419 -0
  25. data/lib/redis2/connection/command_helper.rb +44 -0
  26. data/lib/redis2/connection/hiredis.rb +63 -0
  27. data/lib/redis2/connection/registry.rb +12 -0
  28. data/lib/redis2/connection/ruby.rb +322 -0
  29. data/lib/redis2/connection/synchrony.rb +124 -0
  30. data/lib/redis2/connection.rb +9 -0
  31. data/lib/redis2/distributed.rb +853 -0
  32. data/lib/redis2/errors.rb +40 -0
  33. data/lib/redis2/hash_ring.rb +131 -0
  34. data/lib/redis2/pipeline.rb +141 -0
  35. data/lib/redis2/subscribe.rb +83 -0
  36. data/lib/redis2/version.rb +3 -0
  37. data/lib/redis2.rb +2533 -0
  38. data/redis.gemspec +43 -0
  39. data/test/bitpos_test.rb +69 -0
  40. data/test/blocking_commands_test.rb +42 -0
  41. data/test/command_map_test.rb +30 -0
  42. data/test/commands_on_hashes_test.rb +21 -0
  43. data/test/commands_on_lists_test.rb +20 -0
  44. data/test/commands_on_sets_test.rb +77 -0
  45. data/test/commands_on_sorted_sets_test.rb +109 -0
  46. data/test/commands_on_strings_test.rb +101 -0
  47. data/test/commands_on_value_types_test.rb +131 -0
  48. data/test/connection_handling_test.rb +189 -0
  49. data/test/db/.gitkeep +0 -0
  50. data/test/distributed_blocking_commands_test.rb +46 -0
  51. data/test/distributed_commands_on_hashes_test.rb +10 -0
  52. data/test/distributed_commands_on_lists_test.rb +22 -0
  53. data/test/distributed_commands_on_sets_test.rb +83 -0
  54. data/test/distributed_commands_on_sorted_sets_test.rb +18 -0
  55. data/test/distributed_commands_on_strings_test.rb +59 -0
  56. data/test/distributed_commands_on_value_types_test.rb +95 -0
  57. data/test/distributed_commands_requiring_clustering_test.rb +164 -0
  58. data/test/distributed_connection_handling_test.rb +23 -0
  59. data/test/distributed_internals_test.rb +70 -0
  60. data/test/distributed_key_tags_test.rb +52 -0
  61. data/test/distributed_persistence_control_commands_test.rb +26 -0
  62. data/test/distributed_publish_subscribe_test.rb +92 -0
  63. data/test/distributed_remote_server_control_commands_test.rb +66 -0
  64. data/test/distributed_scripting_test.rb +102 -0
  65. data/test/distributed_sorting_test.rb +20 -0
  66. data/test/distributed_test.rb +58 -0
  67. data/test/distributed_transactions_test.rb +32 -0
  68. data/test/encoding_test.rb +18 -0
  69. data/test/error_replies_test.rb +59 -0
  70. data/test/helper.rb +218 -0
  71. data/test/helper_test.rb +24 -0
  72. data/test/internals_test.rb +410 -0
  73. data/test/lint/blocking_commands.rb +150 -0
  74. data/test/lint/hashes.rb +162 -0
  75. data/test/lint/lists.rb +143 -0
  76. data/test/lint/sets.rb +125 -0
  77. data/test/lint/sorted_sets.rb +238 -0
  78. data/test/lint/strings.rb +260 -0
  79. data/test/lint/value_types.rb +122 -0
  80. data/test/persistence_control_commands_test.rb +26 -0
  81. data/test/pipelining_commands_test.rb +242 -0
  82. data/test/publish_subscribe_test.rb +210 -0
  83. data/test/remote_server_control_commands_test.rb +117 -0
  84. data/test/scanning_test.rb +413 -0
  85. data/test/scripting_test.rb +78 -0
  86. data/test/sorting_test.rb +59 -0
  87. data/test/support/connection/hiredis.rb +1 -0
  88. data/test/support/connection/ruby.rb +1 -0
  89. data/test/support/connection/synchrony.rb +17 -0
  90. data/test/support/redis_mock.rb +115 -0
  91. data/test/support/wire/synchrony.rb +24 -0
  92. data/test/support/wire/thread.rb +5 -0
  93. data/test/synchrony_driver.rb +88 -0
  94. data/test/test.conf +9 -0
  95. data/test/thread_safety_test.rb +32 -0
  96. data/test/transactions_test.rb +264 -0
  97. data/test/unknown_commands_test.rb +14 -0
  98. data/test/url_param_test.rb +132 -0
  99. metadata +226 -0
@@ -0,0 +1,51 @@
1
+ require "benchmark"
2
+
3
+ $:.push File.join(File.dirname(__FILE__), 'lib')
4
+
5
+ require 'redis'
6
+
7
+ ITERATIONS = 10000
8
+
9
+ @r = Redis2.new
10
+
11
+ Benchmark.bmbm do |benchmark|
12
+ benchmark.report("set") do
13
+ @r.flushdb
14
+
15
+ ITERATIONS.times do |i|
16
+ @r.set("foo#{i}", "Hello world!")
17
+ @r.get("foo#{i}")
18
+ end
19
+ end
20
+
21
+ benchmark.report("set (pipelined)") do
22
+ @r.flushdb
23
+
24
+ @r.pipelined do
25
+ ITERATIONS.times do |i|
26
+ @r.set("foo#{i}", "Hello world!")
27
+ @r.get("foo#{i}")
28
+ end
29
+ end
30
+ end
31
+
32
+ benchmark.report("lpush+ltrim") do
33
+ @r.flushdb
34
+
35
+ ITERATIONS.times do |i|
36
+ @r.lpush "lpush#{i}", i
37
+ @r.ltrim "ltrim#{i}", 0, 30
38
+ end
39
+ end
40
+
41
+ benchmark.report("lpush+ltrim (pipelined)") do
42
+ @r.flushdb
43
+
44
+ @r.pipelined do
45
+ ITERATIONS.times do |i|
46
+ @r.lpush "lpush#{i}", i
47
+ @r.ltrim "ltrim#{i}", 0, 30
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,21 @@
1
+ # Run with
2
+ #
3
+ # $ ruby -Ilib benchmarking/speed.rb
4
+ #
5
+
6
+ require "benchmark"
7
+ require "redis"
8
+
9
+ r = Redis2.new
10
+ n = (ARGV.shift || 20000).to_i
11
+
12
+ elapsed = Benchmark.realtime do
13
+ # n sets, n gets
14
+ n.times do |i|
15
+ key = "foo#{i}"
16
+ r[key] = key * 10
17
+ r[key]
18
+ end
19
+ end
20
+
21
+ puts '%.2f Kops' % (2 * n / 1000 / elapsed)
@@ -0,0 +1,24 @@
1
+ require 'fileutils'
2
+
3
+ def run_in_background(command)
4
+ fork { system command }
5
+ end
6
+
7
+ def with_all_segments(&block)
8
+ 0.upto(9) do |segment_number|
9
+ block_size = 100000
10
+ start_index = segment_number * block_size
11
+ end_index = start_index + block_size - 1
12
+ block.call(start_index, end_index)
13
+ end
14
+ end
15
+
16
+ #with_all_segments do |start_index, end_index|
17
+ # puts "Initializing keys from #{start_index} to #{end_index}"
18
+ # system "ruby worker.rb initialize #{start_index} #{end_index} 0"
19
+ #end
20
+
21
+ with_all_segments do |start_index, end_index|
22
+ run_in_background "ruby worker.rb write #{start_index} #{end_index} 10"
23
+ run_in_background "ruby worker.rb read #{start_index} #{end_index} 1"
24
+ end
@@ -0,0 +1,71 @@
1
+ BENCHMARK_ROOT = File.dirname(__FILE__)
2
+ REDIS_ROOT = File.join(BENCHMARK_ROOT, "..", "lib")
3
+
4
+ $: << REDIS_ROOT
5
+ require 'redis'
6
+ require 'benchmark'
7
+
8
+ def show_usage
9
+ puts <<-EOL
10
+ Usage: worker.rb [read:write] <start_index> <end_index> <sleep_msec>
11
+ EOL
12
+ end
13
+
14
+ def shift_from_argv
15
+ value = ARGV.shift
16
+ unless value
17
+ show_usage
18
+ exit -1
19
+ end
20
+ value
21
+ end
22
+
23
+ operation = shift_from_argv.to_sym
24
+ start_index = shift_from_argv.to_i
25
+ end_index = shift_from_argv.to_i
26
+ sleep_msec = shift_from_argv.to_i
27
+ sleep_duration = sleep_msec/1000.0
28
+
29
+ redis = Redis2.new
30
+
31
+ case operation
32
+ when :initialize
33
+
34
+ start_index.upto(end_index) do |i|
35
+ redis[i] = 0
36
+ end
37
+
38
+ when :clear
39
+
40
+ start_index.upto(end_index) do |i|
41
+ redis.delete(i)
42
+ end
43
+
44
+ when :read, :write
45
+
46
+ puts "Starting to #{operation} at segment #{end_index + 1}"
47
+
48
+ loop do
49
+ t1 = Time.now
50
+ start_index.upto(end_index) do |i|
51
+ case operation
52
+ when :read
53
+ redis.get(i)
54
+ when :write
55
+ redis.incr(i)
56
+ else
57
+ raise "Unknown operation: #{operation}"
58
+ end
59
+ sleep sleep_duration
60
+ end
61
+ t2 = Time.now
62
+
63
+ requests_processed = end_index - start_index
64
+ time = t2 - t1
65
+ puts "#{t2.strftime("%H:%M")} [segment #{end_index + 1}] : Processed #{requests_processed} requests in #{time} seconds - #{(requests_processed/time).round} requests/sec"
66
+ end
67
+
68
+ else
69
+ raise "Unknown operation: #{operation}"
70
+ end
71
+
data/examples/basic.rb ADDED
@@ -0,0 +1,15 @@
1
+ require 'redis'
2
+
3
+ r = Redis2.new
4
+
5
+ r.del('foo')
6
+
7
+ puts
8
+
9
+ p'set foo to "bar"'
10
+ r['foo'] = 'bar'
11
+
12
+ puts
13
+
14
+ p 'value of foo'
15
+ p r['foo']
@@ -0,0 +1,43 @@
1
+ require "redis"
2
+ require "redis2/distributed"
3
+
4
+ r = Redis2::Distributed.new %w[redis://localhost:6379 redis://localhost:6380 redis://localhost:6381 redis://localhost:6382]
5
+
6
+ r.flushdb
7
+
8
+ r['urmom'] = 'urmom'
9
+ r['urdad'] = 'urdad'
10
+ r['urmom1'] = 'urmom1'
11
+ r['urdad1'] = 'urdad1'
12
+ r['urmom2'] = 'urmom2'
13
+ r['urdad2'] = 'urdad2'
14
+ r['urmom3'] = 'urmom3'
15
+ r['urdad3'] = 'urdad3'
16
+ p r['urmom']
17
+ p r['urdad']
18
+ p r['urmom1']
19
+ p r['urdad1']
20
+ p r['urmom2']
21
+ p r['urdad2']
22
+ p r['urmom3']
23
+ p r['urdad3']
24
+
25
+ r.rpush 'listor', 'foo1'
26
+ r.rpush 'listor', 'foo2'
27
+ r.rpush 'listor', 'foo3'
28
+ r.rpush 'listor', 'foo4'
29
+ r.rpush 'listor', 'foo5'
30
+
31
+ p r.rpop('listor')
32
+ p r.rpop('listor')
33
+ p r.rpop('listor')
34
+ p r.rpop('listor')
35
+ p r.rpop('listor')
36
+
37
+ puts "key distribution:"
38
+
39
+ r.ring.nodes.each do |node|
40
+ p [node.client, node.keys("*")]
41
+ end
42
+ r.flushdb
43
+ p r.keys('*')
@@ -0,0 +1,17 @@
1
+ require 'redis'
2
+
3
+ r = Redis2.new
4
+
5
+ puts
6
+ p 'incr'
7
+ r.del 'counter'
8
+
9
+ p r.incr('counter')
10
+ p r.incr('counter')
11
+ p r.incr('counter')
12
+
13
+ puts
14
+ p 'decr'
15
+ p r.decr('counter')
16
+ p r.decr('counter')
17
+ p r.decr('counter')
data/examples/list.rb ADDED
@@ -0,0 +1,26 @@
1
+ require 'rubygems'
2
+ require 'redis'
3
+
4
+ r = Redis2.new
5
+
6
+ r.del 'logs'
7
+
8
+ puts
9
+
10
+ p "pushing log messages into a LIST"
11
+ r.rpush 'logs', 'some log message'
12
+ r.rpush 'logs', 'another log message'
13
+ r.rpush 'logs', 'yet another log message'
14
+ r.rpush 'logs', 'also another log message'
15
+
16
+ puts
17
+ p 'contents of logs LIST'
18
+
19
+ p r.lrange('logs', 0, -1)
20
+
21
+ puts
22
+ p 'Trim logs LIST to last 2 elements(easy circular buffer)'
23
+
24
+ r.ltrim('logs', -2, -1)
25
+
26
+ p r.lrange('logs', 0, -1)
@@ -0,0 +1,37 @@
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 = Redis2.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 Redis2::BaseConnectionError => error
34
+ puts "#{error}, retrying in 1s"
35
+ sleep 1
36
+ retry
37
+ end
data/examples/sets.rb ADDED
@@ -0,0 +1,36 @@
1
+ require 'rubygems'
2
+ require 'redis'
3
+
4
+ r = Redis2.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')
@@ -0,0 +1,3 @@
1
+ run lambda { |env|
2
+ [200, {"Content-Type" => "text/plain"}, [Redis2.current.randomkey]]
3
+ }
@@ -0,0 +1,20 @@
1
+ require "redis"
2
+
3
+ worker_processes 3
4
+
5
+ # If you set the connection to Redis2 *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 Redis2 after forking the
16
+ # worker processes.
17
+
18
+ after_fork do |server, worker|
19
+ Redis2.current.quit
20
+ end