redis 4.1.0.beta1 → 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 (142) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +13 -2
  3. data/README.md +45 -0
  4. data/lib/redis.rb +497 -20
  5. data/lib/redis/client.rb +14 -6
  6. data/lib/redis/cluster.rb +1 -0
  7. data/lib/redis/cluster/command_loader.rb +2 -0
  8. data/lib/redis/cluster/node_loader.rb +2 -0
  9. data/lib/redis/cluster/option.rb +1 -0
  10. data/lib/redis/cluster/slot_loader.rb +2 -0
  11. data/lib/redis/distributed.rb +3 -4
  12. data/lib/redis/version.rb +1 -1
  13. metadata +20 -243
  14. data/.gitignore +0 -19
  15. data/.travis.yml +0 -61
  16. data/.travis/Gemfile +0 -18
  17. data/.yardopts +0 -3
  18. data/Gemfile +0 -8
  19. data/benchmarking/logging.rb +0 -71
  20. data/benchmarking/pipeline.rb +0 -51
  21. data/benchmarking/speed.rb +0 -21
  22. data/benchmarking/suite.rb +0 -24
  23. data/benchmarking/worker.rb +0 -71
  24. data/bin/build +0 -71
  25. data/bors.toml +0 -14
  26. data/examples/basic.rb +0 -15
  27. data/examples/consistency.rb +0 -114
  28. data/examples/dist_redis.rb +0 -43
  29. data/examples/incr-decr.rb +0 -17
  30. data/examples/list.rb +0 -26
  31. data/examples/pubsub.rb +0 -37
  32. data/examples/sentinel.rb +0 -41
  33. data/examples/sentinel/start +0 -49
  34. data/examples/sets.rb +0 -36
  35. data/examples/unicorn/config.ru +0 -3
  36. data/examples/unicorn/unicorn.rb +0 -20
  37. data/makefile +0 -74
  38. data/redis.gemspec +0 -42
  39. data/test/bitpos_test.rb +0 -63
  40. data/test/blocking_commands_test.rb +0 -40
  41. data/test/client_test.rb +0 -76
  42. data/test/cluster_abnormal_state_test.rb +0 -38
  43. data/test/cluster_blocking_commands_test.rb +0 -15
  44. data/test/cluster_client_internals_test.rb +0 -77
  45. data/test/cluster_client_key_hash_tags_test.rb +0 -88
  46. data/test/cluster_client_options_test.rb +0 -147
  47. data/test/cluster_client_pipelining_test.rb +0 -59
  48. data/test/cluster_client_replicas_test.rb +0 -36
  49. data/test/cluster_client_slots_test.rb +0 -94
  50. data/test/cluster_client_transactions_test.rb +0 -71
  51. data/test/cluster_commands_on_cluster_test.rb +0 -165
  52. data/test/cluster_commands_on_connection_test.rb +0 -40
  53. data/test/cluster_commands_on_geo_test.rb +0 -74
  54. data/test/cluster_commands_on_hashes_test.rb +0 -11
  55. data/test/cluster_commands_on_hyper_log_log_test.rb +0 -17
  56. data/test/cluster_commands_on_keys_test.rb +0 -134
  57. data/test/cluster_commands_on_lists_test.rb +0 -15
  58. data/test/cluster_commands_on_pub_sub_test.rb +0 -101
  59. data/test/cluster_commands_on_scripting_test.rb +0 -56
  60. data/test/cluster_commands_on_server_test.rb +0 -221
  61. data/test/cluster_commands_on_sets_test.rb +0 -39
  62. data/test/cluster_commands_on_sorted_sets_test.rb +0 -35
  63. data/test/cluster_commands_on_streams_test.rb +0 -196
  64. data/test/cluster_commands_on_strings_test.rb +0 -15
  65. data/test/cluster_commands_on_transactions_test.rb +0 -41
  66. data/test/cluster_commands_on_value_types_test.rb +0 -14
  67. data/test/command_map_test.rb +0 -28
  68. data/test/commands_on_geo_test.rb +0 -116
  69. data/test/commands_on_hashes_test.rb +0 -7
  70. data/test/commands_on_hyper_log_log_test.rb +0 -7
  71. data/test/commands_on_lists_test.rb +0 -7
  72. data/test/commands_on_sets_test.rb +0 -7
  73. data/test/commands_on_sorted_sets_test.rb +0 -7
  74. data/test/commands_on_strings_test.rb +0 -7
  75. data/test/commands_on_value_types_test.rb +0 -207
  76. data/test/connection_handling_test.rb +0 -275
  77. data/test/connection_test.rb +0 -57
  78. data/test/distributed_blocking_commands_test.rb +0 -52
  79. data/test/distributed_commands_on_hashes_test.rb +0 -21
  80. data/test/distributed_commands_on_hyper_log_log_test.rb +0 -26
  81. data/test/distributed_commands_on_lists_test.rb +0 -19
  82. data/test/distributed_commands_on_sets_test.rb +0 -105
  83. data/test/distributed_commands_on_sorted_sets_test.rb +0 -59
  84. data/test/distributed_commands_on_strings_test.rb +0 -79
  85. data/test/distributed_commands_on_value_types_test.rb +0 -129
  86. data/test/distributed_commands_requiring_clustering_test.rb +0 -162
  87. data/test/distributed_connection_handling_test.rb +0 -21
  88. data/test/distributed_internals_test.rb +0 -68
  89. data/test/distributed_key_tags_test.rb +0 -50
  90. data/test/distributed_persistence_control_commands_test.rb +0 -24
  91. data/test/distributed_publish_subscribe_test.rb +0 -90
  92. data/test/distributed_remote_server_control_commands_test.rb +0 -64
  93. data/test/distributed_scripting_test.rb +0 -100
  94. data/test/distributed_sorting_test.rb +0 -18
  95. data/test/distributed_test.rb +0 -56
  96. data/test/distributed_transactions_test.rb +0 -30
  97. data/test/encoding_test.rb +0 -14
  98. data/test/error_replies_test.rb +0 -57
  99. data/test/fork_safety_test.rb +0 -60
  100. data/test/helper.rb +0 -344
  101. data/test/helper_test.rb +0 -22
  102. data/test/internals_test.rb +0 -395
  103. data/test/lint/blocking_commands.rb +0 -174
  104. data/test/lint/hashes.rb +0 -203
  105. data/test/lint/hyper_log_log.rb +0 -74
  106. data/test/lint/lists.rb +0 -159
  107. data/test/lint/sets.rb +0 -282
  108. data/test/lint/sorted_sets.rb +0 -497
  109. data/test/lint/strings.rb +0 -348
  110. data/test/lint/value_types.rb +0 -130
  111. data/test/persistence_control_commands_test.rb +0 -24
  112. data/test/pipelining_commands_test.rb +0 -246
  113. data/test/publish_subscribe_test.rb +0 -280
  114. data/test/remote_server_control_commands_test.rb +0 -175
  115. data/test/scanning_test.rb +0 -407
  116. data/test/scripting_test.rb +0 -76
  117. data/test/sentinel_command_test.rb +0 -78
  118. data/test/sentinel_test.rb +0 -253
  119. data/test/sorting_test.rb +0 -57
  120. data/test/ssl_test.rb +0 -69
  121. data/test/support/cluster/orchestrator.rb +0 -199
  122. data/test/support/connection/hiredis.rb +0 -1
  123. data/test/support/connection/ruby.rb +0 -1
  124. data/test/support/connection/synchrony.rb +0 -17
  125. data/test/support/redis_mock.rb +0 -130
  126. data/test/support/ssl/gen_certs.sh +0 -31
  127. data/test/support/ssl/trusted-ca.crt +0 -25
  128. data/test/support/ssl/trusted-ca.key +0 -27
  129. data/test/support/ssl/trusted-cert.crt +0 -81
  130. data/test/support/ssl/trusted-cert.key +0 -28
  131. data/test/support/ssl/untrusted-ca.crt +0 -26
  132. data/test/support/ssl/untrusted-ca.key +0 -27
  133. data/test/support/ssl/untrusted-cert.crt +0 -82
  134. data/test/support/ssl/untrusted-cert.key +0 -28
  135. data/test/support/wire/synchrony.rb +0 -24
  136. data/test/support/wire/thread.rb +0 -5
  137. data/test/synchrony_driver.rb +0 -85
  138. data/test/test.conf.erb +0 -9
  139. data/test/thread_safety_test.rb +0 -60
  140. data/test/transactions_test.rb +0 -272
  141. data/test/unknown_commands_test.rb +0 -12
  142. data/test/url_param_test.rb +0 -136
@@ -1,69 +0,0 @@
1
- require_relative "helper"
2
-
3
- class SslTest < Test::Unit::TestCase
4
-
5
- include Helper::Client
6
-
7
- driver(:ruby) do
8
-
9
- def test_verified_ssl_connection
10
- RedisMock.start({ :ping => proc { "+PONG" } }, ssl_server_opts("trusted")) do |port|
11
- redis = Redis.new(:port => port, :ssl => true, :ssl_params => { :ca_file => ssl_ca_file })
12
- assert_equal redis.ping, "PONG"
13
- end
14
- end
15
-
16
- def test_unverified_ssl_connection
17
- assert_raise(OpenSSL::SSL::SSLError) do
18
- RedisMock.start({ :ping => proc { "+PONG" } }, ssl_server_opts("untrusted")) do |port|
19
- redis = Redis.new(:port => port, :ssl => true, :ssl_params => { :ca_file => ssl_ca_file })
20
- redis.ping
21
- end
22
- end
23
- end
24
-
25
- def test_ssl_blocking
26
- RedisMock.start({}, ssl_server_opts("trusted")) do |port|
27
- redis = Redis.new(:port => port, :ssl => true, :ssl_params => { :ca_file => ssl_ca_file })
28
- assert_equal redis.set("boom", "a" * 10_000_000), "OK"
29
- end
30
- end
31
-
32
- end
33
-
34
- driver(:hiredis, :synchrony) do
35
-
36
- def test_ssl_not_implemented_exception
37
- assert_raise(NotImplementedError) do
38
- RedisMock.start({ :ping => proc { "+PONG" } }, ssl_server_opts("trusted")) do |port|
39
- redis = Redis.new(:port => port, :ssl => true, :ssl_params => { :ca_file => ssl_ca_file })
40
- redis.ping
41
- end
42
- end
43
- end
44
-
45
- end
46
-
47
- private
48
-
49
- def ssl_server_opts(prefix)
50
- ssl_cert = File.join(cert_path, "#{prefix}-cert.crt")
51
- ssl_key = File.join(cert_path, "#{prefix}-cert.key")
52
-
53
- {
54
- :ssl => true,
55
- :ssl_params => {
56
- :cert => OpenSSL::X509::Certificate.new(File.read(ssl_cert)),
57
- :key => OpenSSL::PKey::RSA.new(File.read(ssl_key))
58
- }
59
- }
60
- end
61
-
62
- def ssl_ca_file
63
- File.join(cert_path, "trusted-ca.crt")
64
- end
65
-
66
- def cert_path
67
- File.expand_path("../support/ssl/", __FILE__)
68
- end
69
- end
@@ -1,199 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative '../../../lib/redis'
4
-
5
- class ClusterOrchestrator
6
- SLOT_SIZE = 16384
7
-
8
- def initialize(node_addrs)
9
- raise 'Redis Cluster requires at least 3 master nodes.' if node_addrs.size < 3
10
- @clients = node_addrs.map { |addr| Redis.new(url: addr) }
11
- end
12
-
13
- def rebuild
14
- flush_all_data(@clients)
15
- reset_cluster(@clients)
16
- assign_slots(@clients)
17
- save_config_epoch(@clients)
18
- meet_each_other(@clients)
19
- wait_meeting(@clients)
20
- replicate(@clients)
21
- save_config(@clients)
22
- wait_cluster_building(@clients)
23
- sleep 3
24
- end
25
-
26
- def down
27
- flush_all_data(@clients)
28
- reset_cluster(@clients)
29
- end
30
-
31
- def failover
32
- take_slaves(@clients).last.cluster(:failover, :takeover)
33
- sleep 3
34
- end
35
-
36
- def start_resharding(slot, src_node_key, dest_node_key)
37
- node_map = hashify_node_map(@clients.first)
38
- src_node_id = node_map.fetch(src_node_key)
39
- src_client = find_client(@clients, src_node_key)
40
- dest_node_id = node_map.fetch(dest_node_key)
41
- dest_client = find_client(@clients, dest_node_key)
42
- dest_host, dest_port = dest_node_key.split(':')
43
-
44
- dest_client.cluster(:setslot, slot, 'IMPORTING', src_node_id)
45
- src_client.cluster(:setslot, slot, 'MIGRATING', dest_node_id)
46
-
47
- loop do
48
- keys = src_client.cluster(:getkeysinslot, slot, 100)
49
- break if keys.empty?
50
- keys.each { |k| src_client.migrate(k, host: dest_host, port: dest_port) }
51
- sleep 0.1
52
- end
53
- end
54
-
55
- def finish_resharding(slot, dest_node_key)
56
- node_map = hashify_node_map(@clients.first)
57
- @clients.first.cluster(:setslot, slot, 'NODE', node_map.fetch(dest_node_key))
58
- end
59
-
60
- def close
61
- @clients.each(&:quit)
62
- end
63
-
64
- private
65
-
66
- def flush_all_data(clients)
67
- clients.each do |c|
68
- begin
69
- c.flushall
70
- rescue Redis::CommandError
71
- # READONLY You can't write against a read only slave.
72
- nil
73
- end
74
- end
75
- end
76
-
77
- def reset_cluster(clients)
78
- clients.each { |c| c.cluster(:reset) }
79
- end
80
-
81
- def assign_slots(clients)
82
- masters = take_masters(clients)
83
- slot_slice = SLOT_SIZE / masters.size
84
- mod = SLOT_SIZE % masters.size
85
- slot_sizes = Array.new(masters.size, slot_slice)
86
- mod.downto(1) { |i| slot_sizes[i] += 1 }
87
-
88
- slot_idx = 0
89
- masters.zip(slot_sizes).each do |c, s|
90
- slot_range = slot_idx..slot_idx + s - 1
91
- c.cluster(:addslots, *slot_range.to_a)
92
- slot_idx += s
93
- end
94
- end
95
-
96
- def save_config_epoch(clients)
97
- clients.each_with_index do |c, i|
98
- begin
99
- c.cluster('set-config-epoch', i + 1)
100
- rescue Redis::CommandError
101
- # ERR Node config epoch is already non-zero
102
- nil
103
- end
104
- end
105
- end
106
-
107
- def meet_each_other(clients)
108
- first_cliient = clients.first
109
- target_info = first_cliient.connection
110
- target_host = target_info.fetch(:host)
111
- target_port = target_info.fetch(:port)
112
-
113
- clients.each do |client|
114
- next if first_cliient.id == client.id
115
- client.cluster(:meet, target_host, target_port)
116
- end
117
- end
118
-
119
- def wait_meeting(clients)
120
- first_cliient = clients.first
121
- size = clients.size
122
-
123
- loop do
124
- info = hashify_cluster_info(first_cliient)
125
- break if info['cluster_known_nodes'].to_i == size
126
- sleep 0.1
127
- end
128
- end
129
-
130
- def replicate(clients)
131
- node_map = hashify_node_map(clients.first)
132
- masters = take_masters(clients)
133
-
134
- take_slaves(clients).each_with_index do |slave, i|
135
- master_info = masters[i].connection
136
- master_host = master_info.fetch(:host)
137
- master_port = master_info.fetch(:port)
138
-
139
- loop do
140
- begin
141
- master_node_id = node_map.fetch("#{master_host}:#{master_port}")
142
- slave.cluster(:replicate, master_node_id)
143
- rescue Redis::CommandError
144
- # ERR Unknown node [key]
145
- sleep 0.1
146
- node_map = hashify_node_map(clients.first)
147
- next
148
- end
149
-
150
- break
151
- end
152
- end
153
- end
154
-
155
- def save_config(clients)
156
- clients.each { |c| c.cluster(:saveconfig) }
157
- end
158
-
159
- def wait_cluster_building(clients)
160
- first_cliient = clients.first
161
-
162
- loop do
163
- info = hashify_cluster_info(first_cliient)
164
- break if info['cluster_state'] == 'ok'
165
- sleep 0.1
166
- end
167
- end
168
-
169
- def hashify_cluster_info(client)
170
- client.cluster(:info).split("\r\n").map { |str| str.split(':') }.to_h
171
- end
172
-
173
- def hashify_node_map(client)
174
- client.cluster(:nodes)
175
- .split("\n")
176
- .map { |str| str.split(' ') }
177
- .map { |arr| [arr[1].split('@').first, arr[0]] }
178
- .to_h
179
- end
180
-
181
- def take_masters(clients)
182
- size = clients.size / 2
183
- return clients if size < 3
184
- clients.take(size)
185
- end
186
-
187
- def take_slaves(clients)
188
- size = clients.size / 2
189
- return [] if size < 3
190
- clients[size..size * 2]
191
- end
192
-
193
- def find_client(clients, node_key)
194
- clients.find do |cli|
195
- con = cli.connection
196
- node_key == "#{con.fetch(:host)}:#{con.fetch(:port)}"
197
- end
198
- end
199
- end
@@ -1 +0,0 @@
1
- require_relative "../wire/thread"
@@ -1 +0,0 @@
1
- require_relative "../wire/thread"
@@ -1,17 +0,0 @@
1
- require_relative "../wire/synchrony"
2
-
3
- module Helper
4
- def around
5
- rv = nil
6
-
7
- EM.synchrony do
8
- begin
9
- rv = yield
10
- ensure
11
- EM.stop
12
- end
13
- end
14
-
15
- rv
16
- end
17
- end
@@ -1,130 +0,0 @@
1
- require "socket"
2
-
3
- module RedisMock
4
- class Server
5
- def initialize(options = {}, &block)
6
- tcp_server = TCPServer.new(options[:host] || "127.0.0.1", 0)
7
- tcp_server.setsockopt(Socket::SOL_SOCKET, Socket::SO_REUSEADDR, true)
8
-
9
- if options[:ssl]
10
- ctx = OpenSSL::SSL::SSLContext.new
11
-
12
- ssl_params = options.fetch(:ssl_params, {})
13
- ctx.set_params(ssl_params) unless ssl_params.empty?
14
-
15
- @server = OpenSSL::SSL::SSLServer.new(tcp_server, ctx)
16
- else
17
- @server = tcp_server
18
- end
19
- end
20
-
21
- def port
22
- @server.addr[1]
23
- end
24
-
25
- def start(&block)
26
- @thread = Thread.new { run(&block) }
27
- end
28
-
29
- def shutdown
30
- @thread.kill
31
- end
32
-
33
- def run
34
- begin
35
- loop do
36
- session = @server.accept
37
-
38
- begin
39
- return if yield(session) == :exit
40
- ensure
41
- session.close
42
- end
43
- end
44
- rescue => ex
45
- $stderr.puts "Error running mock server: #{ex.class}: #{ex.message}"
46
- $stderr.puts ex.backtrace
47
- retry
48
- ensure
49
- @server.close
50
- end
51
- end
52
- end
53
-
54
- # Starts a mock Redis server in a thread.
55
- #
56
- # The server will use the lambda handler passed as argument to handle
57
- # connections. For example:
58
- #
59
- # handler = lambda { |session| session.close }
60
- # RedisMock.start_with_handler(handler) do
61
- # # Every connection will be closed immediately
62
- # end
63
- #
64
- def self.start_with_handler(blk, options = {})
65
- server = Server.new(options)
66
- port = server.port
67
-
68
- begin
69
- server.start(&blk)
70
- yield(port)
71
- ensure
72
- server.shutdown
73
- end
74
- end
75
-
76
- # Starts a mock Redis server in a thread.
77
- #
78
- # The server will reply with a `+OK` to all commands, but you can
79
- # customize it by providing a hash. For example:
80
- #
81
- # RedisMock.start(:ping => lambda { "+PONG" }) do |port|
82
- # assert_equal "PONG", Redis.new(:port => port).ping
83
- # end
84
- #
85
- def self.start(commands, options = {}, &blk)
86
- handler = lambda do |session|
87
- while line = session.gets
88
- argv = Array.new(line[1..-3].to_i) do
89
- bytes = session.gets[1..-3].to_i
90
- arg = session.read(bytes)
91
- session.read(2) # Discard \r\n
92
- arg
93
- end
94
-
95
- command = argv.shift
96
- blk = commands[command.to_sym]
97
- blk ||= lambda { |*_| "+OK" }
98
-
99
- response = blk.call(*argv)
100
-
101
- # Convert a nil response to :close
102
- response ||= :close
103
-
104
- if response == :exit
105
- break :exit
106
- elsif response == :close
107
- break :close
108
- elsif response.is_a?(Array)
109
- session.write("*%d\r\n" % response.size)
110
-
111
- response.each do |resp|
112
- if resp.is_a?(Array)
113
- session.write("*%d\r\n" % resp.size)
114
- resp.each do |r|
115
- session.write("$%d\r\n%s\r\n" % [r.length, r])
116
- end
117
- else
118
- session.write("$%d\r\n%s\r\n" % [resp.length, resp])
119
- end
120
- end
121
- else
122
- session.write(response)
123
- session.write("\r\n") unless response.end_with?("\r\n")
124
- end
125
- end
126
- end
127
-
128
- start_with_handler(handler, options, &blk)
129
- end
130
- end
@@ -1,31 +0,0 @@
1
- #!/bin/sh
2
-
3
- get_subject() {
4
- if [ "$1" = "trusted" ]
5
- then
6
- echo "/C=IT/ST=Sicily/L=Catania/O=Redis/OU=Security/CN=127.0.0.1"
7
- else
8
- echo "/C=XX/ST=Untrusted/L=Evilville/O=Evil Hacker/OU=Attack Department/CN=127.0.0.1"
9
- fi
10
- }
11
-
12
- # Generate two CAs: one to be considered trusted, and one that's untrusted
13
- for type in trusted untrusted; do
14
- rm -rf ./demoCA
15
- mkdir -p ./demoCA
16
- mkdir -p ./demoCA/certs
17
- mkdir -p ./demoCA/crl
18
- mkdir -p ./demoCA/newcerts
19
- mkdir -p ./demoCA/private
20
- touch ./demoCA/index.txt
21
-
22
- openssl genrsa -out ${type}-ca.key 2048
23
- openssl req -new -x509 -days 12500 -key ${type}-ca.key -out ${type}-ca.crt -subj "$(get_subject $type)"
24
- openssl x509 -in ${type}-ca.crt -noout -next_serial -out ./demoCA/serial
25
-
26
- openssl req -newkey rsa:2048 -keyout ${type}-cert.key -nodes -out ${type}-cert.req -subj "$(get_subject $type)"
27
- openssl ca -days 12500 -cert ${type}-ca.crt -keyfile ${type}-ca.key -out ${type}-cert.crt -infiles ${type}-cert.req
28
- rm ${type}-cert.req
29
- done
30
-
31
- rm -rf ./demoCA