brown 1.1.2 → 2.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +4 -1
- data/.yardopts +1 -0
- data/LICENCE +674 -0
- data/README.md +321 -0
- data/bin/brown +72 -12
- data/brown.gemspec +31 -21
- data/lib/.gitkeep +0 -0
- data/lib/brown.rb +17 -3
- data/lib/brown/agent.rb +417 -21
- data/lib/brown/agent/amqp_message.rb +42 -0
- data/lib/brown/agent/amqp_message_mock.rb +28 -0
- data/lib/brown/agent/amqp_publisher.rb +169 -0
- data/lib/brown/agent/memo.rb +64 -0
- data/lib/brown/agent/stimulus.rb +143 -0
- data/lib/brown/test.rb +152 -0
- metadata +88 -64
- data/Gemfile +0 -3
- data/Rakefile +0 -19
- data/lib/brown/acl_loader.rb +0 -57
- data/lib/brown/acl_lookup.rb +0 -52
- data/lib/brown/amqp_errors.rb +0 -148
- data/lib/brown/logger.rb +0 -51
- data/lib/brown/message.rb +0 -73
- data/lib/brown/module_methods.rb +0 -134
- data/lib/brown/queue_definition.rb +0 -32
- data/lib/brown/queue_factory.rb +0 -33
- data/lib/brown/receiver.rb +0 -143
- data/lib/brown/sender.rb +0 -92
- data/lib/brown/util.rb +0 -58
- data/lib/smith.rb +0 -4
@@ -1,32 +0,0 @@
|
|
1
|
-
# -*- encoding: utf-8 -*-
|
2
|
-
|
3
|
-
class Brown::QueueDefinition
|
4
|
-
attr_reader :options
|
5
|
-
|
6
|
-
def initialize(name, options)
|
7
|
-
@normalised_queue = "smith.#{name}"
|
8
|
-
@denormalised_queue = "#{name}"
|
9
|
-
@options = options
|
10
|
-
end
|
11
|
-
|
12
|
-
def denormalise
|
13
|
-
@denormalised_queue
|
14
|
-
end
|
15
|
-
|
16
|
-
def name
|
17
|
-
@normalised_queue
|
18
|
-
end
|
19
|
-
|
20
|
-
def normalise
|
21
|
-
@normalised_queue
|
22
|
-
end
|
23
|
-
|
24
|
-
# to_a is defined to make the splat operator work.
|
25
|
-
def to_a
|
26
|
-
return @normalised_queue, @options
|
27
|
-
end
|
28
|
-
|
29
|
-
def to_s
|
30
|
-
"<#{self.class}: #{@denormalised_queue}, #{@options.inspect}>"
|
31
|
-
end
|
32
|
-
end
|
data/lib/brown/queue_factory.rb
DELETED
@@ -1,33 +0,0 @@
|
|
1
|
-
# -*- encoding: utf-8 -*-
|
2
|
-
|
3
|
-
class Brown::QueueFactory
|
4
|
-
def initialize
|
5
|
-
@cache = {}
|
6
|
-
end
|
7
|
-
|
8
|
-
# Convenience method that returns a Sender object.
|
9
|
-
def sender(queue_name, opts={}, &blk)
|
10
|
-
k = "sender:#{queue_name}"
|
11
|
-
@cache[k] ||= Brown::Sender.new(queue_name, opts)
|
12
|
-
blk.call(@cache[k])
|
13
|
-
end
|
14
|
-
|
15
|
-
# Convenience method that returns a Receiver object.
|
16
|
-
def receiver(queue_name, opts={}, &blk)
|
17
|
-
k = "receiver:#{queue_name}"
|
18
|
-
@cache[k] ||= Brown::Receiver.new(queue_name, opts)
|
19
|
-
blk.call(@cache[k])
|
20
|
-
end
|
21
|
-
|
22
|
-
# Passes each queue to the supplied block.
|
23
|
-
def each_queue
|
24
|
-
@cache.values.each do |queue|
|
25
|
-
yield queue if block_given?
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
# Returns all queues as a hash, with the queue name being the key.
|
30
|
-
def queues
|
31
|
-
@cache
|
32
|
-
end
|
33
|
-
end
|
data/lib/brown/receiver.rb
DELETED
@@ -1,143 +0,0 @@
|
|
1
|
-
# -*- encoding: utf-8 -*-
|
2
|
-
|
3
|
-
require 'brown/logger'
|
4
|
-
require 'brown/util'
|
5
|
-
|
6
|
-
class Brown::Receiver
|
7
|
-
include Brown::Logger
|
8
|
-
include Brown::Util
|
9
|
-
|
10
|
-
def initialize(queue_def, opts={}, &blk)
|
11
|
-
@queue_def = queue_def.is_a?(Brown::QueueDefinition) ? queue_def : Brown::QueueDefinition.new(queue_def, opts)
|
12
|
-
|
13
|
-
@acl_type_cache = Brown::ACLLookup
|
14
|
-
|
15
|
-
@options = opts
|
16
|
-
|
17
|
-
@requeue_options = {}
|
18
|
-
@requeue_queue = Brown::Sender.new(@queue_def, opts)
|
19
|
-
|
20
|
-
@payload_type = Array(option_or_default(@queue_def.options, :type, []))
|
21
|
-
|
22
|
-
prefetch = option_or_default(@queue_def.options, :prefetch, 1)
|
23
|
-
|
24
|
-
@channel_completion = EM::Completion.new
|
25
|
-
@queue_completion = EM::Completion.new
|
26
|
-
|
27
|
-
open_channel(:prefetch => prefetch) do |channel|
|
28
|
-
logger.debug { "channel open for receiver on #{@queue_def.denormalise}" }
|
29
|
-
channel.on_error do |ch, close|
|
30
|
-
logger.fatal { "Channel error: #{close.inspect}" }
|
31
|
-
end
|
32
|
-
|
33
|
-
channel.queue(@queue_def.normalise) do |queue|
|
34
|
-
logger.debug { "Registered queue #{@queue_def.denormalise} on channel" }
|
35
|
-
@queue_completion.succeed(queue)
|
36
|
-
end
|
37
|
-
|
38
|
-
@channel_completion.succeed(channel)
|
39
|
-
end
|
40
|
-
|
41
|
-
blk.call(self) if blk
|
42
|
-
end
|
43
|
-
|
44
|
-
def ack(multiple=false)
|
45
|
-
@channel_completion.completion {|channel| channel.ack(multiple) }
|
46
|
-
end
|
47
|
-
|
48
|
-
# Subscribes to a queue and passes the headers and payload into the
|
49
|
-
# block. +subscribe+ will automatically acknowledge the message unless
|
50
|
-
# the options sets :ack to false.
|
51
|
-
def subscribe(opts = {}, &blk)
|
52
|
-
@queue_completion.completion do |queue|
|
53
|
-
logger.debug { "Subscribing to: [queue]:#{@queue_def.denormalise} [options]:#{@queue_def.options}" }
|
54
|
-
queue.subscribe(opts.merge(:ack => true)) do |metadata,payload|
|
55
|
-
logger.debug { "Received a message on #{@queue_def.denormalise}: #{metadata.to_hash.inspect}" }
|
56
|
-
if payload
|
57
|
-
on_message(metadata, payload, &blk)
|
58
|
-
else
|
59
|
-
logger.debug { "Received null message on: #{@queue_def.denormalise} [options]:#{@queue_def.options}" }
|
60
|
-
end
|
61
|
-
end
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
def unsubscribe(&blk)
|
66
|
-
@queue_completion.completion do |queue|
|
67
|
-
queue.unsubscribe(&blk)
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
|
-
def requeue_parameters(opts)
|
72
|
-
@requeue_options.merge!(opts)
|
73
|
-
end
|
74
|
-
|
75
|
-
def on_requeue(&blk)
|
76
|
-
@requeue_options[:on_requeue] = blk
|
77
|
-
end
|
78
|
-
|
79
|
-
def on_requeue_limit(&blk)
|
80
|
-
@requeue_options[:on_requeue_limit] = blk
|
81
|
-
end
|
82
|
-
|
83
|
-
# pops a message off the queue and passes the headers and payload
|
84
|
-
# into the block. +pop+ will automatically acknowledge the message
|
85
|
-
# unless the options sets :ack to false.
|
86
|
-
def pop(&blk)
|
87
|
-
@queue_completion.completion do |queue|
|
88
|
-
queue.pop({}) do |metadata, payload|
|
89
|
-
if payload
|
90
|
-
on_message(metadata, payload, &blk)
|
91
|
-
else
|
92
|
-
blk.call(nil,nil)
|
93
|
-
end
|
94
|
-
end
|
95
|
-
end
|
96
|
-
end
|
97
|
-
|
98
|
-
# Define a channel error handler.
|
99
|
-
def on_error(chain=false, &blk)
|
100
|
-
# TODO Check that this chains callbacks
|
101
|
-
@channel_completion.completion do |channel|
|
102
|
-
channel.on_error(&blk)
|
103
|
-
end
|
104
|
-
end
|
105
|
-
|
106
|
-
def queue_name
|
107
|
-
@queue_def.denormalise
|
108
|
-
end
|
109
|
-
|
110
|
-
def delete(&blk)
|
111
|
-
@queue_completion.completion do |queue|
|
112
|
-
@channel_completion.completion do |channel|
|
113
|
-
queue.unbind(exchange) do
|
114
|
-
queue.delete do
|
115
|
-
exchange.delete do
|
116
|
-
channel.close(&blk)
|
117
|
-
end
|
118
|
-
end
|
119
|
-
end
|
120
|
-
end
|
121
|
-
end
|
122
|
-
end
|
123
|
-
|
124
|
-
def status(&blk)
|
125
|
-
@queue_completion.completion do |queue|
|
126
|
-
queue.status do |num_messages, num_consumers|
|
127
|
-
blk.call(num_messages, num_consumers)
|
128
|
-
end
|
129
|
-
end
|
130
|
-
end
|
131
|
-
|
132
|
-
private
|
133
|
-
|
134
|
-
def on_message(metadata, payload, &blk)
|
135
|
-
if @payload_type.empty? || @payload_type.include?(@acl_type_cache.get_by_hash(metadata.type))
|
136
|
-
Brown::Message.new(payload, metadata, @requeue_queue, @requeue_options, @options, &blk)
|
137
|
-
else
|
138
|
-
allowable_acls = @payload_type.join(", ")
|
139
|
-
received_acl = @acl_type_cache.get_by_hash(metadata.type)
|
140
|
-
raise ACL::IncorrectTypeError, "Received ACL: #{received_acl} on queue: #{@queue_def.denormalise}. This queue can only accept the following ACLs: #{allowable_acls}"
|
141
|
-
end
|
142
|
-
end
|
143
|
-
end
|
data/lib/brown/sender.rb
DELETED
@@ -1,92 +0,0 @@
|
|
1
|
-
# -*- encoding: utf-8 -*-
|
2
|
-
|
3
|
-
require 'brown/logger'
|
4
|
-
require 'brown/util'
|
5
|
-
|
6
|
-
class Brown::Sender
|
7
|
-
include Brown::Logger
|
8
|
-
include Brown::Util
|
9
|
-
|
10
|
-
attr_reader :name
|
11
|
-
|
12
|
-
def initialize(queue_def, opts={})
|
13
|
-
@queue_def = queue_def.is_a?(Brown::QueueDefinition) ? queue_def : Brown::QueueDefinition.new(queue_def, opts)
|
14
|
-
@name = @queue_def.denormalise
|
15
|
-
|
16
|
-
@reply_container = {}
|
17
|
-
|
18
|
-
@message_count = 0
|
19
|
-
|
20
|
-
@channel_completion = EM::Completion.new
|
21
|
-
|
22
|
-
open_channel do |channel|
|
23
|
-
logger.debug { "Opening a channel for sending" }
|
24
|
-
@channel_completion.succeed(channel)
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
def publish(payload, opts={}, &blk)
|
29
|
-
logger.debug { "Publishing to: [queue]: #{@queue_def.denormalise}. [options]: #{opts}" }
|
30
|
-
logger.debug { "ACL content: [queue]: #{@queue_def.denormalise}, [metadata type]: #{payload.class}, [message]: #{payload.inspect}" }
|
31
|
-
|
32
|
-
increment_counter
|
33
|
-
|
34
|
-
type = Brown::ACLLookup.get_by_type(payload.class)
|
35
|
-
|
36
|
-
@channel_completion.completion do |channel|
|
37
|
-
logger.debug { "Publishing #{payload.inspect} to queue #{@queue_def.denormalise}" }
|
38
|
-
AMQP::Exchange.default(channel).publish(payload.to_s, opts.merge(:type => type, :routing_key => @queue_def.normalise), &blk)
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
def delete(&blk)
|
43
|
-
queue.delete do
|
44
|
-
@channel_completion.completion do |channel|
|
45
|
-
channel.close(&blk)
|
46
|
-
end
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
=begin
|
51
|
-
def status(&blk)
|
52
|
-
@queue_completion.completion do |queue|
|
53
|
-
queue.status do |num_messages, num_consumers|
|
54
|
-
blk.call(num_messages, num_consumers) if blk
|
55
|
-
end
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
def message_count(&blk)
|
60
|
-
status do |messages|
|
61
|
-
blk.call(messages) if blk
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
def consumer_count(&blk)
|
66
|
-
status do |_, consumers|
|
67
|
-
blk.call(consumers) if blk
|
68
|
-
end
|
69
|
-
end
|
70
|
-
=end
|
71
|
-
|
72
|
-
def counter
|
73
|
-
@message_count
|
74
|
-
end
|
75
|
-
|
76
|
-
# Define a channel error handler.
|
77
|
-
def on_error(chain=false, &blk)
|
78
|
-
@channel_completion.completion do |channel|
|
79
|
-
channel.on_error(&blk)
|
80
|
-
end
|
81
|
-
end
|
82
|
-
|
83
|
-
def queue_name
|
84
|
-
@queue_def.denormalise
|
85
|
-
end
|
86
|
-
|
87
|
-
private
|
88
|
-
|
89
|
-
def increment_counter(value=1)
|
90
|
-
@message_count += value
|
91
|
-
end
|
92
|
-
end
|
data/lib/brown/util.rb
DELETED
@@ -1,58 +0,0 @@
|
|
1
|
-
# -*- encoding: utf-8 -*-
|
2
|
-
|
3
|
-
require "brown/amqp_errors"
|
4
|
-
require "brown/logger"
|
5
|
-
|
6
|
-
module Brown::Util
|
7
|
-
include Brown::AmqpErrors
|
8
|
-
include Brown::Logger
|
9
|
-
|
10
|
-
def number_of_messages
|
11
|
-
status do |num_messages, _|
|
12
|
-
yield num_messages
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
def number_of_consumers
|
17
|
-
status do |_, num_consumers|
|
18
|
-
yield num_consumers
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
private
|
23
|
-
|
24
|
-
def open_channel(opts={}, &blk)
|
25
|
-
AMQP::Channel.new(Brown.connection) do |channel,_|
|
26
|
-
logger.debug { "Opened channel: #{"%#x" % channel.object_id}" }
|
27
|
-
|
28
|
-
channel.auto_recovery = true
|
29
|
-
logger.debug { "Channel auto recovery enabled" }
|
30
|
-
|
31
|
-
# Set up QoS. If you do not do this then any subscribes will get
|
32
|
-
# overwhelmed if there are too many messages.
|
33
|
-
prefetch = opts[:prefetch] || 1
|
34
|
-
|
35
|
-
channel.prefetch(prefetch)
|
36
|
-
logger.debug { "AMQP prefetch set to: #{prefetch}" }
|
37
|
-
|
38
|
-
blk.call(channel)
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
def random(prefix = '', suffix = '')
|
43
|
-
"#{prefix}#{SecureRandom.hex(8)}#{suffix}"
|
44
|
-
end
|
45
|
-
|
46
|
-
def option_or_default(options, key, default, &blk)
|
47
|
-
if options.is_a?(Hash)
|
48
|
-
if options.key?(key)
|
49
|
-
v = options.delete(key)
|
50
|
-
(blk) ? blk.call(v) : v
|
51
|
-
else
|
52
|
-
default
|
53
|
-
end
|
54
|
-
else
|
55
|
-
raise ArguementError, "Options must be a Hash."
|
56
|
-
end
|
57
|
-
end
|
58
|
-
end
|
data/lib/smith.rb
DELETED