beetle 2.0.0 → 2.0.1
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.
- 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
|