redis2-namespaced 3.0.7

Sign up to get free protection for your applications and to get access to all the features.
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