activemessaging-kestrel-adapter 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,9 @@
1
+ == 0.0.3 / 2011-02-05
2
+ * Introduce a 0.1 second sleep in #receive if no subscribed queues have a message
3
+ to avoid spin loops in the ActiveMessaging Gateway. This is a bug, IMHO, in
4
+ ActiveMessaging.
5
+ * Fix bugs in receive loop to match new ActiveMessaging 0.7.1 API
6
+
1
7
  == 0.0.2 / 2011-02-03
2
8
  * Implement simple retry in the face of receive errors to avoid log spew
3
9
  by the ActiveMessaging Gateway as it retries over and over. Extensible
data/README.md CHANGED
@@ -19,6 +19,7 @@ Examples
19
19
  # development:
20
20
  # adapter: kestrel
21
21
  # servers: localhost:22133
22
+ # empty_queues_delay: 0.1
22
23
  # retry_policy:
23
24
  # strategy: SimpleRetry
24
25
  # config:
data/Rakefile CHANGED
@@ -16,7 +16,7 @@ Bones {
16
16
  readme_file 'README.md'
17
17
 
18
18
  depend_on 'memcache-client'
19
- depend_on 'activemessaging'
19
+ depend_on 'activemessaging', '>= 0.7.1'
20
20
 
21
21
  rdoc.include << 'README.md'
22
22
 
@@ -7,7 +7,11 @@ module ActiveMessaging
7
7
  # kestrel message queue server.
8
8
  module Kestrel
9
9
  # Simple struct for wrapping received messages
10
- Message = Struct.new(:headers, :body, :command)
10
+ Message = Struct.new(:headers, :body, :destination) do
11
+ def matches_subscription?(subscription)
12
+ destination.to_s == subscription.destination.value.to_s
13
+ end
14
+ end
11
15
 
12
16
  # Resolve the provided string into a class object
13
17
  def to_class(class_name, initial_scope = Kernel)
@@ -49,16 +53,20 @@ module ActiveMessaging
49
53
  class Connection < ActiveMessaging::Adapters::BaseConnection
50
54
  include ActiveMessaging::Adapter
51
55
  register :kestrel
52
- attr_accessor :reliable
53
56
  # Reconnect on error
54
57
  attr_accessor :retry_policy
58
+ # Logging
59
+ attr_accessor :logger
55
60
 
56
- def initialize(cfg)
61
+ # Create a new Kestrel adapter using the provided config
62
+ def initialize(cfg = {})
57
63
  cfg = symbolize_keys(cfg)
64
+ # TODO: Decide on fallback logging ...
65
+ @logger = cfg.delete(:logger) || (defined?(::Rails) && ::Rails.logger ? ::Rails.logger : nil) || default_logger
58
66
  @retry_policy = cfg.delete(:retry_policy) || {:strategy => SimpleRetry, :config => {:tries => 1, :delay => 5}}
67
+ @empty_queues_delay = cfg.delete(:empty_queues_delay) || 0.1
59
68
  if @retry_policy[:strategy].is_a?(String)
60
- # TODO: when getting a retry policy strategy from the config file, it will be a string. Convert it to a class
61
- # using the Kestrel module as a context, then Kernel.
69
+ # Convert strategy from string to class
62
70
  @retry_policy[:strategy] = Kestrel.const_get(retry_policy[:strategy]) rescue Kestrel.to_class(@retry_policy[:strategy])
63
71
  end
64
72
  @config = cfg
@@ -69,6 +77,7 @@ module ActiveMessaging
69
77
 
70
78
  # Connect to the kestrel server using a Memcached client
71
79
  def connect
80
+ logger.debug("Creating connection to Kestrel using config #{@config.inspect}") if logger.level <= Logger::DEBUG
72
81
  @kestrel = MemCache.new(@config)
73
82
  @kestrel.servers = @config[:servers]
74
83
  end
@@ -105,25 +114,36 @@ module ActiveMessaging
105
114
  # Gets a message from any subscribed destination and returns it as a
106
115
  # ActiveMessaging::Adaptors::Kestrel::Message object
107
116
  def receive
108
- return nil if @subscriptions.size < 1
109
117
 
110
- # instantiate a class for doing the retries
111
- retrier = @retry_policy[:strategy].new
118
+ if @subscriptions.size > 0
119
+ # instantiate a class for doing the retries
120
+ retrier = @retry_policy[:strategy].new
112
121
 
113
- retrier.do_work(@retry_policy[:config]) do
114
- queues_to_check = @subscriptions.size > 1 ? @subscriptions.keys.sort_by{rand} : @subscriptions.keys
115
- queues_to_check.each do |queue|
116
- if item = @kestrel.get(normalize(queue))
117
- # TODO: ActiveMessaging ought to provide a way to do messaging
118
- # without having to wrap the messages in another object
119
- return Message.new({'destination' => queue}, item, 'MESSAGE')
122
+ retrier.do_work(@retry_policy[:config]) do
123
+ queues_to_check = @subscriptions.size > 1 ? @subscriptions.keys.sort_by{rand} : @subscriptions.keys
124
+ queues_to_check.each do |queue|
125
+ if item = @kestrel.get(normalize(queue))
126
+ # TODO: ActiveMessaging ought to provide a way to do messaging
127
+ # without having to wrap the messages in another object
128
+ #logger.debug("Got message from queue #{queue}: #{item}") if logger.level <= Logger::DEBUG
129
+ return Message.new({'destination' => queue}, item, queue)
130
+ end
120
131
  end
121
132
  end
122
133
  end
134
+ # Sleep a little to avoid a spin loop (ActiveMessaging Gateway ought to do this)
135
+ sleep(@empty_queues_delay)
123
136
  return nil
124
137
  end
125
138
 
126
139
  private
140
+ def default_logger
141
+ # Create a logger on STDOUT at debug level
142
+ logger = Logger.new(STDOUT)
143
+ logger.level = Logger::DEBUG
144
+ logger
145
+ end
146
+
127
147
  def normalize(name)
128
148
  # Kestrel doesn't like '/' chars in queue names, so get rid of them
129
149
  # (and memoize the calculation)
@@ -1,4 +1,5 @@
1
1
  require 'test/unit'
2
+ require 'active_support' # Annoying that I have to do this for the ActiveMessaging framework ...
2
3
  require 'activemessaging'
3
4
  require 'activemessaging-kestrel-adapter'
4
5
 
@@ -1 +1 @@
1
- 0.0.2
1
+ 0.0.3
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activemessaging-kestrel-adapter
3
3
  version: !ruby/object:Gem::Version
4
- hash: 27
4
+ hash: 25
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 0
9
- - 2
10
- version: 0.0.2
9
+ - 3
10
+ version: 0.0.3
11
11
  platform: ruby
12
12
  authors:
13
13
  - Douglas A. Seifert
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-02-04 00:00:00 -08:00
18
+ date: 2011-02-06 00:00:00 -08:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -26,12 +26,12 @@ dependencies:
26
26
  requirements:
27
27
  - - "="
28
28
  - !ruby/object:Gem::Version
29
- hash: 61
29
+ hash: 49
30
30
  segments:
31
31
  - 1
32
32
  - 8
33
- - 5
34
- version: 1.8.5
33
+ - 3
34
+ version: 1.8.3
35
35
  type: :runtime
36
36
  version_requirements: *id001
37
37
  - !ruby/object:Gem::Dependency
@@ -40,7 +40,7 @@ dependencies:
40
40
  requirement: &id002 !ruby/object:Gem::Requirement
41
41
  none: false
42
42
  requirements:
43
- - - "="
43
+ - - ">="
44
44
  - !ruby/object:Gem::Version
45
45
  hash: 1
46
46
  segments: