File: test_failover.rb

package info (click to toggle)
ruby-dalli 3.2.8-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 684 kB
  • sloc: ruby: 6,552; sh: 20; makefile: 4
file content (179 lines) | stat: -rw-r--r-- 5,583 bytes parent folder | download
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