beetle 0.2.1 → 0.2.4

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.
data/README.rdoc CHANGED
@@ -54,12 +54,11 @@ windows and execute the following commands:
54
54
  rake redis:start1
55
55
  rake redis:start2
56
56
 
57
-
58
57
  == Prerequisites
59
58
 
60
59
  To set up a redundant messaging system you will need
61
60
  * at least 2 AMQP servers (we use {RabbitMQ}[http://www.rabbitmq.com/])
62
- * at least one Redis server (better are two in a master/slave setup)
61
+ * at least one {Redis}[http://github.com/antirez/redis] server (better are two in a master/slave setup)
63
62
 
64
63
  == Gem Dependencies
65
64
 
@@ -67,15 +66,17 @@ At runtime, Beetle will use
67
66
  * {uuid4r}[http://github.com/skaes/uuid4r]
68
67
  (which needs ossp-uuid)
69
68
  * {bunny}[http://github.com/celldee/bunny]
70
- * {redis-rb}[http://github.com/ezmobius/redis-rb]
71
- (which needs {redis}[http://github.com/antirez/redis])
69
+ * {redis}[http://github.com/ezmobius/redis-rb]
72
70
  * {amqp}[http://github.com/tmm1/amqp]
73
71
  (which is based on {eventmachine}[http://github.com/eventmachine/eventmachine])
72
+ * {daemons}[http://daemons.rubyforge.org/]
74
73
  * activesupport
75
74
 
76
75
  For development, you'll need
77
- * mocha
78
- * rcov
76
+ * {mocha}[http://github.com/floehopper/mocha]
77
+ * {rcov}[http://github.com/relevance/rcov]
78
+ * {cucumber}[http://github.com/aslakhellesoy/cucumber]
79
+ * {daemon_controller}[http://github.com/FooBarWidget/daemon_controller]
79
80
 
80
81
  == Authors
81
82
 
data/beetle.gemspec CHANGED
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = "beetle"
3
- s.version = "0.2.1"
3
+ s.version = "0.2.4"
4
4
 
5
5
  s.required_rubygems_version = ">= 1.3.1"
6
6
  s.authors = ["Stefan Kaes", "Pascal Friederich", "Ali Jelveh", "Sebastian Roebke"]
@@ -31,7 +31,7 @@ Gem::Specification.new do |s|
31
31
  s.specification_version = 3
32
32
  s.add_runtime_dependency("uuid4r", [">= 0.1.1"])
33
33
  s.add_runtime_dependency("bunny", [">= 0.6.0"])
34
- s.add_runtime_dependency("redis", [">= 2.0.3"])
34
+ s.add_runtime_dependency("redis", [">= 2.0.4"])
35
35
  s.add_runtime_dependency("amqp", [">= 0.6.7"])
36
36
  s.add_runtime_dependency("activesupport", [">= 2.3.4"])
37
37
  s.add_runtime_dependency("daemons", [">= 1.0.10"])
@@ -46,7 +46,7 @@ module Beetle
46
46
 
47
47
  dir_mode = nil
48
48
  dir = nil
49
- opts.on("--pid-dir DIR", String, "Write pid and log to DIR") do |val|
49
+ opts.on("--pid-dir DIR", String, "Write pid and output to DIR") do |val|
50
50
  dir_mode = :normal
51
51
  dir = val
52
52
  end
@@ -55,7 +55,7 @@ module Beetle
55
55
 
56
56
  dir_mode = nil
57
57
  dir = nil
58
- opts.on("--pid-dir DIR", String, "Write pid and log to DIR") do |val|
58
+ opts.on("--pid-dir DIR", String, "Write pid and output to DIR") do |val|
59
59
  dir_mode = :normal
60
60
  dir = val
61
61
  end
@@ -4,8 +4,10 @@ module Beetle
4
4
  class Configuration
5
5
  # system name (used for redis cluster partitioning) (defaults to <tt>system</tt>)
6
6
  attr_accessor :system_name
7
- # default logger (defaults to <tt>Logger.new(STDOUT)</tt>)
7
+ # default logger (defaults to <tt>Logger.new(log_file)</tt>)
8
8
  attr_accessor :logger
9
+ # defaults to <tt>STDOUT</tt>
10
+ attr_accessor :log_file
9
11
  # number of seconds after which keys are removed form the message deduplication store (defaults to <tt>3.days</tt>)
10
12
  attr_accessor :gc_threshold
11
13
  # the redis server to use for deduplication
@@ -49,14 +51,6 @@ module Beetle
49
51
  def initialize #:nodoc:
50
52
  self.system_name = "system"
51
53
 
52
- self.logger = begin
53
- logger = Logger.new(STDOUT)
54
- logger.formatter = Logger::Formatter.new
55
- logger.level = Logger::INFO
56
- logger.datetime_format = "%Y-%m-%d %H:%M:%S"
57
- logger
58
- end
59
-
60
54
  self.gc_threshold = 3.days
61
55
  self.redis_server = "localhost:6379"
62
56
  self.redis_servers = ""
@@ -72,6 +66,8 @@ module Beetle
72
66
  self.vhost = "/"
73
67
  self.user = "guest"
74
68
  self.password = "guest"
69
+
70
+ self.log_file = STDOUT
75
71
  end
76
72
 
77
73
  # setting the external config file will load it on assignment
@@ -80,6 +76,16 @@ module Beetle
80
76
  load_config
81
77
  end
82
78
 
79
+ def logger
80
+ @logger ||= begin
81
+ l = Logger.new(log_file)
82
+ l.formatter = Logger::Formatter.new
83
+ l.level = Logger::INFO
84
+ l.datetime_format = "%Y-%m-%d %H:%M:%S"
85
+ l
86
+ end
87
+ end
88
+
83
89
  private
84
90
  def load_config
85
91
  hash = YAML::load(ERB.new(IO.read(config_file)).result)
@@ -279,7 +279,7 @@ module Beetle
279
279
  end
280
280
 
281
281
  def run_handler(handler)
282
- Redis::Timer.timeout(@timeout.to_f) { @handler_result = handler.call(self) }
282
+ Timer.timeout(@timeout.to_f) { @handler_result = handler.call(self) }
283
283
  RC::OK
284
284
  rescue Exception => @exception
285
285
  Beetle::reraise_expectation_errors!
@@ -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
@@ -51,29 +51,3 @@ class Redis #:nodoc:
51
51
  info["role"] == "slave" && info["master_host"] == host && info["master_port"] == port.to_s
52
52
  end
53
53
  end
54
-
55
- class Redis::Client #:nodoc:
56
- protected
57
- def connect_to(host, port)
58
- if @timeout != 0 and Redis::Timer
59
- begin
60
- Redis::Timer.timeout(@timeout){ @sock = TCPSocket.new(host, port) }
61
- rescue Timeout::Error
62
- @sock = nil
63
- raise Timeout::Error, "Timeout connecting to the server"
64
- end
65
- else
66
- @sock = TCPSocket.new(host, port)
67
- end
68
-
69
- @sock.setsockopt Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1
70
-
71
- # If the timeout is set we set the low level socket options in order
72
- # to make sure a blocking read will return after the specified number
73
- # of seconds. This hack is from memcached ruby client.
74
- self.timeout = @timeout
75
-
76
- rescue Errno::ECONNREFUSED
77
- raise Errno::ECONNREFUSED, "Unable to connect to Redis on #{host}:#{port}"
78
- end
79
- end
data/lib/beetle.rb CHANGED
@@ -54,4 +54,5 @@ module Beetle
54
54
  end
55
55
  end
56
56
 
57
+ Timer = RUBY_VERSION < "1.9" ? SystemTimer : Timeout
57
58
  end
@@ -1,5 +1,4 @@
1
1
  require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
2
- require 'tempfile'
3
2
 
4
3
  module Beetle
5
4
  class ConfigurationTest < Test::Unit::TestCase
@@ -13,5 +12,19 @@ module Beetle
13
12
  config.config_file = "some/path/to/a/file"
14
13
  assert_equal new_value, config.gc_threshold
15
14
  end
15
+
16
+ test "should log to STDOUT if no log_file given" do
17
+ config = Configuration.new
18
+ Logger.expects(:new).with(STDOUT).returns(stub_everything)
19
+ config.logger
20
+ end
21
+
22
+ test "should log to file if log_file given" do
23
+ file = '/path/to/file'
24
+ config = Configuration.new
25
+ config.log_file = file
26
+ Logger.expects(:new).with(file).returns(stub_everything)
27
+ config.logger
28
+ end
16
29
  end
17
30
  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
@@ -56,15 +56,9 @@ module Beetle
56
56
  end
57
57
 
58
58
  class RedisTimeoutTest < Test::Unit::TestCase
59
- test "should use Redis::Timer if timeout is greater 0" do
59
+ test "should use a timer" do
60
60
  r = Redis.new(:host => "localhost", :port => 6390, :timeout => 1)
61
- Redis::Timer.expects(:timeout).with(1).raises(Timeout::Error)
62
- assert_equal({}, r.info_with_rescue)
63
- end
64
-
65
- test "should not use Redis::Timer if timeout 0" do
66
- r = Redis.new(:host => "localhost", :port => 6390, :timeout => 0)
67
- Redis::Timer.expects(:timeout).never
61
+ r.client.expects(:with_timeout).with(1).raises(Timeout::Error)
68
62
  assert_equal({}, r.info_with_rescue)
69
63
  end
70
64
  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: 21
4
+ hash: 31
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 2
9
- - 1
10
- version: 0.2.1
9
+ - 4
10
+ version: 0.2.4
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-07-22 00:00:00 +02:00
21
+ date: 2010-08-06 00:00:00 +02:00
22
22
  default_executable: beetle
23
23
  dependencies:
24
24
  - !ruby/object:Gem::Dependency
@@ -61,12 +61,12 @@ dependencies:
61
61
  requirements:
62
62
  - - ">="
63
63
  - !ruby/object:Gem::Version
64
- hash: 9
64
+ hash: 7
65
65
  segments:
66
66
  - 2
67
67
  - 0
68
- - 3
69
- version: 2.0.3
68
+ - 4
69
+ version: 2.0.4
70
70
  type: :runtime
71
71
  version_requirements: *id003
72
72
  - !ruby/object:Gem::Dependency