smith 0.5.7
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/bin/agency +55 -0
- data/bin/smithctl +102 -0
- data/lib/smith.rb +237 -0
- data/lib/smith/acl_compiler.rb +74 -0
- data/lib/smith/agent.rb +207 -0
- data/lib/smith/agent_cache.rb +40 -0
- data/lib/smith/agent_config.rb +22 -0
- data/lib/smith/agent_monitoring.rb +52 -0
- data/lib/smith/agent_process.rb +181 -0
- data/lib/smith/application/agency.rb +126 -0
- data/lib/smith/bootstrap.rb +153 -0
- data/lib/smith/cache.rb +61 -0
- data/lib/smith/command.rb +128 -0
- data/lib/smith/commands/agency/agents.rb +28 -0
- data/lib/smith/commands/agency/common.rb +18 -0
- data/lib/smith/commands/agency/kill.rb +13 -0
- data/lib/smith/commands/agency/list.rb +65 -0
- data/lib/smith/commands/agency/logger.rb +56 -0
- data/lib/smith/commands/agency/metadata.rb +14 -0
- data/lib/smith/commands/agency/restart.rb +39 -0
- data/lib/smith/commands/agency/start.rb +62 -0
- data/lib/smith/commands/agency/state.rb +14 -0
- data/lib/smith/commands/agency/stop.rb +70 -0
- data/lib/smith/commands/agency/version.rb +23 -0
- data/lib/smith/commands/smithctl/cat.rb +70 -0
- data/lib/smith/commands/smithctl/pop.rb +76 -0
- data/lib/smith/commands/smithctl/rm.rb +36 -0
- data/lib/smith/commands/smithctl/smithctl_version.rb +23 -0
- data/lib/smith/commands/smithctl/top.rb +42 -0
- data/lib/smith/commands/template.rb +9 -0
- data/lib/smith/config.rb +32 -0
- data/lib/smith/logger.rb +91 -0
- data/lib/smith/messaging/acl/agency_command.proto +5 -0
- data/lib/smith/messaging/acl/agent_command.proto +5 -0
- data/lib/smith/messaging/acl/agent_config_request.proto +4 -0
- data/lib/smith/messaging/acl/agent_config_update.proto +5 -0
- data/lib/smith/messaging/acl/agent_keepalive.proto +6 -0
- data/lib/smith/messaging/acl/agent_lifecycle.proto +12 -0
- data/lib/smith/messaging/acl/agent_stats.proto +14 -0
- data/lib/smith/messaging/acl/default.rb +51 -0
- data/lib/smith/messaging/acl/search.proto +9 -0
- data/lib/smith/messaging/amqp_options.rb +55 -0
- data/lib/smith/messaging/endpoint.rb +116 -0
- data/lib/smith/messaging/exceptions.rb +7 -0
- data/lib/smith/messaging/payload.rb +102 -0
- data/lib/smith/messaging/queue_factory.rb +67 -0
- data/lib/smith/messaging/receiver.rb +237 -0
- data/lib/smith/messaging/responder.rb +15 -0
- data/lib/smith/messaging/sender.rb +61 -0
- metadata +239 -0
@@ -0,0 +1,116 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
module Smith
|
3
|
+
module Messaging
|
4
|
+
class Endpoint
|
5
|
+
include Logger
|
6
|
+
|
7
|
+
attr_accessor :denomalized_queue_name, :queue_name
|
8
|
+
|
9
|
+
def initialize(queue_name, options)
|
10
|
+
@denomalized_queue_name = queue_name
|
11
|
+
@queue_name = normalise(queue_name)
|
12
|
+
@message_counts = Hash.new(0)
|
13
|
+
@options = options
|
14
|
+
end
|
15
|
+
|
16
|
+
def ready(&blk)
|
17
|
+
Smith.channel.direct(@queue_name, options.exchange) do |exchange|
|
18
|
+
@exchange = exchange
|
19
|
+
|
20
|
+
exchange.on_return do |basic_return,metadata,payload|
|
21
|
+
logger.error { "#{ACL::Payload.decode(payload.clone, metadata.type)} was returned! Exchange: #{reply_code.exchange}, reply_code = #{basic_return.reply_code}, reply_text = #{basic_return.reply_text}" }
|
22
|
+
logger.error { "Properties: #{metadata.properties}" }
|
23
|
+
end
|
24
|
+
|
25
|
+
logger.verbose { "Creating queue: [queue]:#{denomalized_queue_name} [options]:#{options.queue}" }
|
26
|
+
|
27
|
+
Smith.channel.queue(queue_name, options.queue) do |queue|
|
28
|
+
@queue = queue
|
29
|
+
@options.queue_name = queue_name
|
30
|
+
queue.bind(exchange, :routing_key => queue_name)
|
31
|
+
blk.call(self)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def number_of_messages
|
37
|
+
@queue.status do |num_messages, num_consumers|
|
38
|
+
yield num_messages
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def number_of_consumers
|
43
|
+
@queue.status do |num_messages, num_consumers|
|
44
|
+
yield num_consumers
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# Return the total number of messages sent or received for the named queue.
|
49
|
+
def counter
|
50
|
+
@message_counts[queue_name]
|
51
|
+
end
|
52
|
+
|
53
|
+
def messages?(blk=nil, err=proc {logger.debug { "No messages on #{@denomalized_queue_name}" } })
|
54
|
+
number_of_messages do |n|
|
55
|
+
if n > 0
|
56
|
+
if blk.respond_to? :call
|
57
|
+
blk.call(self)
|
58
|
+
else
|
59
|
+
yield self
|
60
|
+
end
|
61
|
+
else
|
62
|
+
err.call
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def consumers?(blk=nil, err=proc {logger.debug { "Nothing listening on #{@denomalized_queue_name}" } })
|
68
|
+
number_of_consumers do |n|
|
69
|
+
if n > 0
|
70
|
+
if blk.respond_to? :call
|
71
|
+
blk.call(self)
|
72
|
+
else
|
73
|
+
yield self
|
74
|
+
end
|
75
|
+
else
|
76
|
+
if err.respond_to? :call
|
77
|
+
err.call
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def timeout(timeout, blk=nil, &block)
|
84
|
+
cancel_timeout
|
85
|
+
blk ||= block
|
86
|
+
@timeout = EventMachine::Timer.new(timeout, blk)
|
87
|
+
end
|
88
|
+
|
89
|
+
protected
|
90
|
+
|
91
|
+
attr_accessor :exchange, :queue, :options
|
92
|
+
|
93
|
+
def increment_counter(value=1)
|
94
|
+
@message_counts[queue_name] += value
|
95
|
+
end
|
96
|
+
|
97
|
+
def denormalise(name)
|
98
|
+
name.sub(/#{Regexp.escape("#{Smith.config.smith.namespace}.")}/, '')
|
99
|
+
end
|
100
|
+
|
101
|
+
def normalise(name)
|
102
|
+
"#{Smith.config.smith.namespace}.#{name}"
|
103
|
+
end
|
104
|
+
|
105
|
+
def cancel_timeout
|
106
|
+
@timeout.cancel if @timeout
|
107
|
+
end
|
108
|
+
|
109
|
+
private
|
110
|
+
|
111
|
+
def random(prefix = '', suffix = '')
|
112
|
+
"#{prefix}#{SecureRandom.hex(8)}#{suffix}"
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
@@ -0,0 +1,102 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
module Smith
|
3
|
+
module ACL
|
4
|
+
|
5
|
+
module ACLInstanceMethods
|
6
|
+
def inspect
|
7
|
+
"<#{self.class.to_s}> -> #{self.to_hash}"
|
8
|
+
end
|
9
|
+
|
10
|
+
def as_json
|
11
|
+
Yajl.dump(self.to_hash)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
module ClassMethods
|
16
|
+
def content_class(e)
|
17
|
+
@@acl_classes ||= {:default => Default}
|
18
|
+
|
19
|
+
e = e.to_sym
|
20
|
+
|
21
|
+
if @@acl_classes.include?(e)
|
22
|
+
@@acl_classes[e]
|
23
|
+
else
|
24
|
+
class_name = Extlib::Inflection.camelize(e)
|
25
|
+
if ACL.constants.include?(class_name)
|
26
|
+
logger.error { "Shouldn't get here." }
|
27
|
+
else
|
28
|
+
logger.debug { "#{class_name} Loaded from #{e}.pb.rb" }
|
29
|
+
ACL.const_get(class_name).tap do |clazz|
|
30
|
+
# Override the inspect method
|
31
|
+
@@acl_classes[e] = clazz.send(:include, ACLInstanceMethods)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
class Payload
|
39
|
+
include Logger
|
40
|
+
|
41
|
+
include ClassMethods
|
42
|
+
extend ClassMethods
|
43
|
+
|
44
|
+
# content can be an existing ACL class.
|
45
|
+
def initialize(type=:default, opts={})
|
46
|
+
if opts[:from]
|
47
|
+
@type = opts[:from].class.to_s.split(/::/).last.snake_case
|
48
|
+
@content = opts[:from]
|
49
|
+
else
|
50
|
+
@type = type
|
51
|
+
@clazz = content_class(type)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
# Add content to the content or get the content from a payload
|
56
|
+
def content(*content, &block)
|
57
|
+
if content.empty?
|
58
|
+
if block.nil?
|
59
|
+
return @content
|
60
|
+
else
|
61
|
+
@content = @clazz.new
|
62
|
+
block.call(@content)
|
63
|
+
end
|
64
|
+
else
|
65
|
+
@content = @clazz.new(content.first)
|
66
|
+
end
|
67
|
+
self
|
68
|
+
end
|
69
|
+
|
70
|
+
# The type of content.
|
71
|
+
def type
|
72
|
+
@type.to_s
|
73
|
+
end
|
74
|
+
|
75
|
+
# Returns a hash of the payload.
|
76
|
+
def to_hash
|
77
|
+
@content.to_hash
|
78
|
+
end
|
79
|
+
|
80
|
+
# Encode the content, returning the encoded data.
|
81
|
+
def encode
|
82
|
+
@content.serialize_to_string
|
83
|
+
end
|
84
|
+
|
85
|
+
# Returns true if the payload has all its required fields set.
|
86
|
+
def initialized?
|
87
|
+
raise RuntimeError, "You probably forgot to call #content or give the :from option when instantiating the object." if @content.nil?
|
88
|
+
@content.initialized?
|
89
|
+
end
|
90
|
+
|
91
|
+
# Convert the payload to a pretty string.
|
92
|
+
def to_s
|
93
|
+
@content.inspect
|
94
|
+
end
|
95
|
+
|
96
|
+
# Decode the content using the specified decoder.
|
97
|
+
def self.decode(payload, decoder=:default)
|
98
|
+
content_class(decoder).new.parse_from_string(payload)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
module Smith
|
4
|
+
class QueueFactory
|
5
|
+
def initialize
|
6
|
+
@cache = Cache.new
|
7
|
+
end
|
8
|
+
|
9
|
+
def create(queue_name, type, opts={})
|
10
|
+
key = "#{type}:#{queue_name}"
|
11
|
+
if @cache[key]
|
12
|
+
@cache[key]
|
13
|
+
else
|
14
|
+
update_cache(key, opts) do |o|
|
15
|
+
case type
|
16
|
+
when :receiver
|
17
|
+
Messaging::Receiver.new(queue_name, o)
|
18
|
+
when :sender
|
19
|
+
Messaging::Sender.new(queue_name, o)
|
20
|
+
else
|
21
|
+
raise ArgumentError, "unknown queue type"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
# Simple wrapper around create that runs Endpoint#ready and calls the block
|
28
|
+
def queue(queue_name, type, opts={}, &blk)
|
29
|
+
create(queue_name, type, opts).ready { |queue| blk.call(queue) }
|
30
|
+
end
|
31
|
+
|
32
|
+
# Convenience method that returns a Sender object. #ready is called by
|
33
|
+
# this method.
|
34
|
+
def sender(queue_name, opts={}, &blk)
|
35
|
+
queue(queue_name, :sender, opts) { |sender| blk.call(sender) }
|
36
|
+
end
|
37
|
+
|
38
|
+
# Convenience method that returns a Receiver object. #ready is called by
|
39
|
+
# this method.
|
40
|
+
def receiver(queue_name, opts={}, &blk)
|
41
|
+
queue(queue_name, :receiver, opts) { |receiver| blk.call(receiver) }
|
42
|
+
end
|
43
|
+
|
44
|
+
# Passes each queue to the supplied block.
|
45
|
+
def each_queue
|
46
|
+
@cache.each do |queue|
|
47
|
+
yield queue
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
# Returns all queues as a hash, with the queue name being the key.
|
52
|
+
def queues
|
53
|
+
@cache
|
54
|
+
end
|
55
|
+
|
56
|
+
private
|
57
|
+
|
58
|
+
def update_cache(queue_name, opts, &blk)
|
59
|
+
dont_cache = (opts.has_key?(:dont_cache)) ? opts.delete(:dont_cache) : false
|
60
|
+
if dont_cache
|
61
|
+
blk.call(opts)
|
62
|
+
else
|
63
|
+
@cache.update(queue_name, blk.call(opts))
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,237 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
module Smith
|
3
|
+
module Messaging
|
4
|
+
class Receiver < Endpoint
|
5
|
+
|
6
|
+
include Logger
|
7
|
+
|
8
|
+
attr_accessor :options
|
9
|
+
|
10
|
+
def initialize(queue_name, opts={})
|
11
|
+
@auto_ack = (opts.has_key?(:auto_ack)) ? opts.delete(:auto_ack) : true
|
12
|
+
@threading = (opts.has_key?(:threading)) ? opts.delete(:threading) : false
|
13
|
+
@payload_type = (opts.key?(:type)) ? [opts.delete(:type)].flatten : []
|
14
|
+
|
15
|
+
super(queue_name, AmqpOptions.new(opts))
|
16
|
+
end
|
17
|
+
|
18
|
+
# Subscribes to a queue and passes the headers and payload into the
|
19
|
+
# block. +subscribe+ will automatically acknowledge the message unless
|
20
|
+
# the options sets :ack to false.
|
21
|
+
def subscribe(&block)
|
22
|
+
if !@queue.subscribed?
|
23
|
+
opts = options.subscribe
|
24
|
+
logger.verbose { "Subscribing to: [queue]:#{denomalized_queue_name} [options]:#{opts}" }
|
25
|
+
queue.subscribe(opts) do |metadata,payload|
|
26
|
+
if payload
|
27
|
+
if @payload_type.empty? || @payload_type.include?(metadata.type.to_sym)
|
28
|
+
thread(Reply.new(self, metadata, payload)) do |reply|
|
29
|
+
increment_counter
|
30
|
+
block.call(reply)
|
31
|
+
end
|
32
|
+
else
|
33
|
+
raise IncorrectPayloadType, "This queue can only accept the following payload types: #{@payload_type.to_a.to_s}"
|
34
|
+
end
|
35
|
+
else
|
36
|
+
logger.verbose { "Received null message on: #{denomalized_queue_name} [options]:#{opts}" }
|
37
|
+
end
|
38
|
+
end
|
39
|
+
else
|
40
|
+
logger.error { "Queue is already subscribed too. Not listening on: #{denormalise_queue_name}" }
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
# pops a message off the queue and passes the headers and payload
|
45
|
+
# into the block. +pop+ will automatically acknowledge the message
|
46
|
+
# unless the options sets :ack to false.
|
47
|
+
def pop(&block)
|
48
|
+
opts = options.pop
|
49
|
+
@queue.pop(opts) do |metadata, payload|
|
50
|
+
thread(Reply.new(self, metadata, (payload.nil?) ? nil : payload)) do |reply|
|
51
|
+
block.call(reply)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def threading?
|
57
|
+
@threading
|
58
|
+
end
|
59
|
+
|
60
|
+
def auto_ack?
|
61
|
+
@auto_ack
|
62
|
+
end
|
63
|
+
|
64
|
+
private
|
65
|
+
|
66
|
+
# Controls whether to use threads or not. Given that I need to ack in the
|
67
|
+
# thread (TODO check this) I also need to pass in a flag to say whether
|
68
|
+
# to auto ack or not. This is because it can get called twice and we don't
|
69
|
+
# want to ack more than once or an error will be thrown.
|
70
|
+
def thread(reply, &block)
|
71
|
+
logger.verbose { "Threads: [queue]: #{denomalized_queue_name}: #{threading?}" }
|
72
|
+
logger.verbose { "auto_ack: [queue]: #{denomalized_queue_name}: #{auto_ack?}" }
|
73
|
+
if threading?
|
74
|
+
EM.defer do
|
75
|
+
block.call(reply)
|
76
|
+
reply.ack if auto_ack?
|
77
|
+
end
|
78
|
+
else
|
79
|
+
block.call(reply)
|
80
|
+
reply.ack if auto_ack?
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
# I'm not terribly happy about this class. It's publicaly visable and it contains
|
85
|
+
# some gross violations of Ruby's protection mechanism. I suspect it's an indication
|
86
|
+
# of a more fundamental design flaw. I will leave it as is for the time being but
|
87
|
+
# this really needs to be reviewed. FIXME review this class.
|
88
|
+
class Reply
|
89
|
+
|
90
|
+
include Logger
|
91
|
+
|
92
|
+
attr_reader :metadata, :payload, :time
|
93
|
+
|
94
|
+
def initialize(receiver, metadata, undecoded_payload)
|
95
|
+
@undecoded_payload = undecoded_payload
|
96
|
+
@receiver = receiver
|
97
|
+
@exchange = receiver.send(:exchange)
|
98
|
+
@metadata = metadata
|
99
|
+
@time = Time.now
|
100
|
+
|
101
|
+
if undecoded_payload
|
102
|
+
@payload = ACL::Payload.decode(undecoded_payload, metadata.type)
|
103
|
+
logger.verbose { "Received content on: [queue]: #{denomalized_queue_name}." }
|
104
|
+
logger.verbose { "Payload content: [queue]: #{denomalized_queue_name}, [metadata type]: #{metadata.type}, [message]: #{payload.inspect}" }
|
105
|
+
else
|
106
|
+
logger.verbose { "Received nil content on: [queue]: #{denomalized_queue_name}." }
|
107
|
+
@payload = nil
|
108
|
+
@nil_message = true
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
# Reply to a message. If reply_to header is not set a error will be logged
|
113
|
+
def reply(&block)
|
114
|
+
responder = Responder.new
|
115
|
+
if reply_to
|
116
|
+
responder.callback do |return_value|
|
117
|
+
Sender.new(@metadata.reply_to, :auto_delete => true).ready do |sender|
|
118
|
+
logger.verbose { "Replying on: #{@metadata.reply_to}" } if logger.level == 0
|
119
|
+
sender.publish(ACL::Payload.new(:default).content(return_value), sender.options.publish(:correlation_id => @metadata.message_id))
|
120
|
+
end
|
121
|
+
end
|
122
|
+
else
|
123
|
+
# Null responder. If a call on the responder is made log a warning. Something is wrong.
|
124
|
+
responder.callback do |return_value|
|
125
|
+
logger.error { "You are responding to a message that has no reply_to on queue: #{denomalized_queue_name}." }
|
126
|
+
logger.verbose { "Queue options: #{@metadata.exchange}." }
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
block.call(responder)
|
131
|
+
end
|
132
|
+
|
133
|
+
# acknowledge the message.
|
134
|
+
def ack(multiple=false)
|
135
|
+
@metadata.ack(multiple) unless @nil_message
|
136
|
+
end
|
137
|
+
|
138
|
+
# reject the message. Optionally requeuing it.
|
139
|
+
def reject(opts={})
|
140
|
+
@metadata.reject(opts) unless @nil_message
|
141
|
+
end
|
142
|
+
|
143
|
+
def reply_to
|
144
|
+
@metadata.reply_to
|
145
|
+
end
|
146
|
+
|
147
|
+
# Republish the message to the end of the same queue. This is useful
|
148
|
+
# for when the agent encounters an error and needs to requeue the message.
|
149
|
+
def requeue(delay, count, strategy, &block)
|
150
|
+
requeue_with_strategy(delay, count, strategy) do
|
151
|
+
|
152
|
+
# Sort out the options. Receiver#queue is private hence the send. I know, I know.
|
153
|
+
opts = @receiver.send(:queue).opts.tap do |o|
|
154
|
+
o.delete(:queue)
|
155
|
+
o.delete(:exchange)
|
156
|
+
|
157
|
+
o[:headers] = increment_requeue_count(metadata.headers)
|
158
|
+
o[:routing_key] = normalised_queue_name
|
159
|
+
o[:type] = metadata.type
|
160
|
+
end
|
161
|
+
|
162
|
+
logger.verbose { "Requeuing to: #{denomalized_queue_name}. [options]: #{opts}" }
|
163
|
+
logger.verbose { "Requeuing to: #{denomalized_queue_name}. [message]: #{ACL::Payload.decode(@undecoded_payload, metadata.type)}" }
|
164
|
+
|
165
|
+
@receiver.send(:exchange).publish(@undecoded_payload, opts)
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
def on_requeue_error(&block)
|
170
|
+
@on_requeue_error = block
|
171
|
+
end
|
172
|
+
|
173
|
+
def on_requeue(&block)
|
174
|
+
@on_requeue = block
|
175
|
+
end
|
176
|
+
|
177
|
+
def current_requeue_number
|
178
|
+
metadata.headers['requeue'] || 0
|
179
|
+
end
|
180
|
+
|
181
|
+
# The payload type. This returns the protocol buffers class name as a string.
|
182
|
+
def payload_type
|
183
|
+
@metadata.type
|
184
|
+
end
|
185
|
+
|
186
|
+
def queue_name
|
187
|
+
denomalized_queue_name
|
188
|
+
end
|
189
|
+
|
190
|
+
private
|
191
|
+
|
192
|
+
def requeue_with_strategy(delay, count, strategy, &block)
|
193
|
+
if current_requeue_number < count
|
194
|
+
method = "#{strategy}_strategy".to_sym
|
195
|
+
if respond_to?(method, true)
|
196
|
+
cummulative_delay = send(method, delay)
|
197
|
+
@on_requeue.call(cummulative_delay, current_requeue_number + 1)
|
198
|
+
EM.add_timer(cummulative_delay) do
|
199
|
+
block.call(cummulative_delay, current_requeue_number + 1)
|
200
|
+
end
|
201
|
+
else
|
202
|
+
raise RuntimeError, "Unknown requeue strategy. #{method}"
|
203
|
+
end
|
204
|
+
else
|
205
|
+
@on_requeue_error.call(cummulative_delay, current_requeue_number)
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
def exponential_no_initial_delay_strategy(delay)
|
210
|
+
delay * (2 ** current_requeue_number - 1)
|
211
|
+
end
|
212
|
+
|
213
|
+
def exponential_strategy(delay)
|
214
|
+
delay * (2 ** current_requeue_number)
|
215
|
+
end
|
216
|
+
|
217
|
+
def linear_strategy(delay)
|
218
|
+
delay * (current_requeue_number + 1)
|
219
|
+
end
|
220
|
+
|
221
|
+
def denomalized_queue_name
|
222
|
+
@receiver.denomalized_queue_name
|
223
|
+
end
|
224
|
+
|
225
|
+
def normalised_queue_name
|
226
|
+
@receiver.queue_name
|
227
|
+
end
|
228
|
+
|
229
|
+
def increment_requeue_count(headers)
|
230
|
+
headers.tap do |m|
|
231
|
+
m['requeue'] = (m['requeue']) ? m['requeue'] + 1 : 1
|
232
|
+
end
|
233
|
+
end
|
234
|
+
end
|
235
|
+
end
|
236
|
+
end
|
237
|
+
end
|