brown 1.1.2 → 2.1.0
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.
- 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