beetle 2.0.0 → 2.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.rdoc +6 -1
- data/RELEASE_NOTES.rdoc +7 -1
- data/Rakefile +2 -0
- data/beetle.gemspec +3 -3
- data/features/step_definitions/redis_auto_failover_steps.rb +7 -3
- data/features/support/env.rb +1 -1
- data/features/support/system_notification_logger +3 -3
- data/features/support/test_daemons/redis.conf.erb +1 -1
- data/features/support/test_daemons/redis.rb +15 -5
- data/features/support/test_daemons/redis_configuration_client.rb +2 -1
- data/features/support/test_daemons/redis_configuration_server.rb +4 -5
- data/lib/beetle/redis_ext.rb +17 -2
- data/lib/beetle/version.rb +1 -1
- data/test/beetle/dead_lettering_test.rb +37 -33
- data/test/beetle/redis_ext_test.rb +8 -1
- data/test/test_helper.rb +1 -0
- metadata +9 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f8b9df71eabc29dad2d131ff952029d8beffcf82
|
4
|
+
data.tar.gz: 0301abf7e282bbc202f14d8671dec32569ca6835
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c88a91e53de54ef055ae3dc8e28d55395331a6ec9c798b39c86cb66f49156246a3bf2d8b21d6afd15f84f343b58f29e1238b35ffaab9b87621c8f769c0fadbda
|
7
|
+
data.tar.gz: a6bc8a6759b4dcc65bd9b095d80df03b748f1de0f2da8b6f1731778fc0d825eca33e13377ad43287bdce50674dca4c65d199738a0756a284320711ef6e0fd5f5
|
data/README.rdoc
CHANGED
@@ -151,6 +151,11 @@ In short (see {semver.org}[http://semver.org] for details):
|
|
151
151
|
Then use `rake release` which will create the git tag and upload the
|
152
152
|
gem to github.com:
|
153
153
|
|
154
|
-
|
154
|
+
bundle exec rake release
|
155
155
|
|
156
156
|
The generated gem is located in the `pkg/` directory.
|
157
|
+
|
158
|
+
In order to build go binaries and upload the docker container with the
|
159
|
+
beetle GO binary to docker hub, run
|
160
|
+
|
161
|
+
make release
|
data/RELEASE_NOTES.rdoc
CHANGED
@@ -1,8 +1,14 @@
|
|
1
1
|
= Release Notes
|
2
2
|
|
3
|
+
== Version 2.0.1
|
4
|
+
|
5
|
+
* fix for beetle command not geting stuck when connecting to
|
6
|
+
configuration server
|
7
|
+
* configuration server displays last seen times in a human readable format
|
8
|
+
|
3
9
|
== Version 2.0.0
|
4
10
|
|
5
|
-
* beetle command has been rewritten in
|
11
|
+
* beetle command has been rewritten in Go
|
6
12
|
* garbage collecting redis keys now uses the redis SCAN command
|
7
13
|
|
8
14
|
== Version 1.0.4
|
data/Rakefile
CHANGED
data/beetle.gemspec
CHANGED
@@ -35,11 +35,11 @@ Gem::Specification.new do |s|
|
|
35
35
|
s.add_development_dependency "daemons", ">= 1.2.0"
|
36
36
|
s.add_development_dependency "i18n"
|
37
37
|
s.add_development_dependency "minitest", "~> 5.1"
|
38
|
-
s.add_development_dependency "mocha", "~> 1.
|
38
|
+
s.add_development_dependency "mocha", "~> 1.3.0"
|
39
39
|
s.add_development_dependency "mysql2", "~> 0.4.4"
|
40
40
|
s.add_development_dependency "rake", "~> 11.2"
|
41
41
|
s.add_development_dependency "rdoc", "~> 4.0"
|
42
|
-
s.add_development_dependency "simplecov", "~> 0.
|
43
|
-
s.add_development_dependency "webmock", "~>
|
42
|
+
s.add_development_dependency "simplecov", "~> 0.15"
|
43
|
+
s.add_development_dependency "webmock", "~> 3.0"
|
44
44
|
s.add_development_dependency "websocket-eventmachine-client"
|
45
45
|
end
|
@@ -126,17 +126,21 @@ end
|
|
126
126
|
|
127
127
|
Then /^a system notification for "([^\"]*)" not being available should be sent$/ do |redis_name|
|
128
128
|
text = "Redis master '#{TestDaemons::Redis[redis_name].ip_with_port}' not available"
|
129
|
-
|
129
|
+
lines = File.readlines(system_notification_log_path)
|
130
|
+
tail = (["","",""]+lines)[-3..-1].join("\n")
|
131
|
+
assert_match /#{text}/, tail
|
130
132
|
end
|
131
133
|
|
132
134
|
Then /^a system notification for switching from "([^\"]*)" to "([^\"]*)" should be sent$/ do |old_redis_master_name, new_redis_master_name|
|
133
135
|
text = "Setting redis master to '#{TestDaemons::Redis[new_redis_master_name].ip_with_port}' (was '#{TestDaemons::Redis[old_redis_master_name].ip_with_port}')"
|
134
|
-
|
136
|
+
lines = File.readlines(system_notification_log_path)
|
137
|
+
assert_match /#{Regexp.escape(text)}/, lines.last
|
135
138
|
end
|
136
139
|
|
137
140
|
Then /^a system notification for no slave available to become new master should be sent$/ do
|
138
141
|
text = "Redis master could not be switched, no slave available to become new master"
|
139
|
-
|
142
|
+
lines = File.readlines(system_notification_log_path)
|
143
|
+
assert_match /#{text}/, lines.last
|
140
144
|
end
|
141
145
|
|
142
146
|
Then /^the redis configuration server should answer http requests$/ do
|
data/features/support/env.rb
CHANGED
@@ -9,7 +9,7 @@ require File.expand_path("../../lib/beetle", File.dirname(__FILE__))
|
|
9
9
|
tmp_path = File.expand_path("../../tmp", File.dirname(__FILE__))
|
10
10
|
system_notification_log_file_path = "#{tmp_path}/system_notifications.log"
|
11
11
|
|
12
|
-
DEBUG =
|
12
|
+
DEBUG = false
|
13
13
|
|
14
14
|
Daemons.run_proc("system_notification_logger", :log_output => true, :dir_mode => :normal, :dir => tmp_path) do
|
15
15
|
Beetle.config.servers = "127.0.0.1:5672" # rabbitmq
|
@@ -34,11 +34,11 @@ Daemons.run_proc("system_notification_logger", :log_output => true, :dir_mode =>
|
|
34
34
|
end
|
35
35
|
ws.onclose do
|
36
36
|
puts "server closed connection" if DEBUG && !@interrupted
|
37
|
-
EM.add_timer(
|
37
|
+
EM.add_timer(0){ EM.stop_event_loop }
|
38
38
|
end
|
39
39
|
ws.onmessage do |text|
|
40
40
|
puts "writing message to #{system_notification_log_file_path}: #{text}"
|
41
|
-
log_file << text
|
41
|
+
log_file << (text + "\n")
|
42
42
|
end
|
43
43
|
puts "Started system notification logger"
|
44
44
|
trap("INT") { shutdown(ws) }
|
@@ -425,7 +425,7 @@ slave-priority 100
|
|
425
425
|
# Once the limit is reached Redis will close all the new connections sending
|
426
426
|
# an error 'max number of clients reached'.
|
427
427
|
#
|
428
|
-
|
428
|
+
maxclients 100
|
429
429
|
|
430
430
|
# Don't use more memory than the specified amount of bytes.
|
431
431
|
# When the memory limit is reached Redis will try to remove keys
|
@@ -43,16 +43,26 @@ module TestDaemons
|
|
43
43
|
create_config
|
44
44
|
daemon_controller.stop if running?
|
45
45
|
sleep delay
|
46
|
-
|
46
|
+
tries = 3
|
47
|
+
begin
|
48
|
+
daemon_controller.start
|
49
|
+
rescue DaemonController::StartError => e
|
50
|
+
puts "?????????? redis-server failed to start: #{e}"
|
51
|
+
retry if (tries -= 1) > 0
|
52
|
+
rescue DaemonController::AlreadyStarted => e
|
53
|
+
puts "?????????? redis-server already startes: #{e}"
|
54
|
+
end
|
47
55
|
end
|
48
56
|
|
49
57
|
def stop
|
50
58
|
return unless running?
|
51
59
|
# TODO: Might need to be moved into RedisConfigurationServer
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
60
|
+
10.times do
|
61
|
+
rdb_bgsave_in_progress, aof_rewrite_in_progress = redis.info_with_rescue.values_at("rdb_bgsave_in_progress", "aof_rewrite_in_progress")
|
62
|
+
break if rdb_bgsave_in_progress == "0" && aof_rewrite_in_progress == "0"
|
63
|
+
puts "#{Time.now} redis #{name} is still saving to disk"
|
64
|
+
sleep 1
|
65
|
+
end
|
56
66
|
daemon_controller.stop
|
57
67
|
raise "FAILED TO STOP redis server on port #{port}" if running?
|
58
68
|
ensure
|
@@ -29,7 +29,8 @@ module TestDaemons
|
|
29
29
|
:ping_command => lambda{ answers_text_requests? },
|
30
30
|
:pid_file => pid_file,
|
31
31
|
:log_file => log_file,
|
32
|
-
:start_timeout =>
|
32
|
+
:start_timeout => 10,
|
33
|
+
:stop_timeout => 10,
|
33
34
|
)
|
34
35
|
end
|
35
36
|
|
@@ -74,10 +75,8 @@ module TestDaemons
|
|
74
75
|
false
|
75
76
|
end
|
76
77
|
|
77
|
-
HTTP_SERVER_PORT = RUBY_PLATFORM =~ /darwin/ ? 9650 : 8080
|
78
|
-
|
79
78
|
def self.get_status(path, content_type)
|
80
|
-
uri = URI.parse("http://127.0.0.1
|
79
|
+
uri = URI.parse("http://127.0.0.1:9650#{path}")
|
81
80
|
http = Net::HTTP.new(uri.host, uri.port)
|
82
81
|
request = Net::HTTP::Get.new(uri.request_uri)
|
83
82
|
request['Accept'] = content_type
|
@@ -86,7 +85,7 @@ module TestDaemons
|
|
86
85
|
end
|
87
86
|
|
88
87
|
def self.initiate_master_switch
|
89
|
-
http = Net::HTTP.new('127.0.0.1',
|
88
|
+
http = Net::HTTP.new('127.0.0.1', 9650)
|
90
89
|
response = http.post '/initiate_master_switch', ''
|
91
90
|
response
|
92
91
|
end
|
data/lib/beetle/redis_ext.rb
CHANGED
@@ -46,10 +46,11 @@ class Redis #:nodoc:
|
|
46
46
|
info["role"] == "slave" && info["master_host"] == host && info["master_port"] == port.to_s
|
47
47
|
end
|
48
48
|
|
49
|
-
# compatibility layer for redis 2.2.2
|
50
|
-
# remove this once all our apps have upgraded to 3.x
|
51
49
|
if Redis::VERSION < "3.0"
|
52
50
|
|
51
|
+
# compatibility layer for redis 2.2.2
|
52
|
+
# remove this once all our apps have upgraded to 3.x
|
53
|
+
|
53
54
|
# Redis 2 tries to establish a connection on inspect. this is evil!
|
54
55
|
def inspect
|
55
56
|
super
|
@@ -77,5 +78,19 @@ class Redis #:nodoc:
|
|
77
78
|
def msetnx(*values)
|
78
79
|
super != 0
|
79
80
|
end
|
81
|
+
|
82
|
+
elsif Redis::VERSION >= "4.0.0"
|
83
|
+
|
84
|
+
# redis 4.0.0 has a shutdown method which raises if a connection to the redis server
|
85
|
+
# cannot be established.
|
86
|
+
module SaneShutdown
|
87
|
+
def shutdown
|
88
|
+
super
|
89
|
+
rescue CannotConnectError
|
90
|
+
nil
|
91
|
+
end
|
92
|
+
end
|
93
|
+
prepend SaneShutdown
|
94
|
+
|
80
95
|
end
|
81
96
|
end
|
data/lib/beetle/version.rb
CHANGED
@@ -40,23 +40,25 @@ module Beetle
|
|
40
40
|
end
|
41
41
|
|
42
42
|
test "creates a policy by posting to the rabbitmq" do
|
43
|
-
stub_request(:put, "http://
|
44
|
-
with(:
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
43
|
+
stub_request(:put, "http://localhost:15672/api/policies/%2F/QUEUE_NAME_policy")
|
44
|
+
.with(basic_auth: ['guest', 'guest'])
|
45
|
+
.with(:body => {
|
46
|
+
"pattern" => "^QUEUE_NAME$",
|
47
|
+
"priority" => 1,
|
48
|
+
"apply-to" => "queues",
|
49
|
+
"definition" => {
|
50
|
+
"dead-letter-routing-key" => "QUEUE_NAME_dead_letter",
|
51
|
+
"dead-letter-exchange" => ""
|
52
|
+
}}.to_json)
|
53
|
+
.to_return(:status => 204)
|
53
54
|
|
54
55
|
@dead_lettering.set_dead_letter_policy!(@server, @queue_name)
|
55
56
|
end
|
56
57
|
|
57
58
|
test "raises exception when policy couldn't successfully be created" do
|
58
|
-
stub_request(:put, "http://
|
59
|
-
|
59
|
+
stub_request(:put, "http://localhost:15672/api/policies/%2F/QUEUE_NAME_policy")
|
60
|
+
.with(basic_auth: ['guest', 'guest'])
|
61
|
+
.to_return(:status => [405])
|
60
62
|
|
61
63
|
assert_raises DeadLettering::FailedRabbitRequest do
|
62
64
|
@dead_lettering.set_dead_letter_policy!(@server, @queue_name)
|
@@ -64,32 +66,34 @@ module Beetle
|
|
64
66
|
end
|
65
67
|
|
66
68
|
test "can optionally specify a message ttl" do
|
67
|
-
stub_request(:put, "http://
|
68
|
-
with(:
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
69
|
+
stub_request(:put, "http://localhost:15672/api/policies/%2F/QUEUE_NAME_policy")
|
70
|
+
.with(basic_auth: ['guest', 'guest'])
|
71
|
+
.with(:body => {
|
72
|
+
"pattern" => "^QUEUE_NAME$",
|
73
|
+
"priority" => 1,
|
74
|
+
"apply-to" => "queues",
|
75
|
+
"definition" => {
|
76
|
+
"dead-letter-routing-key" => "QUEUE_NAME_dead_letter",
|
77
|
+
"dead-letter-exchange" => "",
|
78
|
+
"message-ttl" => 10000
|
79
|
+
}}.to_json)
|
80
|
+
.to_return(:status => 204)
|
78
81
|
|
79
82
|
@dead_lettering.set_dead_letter_policy!(@server, @queue_name, :message_ttl => 10000)
|
80
83
|
end
|
81
84
|
|
82
85
|
test "properly encodes the vhost from the configuration" do
|
83
|
-
stub_request(:put, "http://
|
84
|
-
with(:
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
86
|
+
stub_request(:put, "http://localhost:15672/api/policies/foo%2F/QUEUE_NAME_policy")
|
87
|
+
.with(basic_auth: ['guest', 'guest'])
|
88
|
+
.with(:body => {
|
89
|
+
"pattern" => "^QUEUE_NAME$",
|
90
|
+
"priority" => 1,
|
91
|
+
"apply-to" => "queues",
|
92
|
+
"definition" => {
|
93
|
+
"dead-letter-routing-key" => "QUEUE_NAME_dead_letter",
|
94
|
+
"dead-letter-exchange" => ""
|
95
|
+
}}.to_json)
|
96
|
+
.to_return(:status => 204)
|
93
97
|
|
94
98
|
@config.vhost = "foo/"
|
95
99
|
|
@@ -80,13 +80,20 @@ module Beetle
|
|
80
80
|
@r.shutdown
|
81
81
|
end
|
82
82
|
|
83
|
-
|
83
|
+
elsif Redis::VERSION < "4.0"
|
84
84
|
|
85
85
|
test "redis shutdown implementation should call :shutdown and return nil" do
|
86
86
|
@r.client.expects(:call).with([:shutdown]).once.raises(Redis::ConnectionError)
|
87
87
|
assert_nil @r.shutdown
|
88
88
|
end
|
89
89
|
|
90
|
+
else
|
91
|
+
|
92
|
+
test "patched redis shutdown implementation should not raise connection refused but return nil" do
|
93
|
+
# note that we do not have redis running on port 6390
|
94
|
+
assert_nil @r.shutdown
|
95
|
+
end
|
96
|
+
|
90
97
|
end
|
91
98
|
end
|
92
99
|
|
data/test/test_helper.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: beetle
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0.
|
4
|
+
version: 2.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Stefan Kaes
|
@@ -12,7 +12,7 @@ authors:
|
|
12
12
|
autorequire:
|
13
13
|
bindir: bin
|
14
14
|
cert_chain: []
|
15
|
-
date: 2017-
|
15
|
+
date: 2017-09-25 00:00:00.000000000 Z
|
16
16
|
dependencies:
|
17
17
|
- !ruby/object:Gem::Dependency
|
18
18
|
name: uuid4r
|
@@ -202,14 +202,14 @@ dependencies:
|
|
202
202
|
requirements:
|
203
203
|
- - "~>"
|
204
204
|
- !ruby/object:Gem::Version
|
205
|
-
version: 1.
|
205
|
+
version: 1.3.0
|
206
206
|
type: :development
|
207
207
|
prerelease: false
|
208
208
|
version_requirements: !ruby/object:Gem::Requirement
|
209
209
|
requirements:
|
210
210
|
- - "~>"
|
211
211
|
- !ruby/object:Gem::Version
|
212
|
-
version: 1.
|
212
|
+
version: 1.3.0
|
213
213
|
- !ruby/object:Gem::Dependency
|
214
214
|
name: mysql2
|
215
215
|
requirement: !ruby/object:Gem::Requirement
|
@@ -258,28 +258,28 @@ dependencies:
|
|
258
258
|
requirements:
|
259
259
|
- - "~>"
|
260
260
|
- !ruby/object:Gem::Version
|
261
|
-
version: 0.
|
261
|
+
version: '0.15'
|
262
262
|
type: :development
|
263
263
|
prerelease: false
|
264
264
|
version_requirements: !ruby/object:Gem::Requirement
|
265
265
|
requirements:
|
266
266
|
- - "~>"
|
267
267
|
- !ruby/object:Gem::Version
|
268
|
-
version: 0.
|
268
|
+
version: '0.15'
|
269
269
|
- !ruby/object:Gem::Dependency
|
270
270
|
name: webmock
|
271
271
|
requirement: !ruby/object:Gem::Requirement
|
272
272
|
requirements:
|
273
273
|
- - "~>"
|
274
274
|
- !ruby/object:Gem::Version
|
275
|
-
version:
|
275
|
+
version: '3.0'
|
276
276
|
type: :development
|
277
277
|
prerelease: false
|
278
278
|
version_requirements: !ruby/object:Gem::Requirement
|
279
279
|
requirements:
|
280
280
|
- - "~>"
|
281
281
|
- !ruby/object:Gem::Version
|
282
|
-
version:
|
282
|
+
version: '3.0'
|
283
283
|
- !ruby/object:Gem::Dependency
|
284
284
|
name: websocket-eventmachine-client
|
285
285
|
requirement: !ruby/object:Gem::Requirement
|
@@ -389,7 +389,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
389
389
|
version: 1.3.7
|
390
390
|
requirements: []
|
391
391
|
rubyforge_project:
|
392
|
-
rubygems_version: 2.6.
|
392
|
+
rubygems_version: 2.6.13
|
393
393
|
signing_key:
|
394
394
|
specification_version: 3
|
395
395
|
summary: High Availability AMQP Messaging with Redundant Queues
|