1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179
|
# frozen_string_literal: true
require_relative '../helper'
describe 'failover' do
MemcachedManager.supported_protocols.each do |p|
describe "using the #{p} protocol" do
# Timeouts on JRuby work differently and aren't firing, meaning we're
# not testing the condition
unless defined? JRUBY_VERSION
describe 'timeouts' do
it 'not lead to corrupt sockets' do
memcached_persistent(p) do |dc|
value = { test: '123' }
begin
Timeout.timeout 0.01 do
start_time = Time.now
10_000.times do
dc.set('test_123', value)
end
flunk("Did not timeout in #{Time.now - start_time}")
end
rescue Timeout::Error
# Ignore expected timeout
end
assert_equal(value, dc.get('test_123'))
end
end
end
end
describe 'assuming some bad servers' do
it 'silently reconnect if server hiccups' do
server_port = 30_124
memcached_persistent(p, server_port) do |dc, port|
dc.set 'foo', 'bar'
foo = dc.get 'foo'
assert_equal('bar', foo)
memcached_kill(port)
memcached_persistent(p, port) do
foo = dc.get 'foo'
assert_nil foo
memcached_kill(port)
end
end
end
it 'reconnects if server idles the connection' do
port1 = 32_112
port2 = 37_887
memcached(p, port1, '-o idle_timeout=1') do |_, first_port|
memcached(p, port2, '-o idle_timeout=1') do |_, second_port|
dc = Dalli::Client.new ["localhost:#{first_port}", "localhost:#{second_port}"]
dc.set 'foo', 'bar'
dc.set 'foo2', 'bar2'
foo = dc.get_multi 'foo', 'foo2'
assert_equal({ 'foo' => 'bar', 'foo2' => 'bar2' }, foo)
# wait for socket to expire and get cleaned up
sleep 5
foo = dc.get_multi 'foo', 'foo2'
assert_equal({ 'foo' => 'bar', 'foo2' => 'bar2' }, foo)
end
end
end
it 'handle graceful failover' do
port1 = 31_777
port2 = 32_113
memcached_persistent(p, port1) do |_first_dc, first_port|
memcached_persistent(p, port2) do |_second_dc, second_port|
dc = Dalli::Client.new ["localhost:#{first_port}", "localhost:#{second_port}"]
dc.set 'foo', 'bar'
foo = dc.get 'foo'
assert_equal('bar', foo)
memcached_kill(first_port)
dc.set 'foo', 'bar'
foo = dc.get 'foo'
assert_equal('bar', foo)
memcached_kill(second_port)
assert_raises Dalli::RingError, message: 'No server available' do
dc.set 'foo', 'bar'
end
end
end
end
it 'handle them gracefully in get_multi' do
port1 = 32_971
port2 = 34_312
memcached_persistent(p, port1) do |_first_dc, first_port|
memcached(p, port2) do |_second_dc, second_port|
dc = Dalli::Client.new ["localhost:#{first_port}", "localhost:#{second_port}"]
dc.set 'a', 'a1'
result = dc.get_multi ['a']
assert_equal({ 'a' => 'a1' }, result)
memcached_kill(first_port)
result = dc.get_multi ['a']
assert_equal({ 'a' => 'a1' }, result)
end
end
end
it 'handle graceful failover in get_multi' do
port1 = 34_541
port2 = 33_044
memcached_persistent(p, port1) do |_first_dc, first_port|
memcached_persistent(p, port2) do |_second_dc, second_port|
dc = Dalli::Client.new ["localhost:#{first_port}", "localhost:#{second_port}"]
dc.set 'foo', 'foo1'
dc.set 'bar', 'bar1'
result = dc.get_multi %w[foo bar]
assert_equal({ 'foo' => 'foo1', 'bar' => 'bar1' }, result)
memcached_kill(first_port)
dc.set 'foo', 'foo1'
dc.set 'bar', 'bar1'
result = dc.get_multi %w[foo bar]
assert_equal({ 'foo' => 'foo1', 'bar' => 'bar1' }, result)
memcached_kill(second_port)
result = dc.get_multi %w[foo bar]
assert_empty(result)
end
end
end
it 'stats it still properly report' do
port1 = 34_547
port2 = 33_219
memcached_persistent(p, port1) do |_first_dc, first_port|
memcached_persistent(p, port2) do |_second_dc, second_port|
dc = Dalli::Client.new ["localhost:#{first_port}", "localhost:#{second_port}"]
result = dc.stats
assert_instance_of Hash, result["localhost:#{first_port}"]
assert_instance_of Hash, result["localhost:#{second_port}"]
memcached_kill(first_port)
dc = Dalli::Client.new ["localhost:#{first_port}", "localhost:#{second_port}"]
result = dc.stats
assert_instance_of NilClass, result["localhost:#{first_port}"]
assert_instance_of Hash, result["localhost:#{second_port}"]
memcached_kill(second_port)
end
end
end
end
end
end
end
|