beetle 0.2.3 → 0.2.5
Sign up to get free protection for your applications and to get access to all the features.
- data/MIT-LICENSE +20 -0
- data/REDIS_AUTO_FAILOVER.rdoc +124 -0
- data/RELEASE_NOTES.rdoc +50 -0
- data/Rakefile +113 -0
- data/beetle.gemspec +3 -3
- data/features/README.rdoc +23 -0
- data/features/redis_auto_failover.feature +105 -0
- data/features/step_definitions/redis_auto_failover_steps.rb +133 -0
- data/features/support/beetle_handler +32 -0
- data/features/support/env.rb +48 -0
- data/features/support/system_notification_logger +31 -0
- data/features/support/test_daemons/redis.conf.erb +189 -0
- data/features/support/test_daemons/redis.rb +186 -0
- data/features/support/test_daemons/redis_configuration_client.rb +64 -0
- data/features/support/test_daemons/redis_configuration_server.rb +52 -0
- data/lib/beetle/redis_configuration_server.rb +10 -0
- data/script/console +28 -0
- data/script/start_rabbit +29 -0
- data/test/beetle/deduplication_store_test.rb +3 -1
- data/test/beetle/redis_configuration_server_test.rb +18 -0
- metadata +25 -4
@@ -0,0 +1,64 @@
|
|
1
|
+
require 'daemon_controller'
|
2
|
+
|
3
|
+
module TestDaemons
|
4
|
+
class RedisConfigurationClient
|
5
|
+
cattr_reader :instances
|
6
|
+
@@next_daemon_id = 0
|
7
|
+
@@instances = {}
|
8
|
+
|
9
|
+
def initialize(name)
|
10
|
+
@name = name
|
11
|
+
@daemon_id = @@next_daemon_id
|
12
|
+
|
13
|
+
@@next_daemon_id += 1
|
14
|
+
@@instances[name] = self
|
15
|
+
end
|
16
|
+
|
17
|
+
class << self
|
18
|
+
def find_or_initialize_by_name(name)
|
19
|
+
@@instances[name] ||= new(name)
|
20
|
+
end
|
21
|
+
alias_method :[], :find_or_initialize_by_name
|
22
|
+
|
23
|
+
def stop_all
|
24
|
+
@@instances.values.each{|i| i.stop}
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def start
|
29
|
+
daemon_controller.start
|
30
|
+
end
|
31
|
+
|
32
|
+
def stop
|
33
|
+
daemon_controller.stop
|
34
|
+
end
|
35
|
+
|
36
|
+
def daemon_controller
|
37
|
+
@daemon_controller ||= DaemonController.new(
|
38
|
+
:identifier => "Redis configuration test client",
|
39
|
+
:start_command => "ruby bin/beetle configuration_client start -- -v --redis-master-file #{redis_master_file} --id #{@name} --pid-dir #{tmp_path} --amqp-servers 127.0.0.1:5672",
|
40
|
+
:ping_command => lambda{ true },
|
41
|
+
:pid_file => pid_file,
|
42
|
+
:log_file => log_file,
|
43
|
+
:start_timeout => 5
|
44
|
+
)
|
45
|
+
end
|
46
|
+
|
47
|
+
def redis_master_file
|
48
|
+
"#{tmp_path}/redis-master-#{@name}"
|
49
|
+
end
|
50
|
+
|
51
|
+
def pid_file
|
52
|
+
"#{tmp_path}/redis_configuration_client#{@daemon_id}.pid"
|
53
|
+
end
|
54
|
+
|
55
|
+
def log_file
|
56
|
+
"#{tmp_path}/redis_configuration_client.output"
|
57
|
+
end
|
58
|
+
|
59
|
+
def tmp_path
|
60
|
+
File.expand_path(File.dirname(__FILE__) + "/../../../tmp")
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'daemon_controller'
|
2
|
+
|
3
|
+
module TestDaemons
|
4
|
+
class RedisConfigurationServer
|
5
|
+
|
6
|
+
# At the moment, we need only one, so we implement the methods
|
7
|
+
# as class methods
|
8
|
+
|
9
|
+
@@redis_servers = ""
|
10
|
+
@@redis_configuration_clients = ""
|
11
|
+
|
12
|
+
def self.start(redis_servers, redis_configuration_clients)
|
13
|
+
stop
|
14
|
+
@@redis_servers = redis_servers
|
15
|
+
@@redis_configuration_clients = redis_configuration_clients
|
16
|
+
daemon_controller.start
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.stop
|
20
|
+
daemon_controller.stop
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.daemon_controller
|
24
|
+
clients_parameter_string = @@redis_configuration_clients.blank? ? "" : "--client-ids #{@@redis_configuration_clients}"
|
25
|
+
DaemonController.new(
|
26
|
+
:identifier => "Redis configuration test server",
|
27
|
+
:start_command => "ruby bin/beetle configuration_server start -- -v --redis-master-file #{redis_master_file} --redis-servers #{@@redis_servers} #{clients_parameter_string} --redis-retry-interval 1 --pid-dir #{tmp_path} --amqp-servers 127.0.0.1:5672",
|
28
|
+
:ping_command => lambda{ true },
|
29
|
+
:pid_file => pid_file,
|
30
|
+
:log_file => log_file,
|
31
|
+
:start_timeout => 5
|
32
|
+
)
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.redis_master_file
|
36
|
+
"#{tmp_path}/redis-master-rc-server"
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.pid_file
|
40
|
+
"#{tmp_path}/redis_configuration_server.pid"
|
41
|
+
end
|
42
|
+
|
43
|
+
def self.log_file
|
44
|
+
"#{tmp_path}/redis_configuration_server.output"
|
45
|
+
end
|
46
|
+
|
47
|
+
def self.tmp_path
|
48
|
+
File.expand_path(File.dirname(__FILE__) + "/../../../tmp")
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
end
|
@@ -64,6 +64,7 @@ module Beetle
|
|
64
64
|
def pong(payload)
|
65
65
|
id = payload["id"]
|
66
66
|
token = payload["token"]
|
67
|
+
return unless validate_pong_client_id(id)
|
67
68
|
logger.info "Received pong message from id '#{id}' with token '#{token}'"
|
68
69
|
return unless redeem_token(token)
|
69
70
|
@client_pong_ids_received << id
|
@@ -164,6 +165,15 @@ module Beetle
|
|
164
165
|
redis.unknowns.include?(current_master) ? redis.slaves_of(current_master).first : current_master
|
165
166
|
end
|
166
167
|
|
168
|
+
def validate_pong_client_id(client_id)
|
169
|
+
unless known_client = @client_ids.include?(client_id)
|
170
|
+
msg = "Received pong message from unknown client '#{client_id}'"
|
171
|
+
logger.error(msg)
|
172
|
+
beetle.publish(:system_notification, {"message" => msg}.to_json)
|
173
|
+
end
|
174
|
+
known_client
|
175
|
+
end
|
176
|
+
|
167
177
|
def redeem_token(token)
|
168
178
|
valid_token = token == @current_token
|
169
179
|
logger.info "Ignored message (token was '#{token.inspect}', but expected '#{@current_token.inspect}')" unless valid_token
|
data/script/console
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'rubygems'
|
3
|
+
require 'optparse'
|
4
|
+
|
5
|
+
options = { }
|
6
|
+
OptionParser.new do |opt|
|
7
|
+
opt.banner = "Usage: console [options]"
|
8
|
+
opt.on("--debugger", 'Enable ruby-debugging for the console.') { |v| options[:debugger] = v }
|
9
|
+
opt.parse!(ARGV)
|
10
|
+
end
|
11
|
+
|
12
|
+
libs = " -r irb/completion"
|
13
|
+
libs << %( -r ubygems)
|
14
|
+
libs << %( -r #{File.expand_path("../../lib/beetle.rb",__FILE__)})
|
15
|
+
|
16
|
+
if options[:debugger]
|
17
|
+
begin
|
18
|
+
require 'ruby-debug'
|
19
|
+
libs << " -r ruby-debug"
|
20
|
+
puts "=> Debugger enabled"
|
21
|
+
rescue Exception
|
22
|
+
puts "You need to install ruby-debug to run the console in debugging mode. With gems, use 'gem install ruby-debug'"
|
23
|
+
exit
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
irb = RUBY_PLATFORM =~ /(:?mswin|mingw)/ ? 'irb.bat' : 'irb'
|
28
|
+
exec "#{irb} #{libs} --simple-prompt"
|
data/script/start_rabbit
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
|
3
|
+
# export RABBITMQ_MNESIA_BASE=/var/lib/rabbitmq/mnesia2
|
4
|
+
# Defaults to /var/lib/rabbitmq/mnesia. Set this to the directory where Mnesia
|
5
|
+
# database files should be placed.
|
6
|
+
|
7
|
+
# export RABBITMQ_LOG_BASE
|
8
|
+
# Defaults to /var/log/rabbitmq. Log files generated by the server will be placed
|
9
|
+
# in this directory.
|
10
|
+
|
11
|
+
export RABBITMQ_NODENAME=$1
|
12
|
+
# Defaults to rabbit. This can be useful if you want to run more than one node
|
13
|
+
# per machine - RABBITMQ_NODENAME should be unique per erlang-node-and-machine
|
14
|
+
# combination. See clustering on a single machine guide at <http://www.rab-
|
15
|
+
# bitmq.com/clustering.html#single-machine> for details.
|
16
|
+
|
17
|
+
# RABBITMQ_NODE_IP_ADDRESS
|
18
|
+
# Defaults to 0.0.0.0. This can be changed if you only want to bind to one net-
|
19
|
+
# work interface.
|
20
|
+
|
21
|
+
export RABBITMQ_NODE_PORT=$2
|
22
|
+
# Defaults to 5672.
|
23
|
+
|
24
|
+
# RABBITMQ_CLUSTER_CONFIG_FILE
|
25
|
+
# Defaults to /etc/rabbitmq/rabbitmq_cluster.config. If this file is present it
|
26
|
+
# is used by the server to auto-configure a RabbitMQ cluster. See the clustering
|
27
|
+
# guide at <http://www.rabbitmq.com/clustering.html> for details.
|
28
|
+
|
29
|
+
rabbitmq-server
|
@@ -73,7 +73,9 @@ module Beetle
|
|
73
73
|
|
74
74
|
private
|
75
75
|
def redis_test_master_file(server_string)
|
76
|
-
|
76
|
+
tmp_dir = File.expand_path("../../../tmp", __FILE__)
|
77
|
+
Dir.mkdir(tmp_dir) unless File.exists?(tmp_dir)
|
78
|
+
path = tmp_dir + "/redis-master-for-unit-tests"
|
77
79
|
File.open(path, "w"){|f| f.puts server_string}
|
78
80
|
path
|
79
81
|
end
|
@@ -275,4 +275,22 @@ module Beetle
|
|
275
275
|
info
|
276
276
|
end
|
277
277
|
end
|
278
|
+
|
279
|
+
class RedisConfigurationServerSystemNotificationAndLoggingTest < Test::Unit::TestCase
|
280
|
+
def setup
|
281
|
+
Beetle.config.redis_configuration_client_ids = "rc-client-1,rc-client-2"
|
282
|
+
@server = RedisConfigurationServer.new
|
283
|
+
@server.stubs(:beetle).returns(stub(:publish))
|
284
|
+
@server.stubs(:logger).returns(stub)
|
285
|
+
EventMachine.stubs(:add_timer).yields
|
286
|
+
end
|
287
|
+
|
288
|
+
test "should log and send a system notification when pong message from unknown client received" do
|
289
|
+
payload = {"id" => "unknown-client", "token" => @server.current_token}
|
290
|
+
msg = "Received pong message from unknown client 'unknown-client'"
|
291
|
+
@server.beetle.expects(:publish).with(:system_notification, ({:message => msg}).to_json)
|
292
|
+
@server.logger.expects(:error).with(msg)
|
293
|
+
@server.pong(payload)
|
294
|
+
end
|
295
|
+
end
|
278
296
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: beetle
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 29
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 2
|
9
|
-
-
|
10
|
-
version: 0.2.
|
9
|
+
- 5
|
10
|
+
version: 0.2.5
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Stefan Kaes
|
@@ -18,7 +18,7 @@ autorequire:
|
|
18
18
|
bindir: bin
|
19
19
|
cert_chain: []
|
20
20
|
|
21
|
-
date: 2010-
|
21
|
+
date: 2010-08-23 00:00:00 +02:00
|
22
22
|
default_executable: beetle
|
23
23
|
dependencies:
|
24
24
|
- !ruby/object:Gem::Dependency
|
@@ -182,7 +182,12 @@ executables:
|
|
182
182
|
extensions:
|
183
183
|
- ext/mkrf_conf.rb
|
184
184
|
extra_rdoc_files:
|
185
|
+
- examples/README.rdoc
|
186
|
+
- features/README.rdoc
|
185
187
|
- README.rdoc
|
188
|
+
- REDIS_AUTO_FAILOVER.rdoc
|
189
|
+
- RELEASE_NOTES.rdoc
|
190
|
+
- MIT-LICENSE
|
186
191
|
files:
|
187
192
|
- examples/attempts.rb
|
188
193
|
- examples/handler_class.rb
|
@@ -212,9 +217,25 @@ files:
|
|
212
217
|
- lib/beetle/redis_server_info.rb
|
213
218
|
- lib/beetle/subscriber.rb
|
214
219
|
- lib/beetle.rb
|
220
|
+
- features/README.rdoc
|
221
|
+
- features/redis_auto_failover.feature
|
222
|
+
- features/step_definitions/redis_auto_failover_steps.rb
|
223
|
+
- features/support/beetle_handler
|
224
|
+
- features/support/env.rb
|
225
|
+
- features/support/system_notification_logger
|
226
|
+
- features/support/test_daemons/redis.conf.erb
|
227
|
+
- features/support/test_daemons/redis.rb
|
228
|
+
- features/support/test_daemons/redis_configuration_client.rb
|
229
|
+
- features/support/test_daemons/redis_configuration_server.rb
|
230
|
+
- script/console
|
231
|
+
- script/start_rabbit
|
215
232
|
- beetle.gemspec
|
233
|
+
- Rakefile
|
216
234
|
- examples/README.rdoc
|
217
235
|
- README.rdoc
|
236
|
+
- REDIS_AUTO_FAILOVER.rdoc
|
237
|
+
- RELEASE_NOTES.rdoc
|
238
|
+
- MIT-LICENSE
|
218
239
|
- test/beetle/base_test.rb
|
219
240
|
- test/beetle/client_test.rb
|
220
241
|
- test/beetle/configuration_test.rb
|