beetle 0.2.5 → 0.2.6

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/RELEASE_NOTES.rdoc CHANGED
@@ -1,5 +1,11 @@
1
1
  = Release Notes
2
2
 
3
+ == Version 0.2.6
4
+
5
+ * Set dependency on ActiveSupport to 2.3.x since it ain't compatible to version 3.x yet
6
+ * Publishers catch a wider range (all?) of possible exceptions when publishing messages
7
+ * Redis Configuration Servers detect and warn when unknown Redis Configuration Clients connect
8
+
3
9
  == Version 0.2.5
4
10
 
5
11
  Added missing files to gem and rdoc
data/Rakefile CHANGED
@@ -2,6 +2,7 @@ require 'rake'
2
2
  require 'rake/testtask'
3
3
  require 'rcov/rcovtask'
4
4
  require 'cucumber/rake/task'
5
+ require 'active_support'
5
6
 
6
7
  # 1.8/1.9 compatible way of loading lib/beetle.rb
7
8
  $:.unshift 'lib'
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.5"
3
+ s.version = "0.2.6"
4
4
 
5
5
  s.required_rubygems_version = ">= 1.3.1"
6
6
  s.authors = ["Stefan Kaes", "Pascal Friederich", "Ali Jelveh", "Sebastian Roebke"]
@@ -33,7 +33,7 @@ Gem::Specification.new do |s|
33
33
  s.add_runtime_dependency("bunny", [">= 0.6.0"])
34
34
  s.add_runtime_dependency("redis", [">= 2.0.4"])
35
35
  s.add_runtime_dependency("amqp", [">= 0.6.7"])
36
- s.add_runtime_dependency("activesupport", [">= 2.3.4"])
36
+ s.add_runtime_dependency("activesupport", ["~> 2.3.4"])
37
37
  s.add_runtime_dependency("daemons", [">= 1.0.10"])
38
38
  s.add_development_dependency("mocha", [">= 0"])
39
39
  s.add_development_dependency("rcov", [">= 0"])
@@ -9,6 +9,17 @@ module Beetle
9
9
  @bunnies = {}
10
10
  end
11
11
 
12
+ # list of exceptions potentially raised by bunny
13
+ # these need to be lazy, because qrack exceptions are only defined after a connection has been established
14
+ def bunny_exceptions
15
+ [
16
+ Bunny::ConnectionError, Bunny::ForcedChannelCloseError, Bunny::ForcedConnectionCloseError,
17
+ Bunny::MessageError, Bunny::ProtocolError, Bunny::ServerDownError, Bunny::UnsubscribeError,
18
+ Bunny::AcknowledgementError, Qrack::BufferOverflowError, Qrack::InvalidTypeError,
19
+ Errno::EHOSTUNREACH, Errno::ECONNRESET
20
+ ]
21
+ end
22
+
12
23
  def publish(message_name, data, opts={}) #:nodoc:
13
24
  opts = @client.messages[message_name].merge(opts.symbolize_keys)
14
25
  exchange_name = opts.delete(:exchange)
@@ -33,7 +44,7 @@ module Beetle
33
44
  exchange(exchange_name).publish(data, opts)
34
45
  logger.debug "Beetle: message sent!"
35
46
  published = 1
36
- rescue Bunny::ServerDownError, Bunny::ConnectionError
47
+ rescue *bunny_exceptions
37
48
  stop!
38
49
  mark_server_dead
39
50
  tries -= 1
@@ -60,7 +71,7 @@ module Beetle
60
71
  exchange(exchange_name).publish(data, opts)
61
72
  published << @server
62
73
  logger.debug "Beetle: message sent (#{published})!"
63
- rescue Bunny::ServerDownError, Bunny::ConnectionError
74
+ rescue *bunny_exceptions
64
75
  stop!
65
76
  mark_server_dead
66
77
  end
@@ -101,7 +112,7 @@ module Beetle
101
112
  status = msg[:header].properties[:headers][:status]
102
113
  end
103
114
  logger.debug "Beetle: rpc complete!"
104
- rescue Bunny::ServerDownError, Bunny::ConnectionError
115
+ rescue *bunny_exceptions
105
116
  stop!
106
117
  mark_server_dead
107
118
  tries -= 1
@@ -37,6 +37,7 @@ module Beetle
37
37
  # loop, reacting to failover related messages sent by RedisConfigurationServer.
38
38
  def start
39
39
  verify_redis_master_file_string
40
+ client_started!
40
41
  logger.info "RedisConfigurationClient starting (client id: #{id})"
41
42
  determine_initial_master
42
43
  clear_redis_master_file unless current_master.try(:master?)
@@ -102,6 +103,7 @@ module Beetle
102
103
  config.message :client_invalidated
103
104
  config.message :reconfigure
104
105
  config.queue :reconfigure, :amqp_name => "#{system}_reconfigure_#{id}"
106
+ config.message :client_started
105
107
 
106
108
  config.handler [:ping, :invalidate, :reconfigure], MessageDispatcher
107
109
  end
@@ -118,6 +120,10 @@ module Beetle
118
120
  beetle.publish(:pong, {"id" => id, "token" => @current_token}.to_json)
119
121
  end
120
122
 
123
+ def client_started!
124
+ beetle.publish(:client_started, {"id" => id}.to_json)
125
+ end
126
+
121
127
  def invalidate!
122
128
  @current_master = nil
123
129
  clear_redis_master_file
@@ -75,6 +75,17 @@ module Beetle
75
75
  end
76
76
  end
77
77
 
78
+ def client_started(payload)
79
+ id = payload["id"]
80
+ if client_id_valid?(id)
81
+ logger.info("Received client_started message from id #{id}")
82
+ else
83
+ msg = "Received client_started message from unknown id '#{id}'"
84
+ logger.error(msg)
85
+ beetle.publish(:system_notification, {"message" => msg}.to_json)
86
+ end
87
+ end
88
+
78
89
  # called by the message dispatcher when a "client_invalidated" message from a RedisConfigurationClient is received
79
90
  def client_invalidated(payload)
80
91
  id = payload["id"]
@@ -139,8 +150,10 @@ module Beetle
139
150
  config.message :invalidate
140
151
  config.message :reconfigure
141
152
  config.message :system_notification
153
+ config.message :client_started
154
+ config.queue :client_started, :amqp_name => "#{system}_client_started"
142
155
 
143
- config.handler [:pong, :client_invalidated], MessageDispatcher
156
+ config.handler [:pong, :client_invalidated, :client_started], MessageDispatcher
144
157
  end
145
158
  end
146
159
 
@@ -166,13 +179,17 @@ module Beetle
166
179
  end
167
180
 
168
181
  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}'"
182
+ unless known_client = client_id_valid?(client_id)
183
+ msg = "Received pong message from unknown id '#{client_id}'"
171
184
  logger.error(msg)
172
185
  beetle.publish(:system_notification, {"message" => msg}.to_json)
173
186
  end
174
187
  known_client
175
188
  end
189
+
190
+ def client_id_valid?(client_id)
191
+ @client_ids.include?(client_id)
192
+ end
176
193
 
177
194
  def redeem_token(token)
178
195
  valid_token = token == @current_token
@@ -10,6 +10,12 @@ module Beetle
10
10
  @client.stubs(:verify_redis_master_file_string)
11
11
  end
12
12
 
13
+ test "should send a client_started message when started" do
14
+ @client.stubs(:clear_redis_master_file)
15
+ @client.beetle.expects(:publish).with(:client_started, {:id => @client.id}.to_json)
16
+ @client.start
17
+ end
18
+
13
19
  test "config should return the beetle config" do
14
20
  assert_equal Beetle.config, @client.config
15
21
  end
@@ -287,10 +287,18 @@ module Beetle
287
287
 
288
288
  test "should log and send a system notification when pong message from unknown client received" do
289
289
  payload = {"id" => "unknown-client", "token" => @server.current_token}
290
- msg = "Received pong message from unknown client 'unknown-client'"
290
+ msg = "Received pong message from unknown id 'unknown-client'"
291
291
  @server.beetle.expects(:publish).with(:system_notification, ({:message => msg}).to_json)
292
292
  @server.logger.expects(:error).with(msg)
293
293
  @server.pong(payload)
294
294
  end
295
+
296
+ test "should warn about unknown clients when receiving client_started messages" do
297
+ payload = {"id" => "unknown-client"}
298
+ msg = "Received client_started message from unknown id 'unknown-client'"
299
+ @server.beetle.expects(:publish).with(:system_notification, ({:message => msg}).to_json)
300
+ @server.logger.expects(:error).with(msg)
301
+ @server.client_started(payload)
302
+ end
295
303
  end
296
304
  end
data/test/test_helper.rb CHANGED
@@ -3,9 +3,20 @@ require 'active_support'
3
3
  require 'active_support/testing/declarative'
4
4
  require 'test/unit'
5
5
  begin
6
- require 'redgreen' unless ENV['TM_FILENAME']
6
+ require 'redgreen' unless ENV['TM_FILENAME']
7
7
  rescue MissingSourceFile
8
8
  end
9
+
10
+ # we can remove this hack which is needed only for testing
11
+ begin
12
+ require 'qrack/errors'
13
+ rescue LoadError
14
+ module Qrack
15
+ class BufferOverflowError < StandardError; end
16
+ class InvalidTypeError < StandardError; end
17
+ end
18
+ end
19
+
9
20
  require 'mocha'
10
21
  require File.expand_path(File.dirname(__FILE__) + '/../lib/beetle')
11
22
 
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: 29
4
+ hash: 27
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 2
9
- - 5
10
- version: 0.2.5
9
+ - 6
10
+ version: 0.2.6
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-08-23 00:00:00 +02:00
21
+ date: 2010-09-08 00:00:00 +02:00
22
22
  default_executable: beetle
23
23
  dependencies:
24
24
  - !ruby/object:Gem::Dependency
@@ -91,7 +91,7 @@ dependencies:
91
91
  requirement: &id005 !ruby/object:Gem::Requirement
92
92
  none: false
93
93
  requirements:
94
- - - ">="
94
+ - - ~>
95
95
  - !ruby/object:Gem::Version
96
96
  hash: 11
97
97
  segments: