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
data/lib/brown/acl_loader.rb
DELETED
@@ -1,57 +0,0 @@
|
|
1
|
-
# -*- encoding: utf-8 -*-
|
2
|
-
|
3
|
-
require 'tmpdir'
|
4
|
-
require 'protobuf'
|
5
|
-
|
6
|
-
require "brown/logger"
|
7
|
-
|
8
|
-
class Brown::ACLLoader
|
9
|
-
extend Brown::Logger
|
10
|
-
|
11
|
-
def self.load_all(*dirs)
|
12
|
-
dirs.flatten!
|
13
|
-
pfiles = dirs.each_with_object([]) do |dir, list|
|
14
|
-
list << Dir["#{dir}/*.proto"]
|
15
|
-
end.flatten
|
16
|
-
|
17
|
-
load_proto_files(pfiles, dirs)
|
18
|
-
end
|
19
|
-
|
20
|
-
def self.load_proto_files(pfiles, dirs)
|
21
|
-
orig_load_path = $LOAD_PATH
|
22
|
-
|
23
|
-
Dir.mktmpdir do |tmpdir|
|
24
|
-
dirs = pfiles.map { |f| File.dirname(f) }.uniq + [tmpdir]
|
25
|
-
dirs.each { |d| $LOAD_PATH.unshift(d) }
|
26
|
-
|
27
|
-
compiles = []
|
28
|
-
|
29
|
-
pfiles.each do |f|
|
30
|
-
pbrbfile = f.gsub(/\.proto$/, ".pb.rb")
|
31
|
-
unless File.exists?(pbrbfile) and File.stat(pfile).mtime <= File.stat(pbrbfile).mtime
|
32
|
-
compiles << f
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
includes = dirs.map { |d| "-I '#{d}'" }.join(" ")
|
37
|
-
|
38
|
-
unless compiles.empty?
|
39
|
-
cmd = "protoc --ruby_out='#{tmpdir}' #{includes} #{compiles.map { |f| "'#{f}'" }.join(' ')} 2>&1"
|
40
|
-
output = nil
|
41
|
-
|
42
|
-
IO.popen(cmd) { |fd| output = fd.read }
|
43
|
-
|
44
|
-
if $?.exitstatus != 0
|
45
|
-
logger.fatal { "protoc failed: #{output}" }
|
46
|
-
raise RuntimeError, output
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
pfiles.each do |f|
|
51
|
-
require "#{File.basename(f, '.proto')}.pb"
|
52
|
-
end
|
53
|
-
end
|
54
|
-
ensure
|
55
|
-
$LOAD_PATH.replace(orig_load_path)
|
56
|
-
end
|
57
|
-
end
|
data/lib/brown/acl_lookup.rb
DELETED
@@ -1,52 +0,0 @@
|
|
1
|
-
# -*- encoding: utf-8 -*-
|
2
|
-
|
3
|
-
require 'extlib'
|
4
|
-
require 'murmurhash3'
|
5
|
-
|
6
|
-
module Brown::ACLLookup
|
7
|
-
def get_by_hash(type)
|
8
|
-
hashes[type]
|
9
|
-
end
|
10
|
-
module_function :get_by_hash
|
11
|
-
|
12
|
-
def get_by_type(type)
|
13
|
-
to_murmur32(type)
|
14
|
-
end
|
15
|
-
module_function :get_by_type
|
16
|
-
|
17
|
-
# Look the key up in the cache. This defaults to the key being the hash.
|
18
|
-
# If :by_type => true is passed in as the second argument then it will
|
19
|
-
# perform the lookup in the type hash.
|
20
|
-
#
|
21
|
-
def include?(key, opts={})
|
22
|
-
if opts[:by_type]
|
23
|
-
!get_by_type(key).nil?
|
24
|
-
else
|
25
|
-
!get_by_hash(key).nil?
|
26
|
-
end
|
27
|
-
end
|
28
|
-
module_function :include?
|
29
|
-
|
30
|
-
def clear!
|
31
|
-
@hashes = nil
|
32
|
-
end
|
33
|
-
module_function :clear!
|
34
|
-
|
35
|
-
def hashes
|
36
|
-
@hashes ||= begin
|
37
|
-
map = ObjectSpace.each_object(Class).map do |k|
|
38
|
-
[[to_murmur32(k), k], [k.to_s.split(/::/).last.snake_case, k]]
|
39
|
-
end.flatten(1)
|
40
|
-
Hash[map]
|
41
|
-
end
|
42
|
-
end
|
43
|
-
module_function :hashes
|
44
|
-
|
45
|
-
private
|
46
|
-
|
47
|
-
# Convert the name to a base 36 murmur hash
|
48
|
-
def to_murmur32(type)
|
49
|
-
MurmurHash3::V32.murmur3_32_str_hash(type.to_s).to_s(36)
|
50
|
-
end
|
51
|
-
module_function :to_murmur32
|
52
|
-
end
|
data/lib/brown/amqp_errors.rb
DELETED
@@ -1,148 +0,0 @@
|
|
1
|
-
# -*- encoding: utf-8 -*-
|
2
|
-
|
3
|
-
module Brown::AmqpErrors
|
4
|
-
def error_message(code, text, &blk)
|
5
|
-
details = error_lookup(code)
|
6
|
-
message = "#{details[:error_class]} exception: #{code} " +
|
7
|
-
"(#{details[:name]}). #{details[:description]}"
|
8
|
-
|
9
|
-
case code
|
10
|
-
when 404
|
11
|
-
diagnosis = "looks like the queue has been deleted."
|
12
|
-
when 406
|
13
|
-
case text
|
14
|
-
when /.*(unknown delivery tag [0-9]+).*/
|
15
|
-
diagnosis = "#{$1} - you've probably already acknowledged the message."
|
16
|
-
end
|
17
|
-
else
|
18
|
-
end
|
19
|
-
blk.call(message, diagnosis)
|
20
|
-
end
|
21
|
-
|
22
|
-
def error_lookup(code)
|
23
|
-
errors[code]
|
24
|
-
end
|
25
|
-
|
26
|
-
def errors
|
27
|
-
@errors ||= {
|
28
|
-
311 => {
|
29
|
-
:name => "content-too-large",
|
30
|
-
:error_class => "Channel",
|
31
|
-
:description => "The client attempted to transfer content larger " +
|
32
|
-
"than the server could accept at the present time. " +
|
33
|
-
"The client may retry at a later time."
|
34
|
-
},
|
35
|
-
313 => {
|
36
|
-
:name => "no-consumers",
|
37
|
-
:error_class => "Channel",
|
38
|
-
:description => "When the exchange cannot deliver to a consumer " +
|
39
|
-
"when the immediate flag is set. As a result of " +
|
40
|
-
"pending data on the queue or the absence of any " +
|
41
|
-
"consumers of the queue."
|
42
|
-
},
|
43
|
-
320 => {
|
44
|
-
:name => "connection-forced",
|
45
|
-
:error_class => "Connection",
|
46
|
-
:description => "An operator intervened to close the Connection " +
|
47
|
-
"for some reason. The client may retry at some " +
|
48
|
-
"later date."
|
49
|
-
},
|
50
|
-
402 => {
|
51
|
-
:name => "invalid-path",
|
52
|
-
:error_class => "Connection",
|
53
|
-
:description => "The client tried to work with an unknown virtual host."
|
54
|
-
},
|
55
|
-
403 => {
|
56
|
-
:name => "access-refused",
|
57
|
-
:error_class => "Channel",
|
58
|
-
:description => "The client attempted to work with a server " +
|
59
|
-
"entity to which it has no access due to security " +
|
60
|
-
"settings."
|
61
|
-
},
|
62
|
-
404 => {
|
63
|
-
:name => "not-found",
|
64
|
-
:error_class => "Channel",
|
65
|
-
:description => "The client attempted to work with a server " +
|
66
|
-
"entity that does not exist."
|
67
|
-
},
|
68
|
-
405 => {
|
69
|
-
:name => "resource-locked",
|
70
|
-
:error_class => "Channel",
|
71
|
-
:description => "The client attempted to work with a server " +
|
72
|
-
"entity to which it has no access because " +
|
73
|
-
"another client is working with it."
|
74
|
-
},
|
75
|
-
406 => {
|
76
|
-
:name => "precondition-failed",
|
77
|
-
:error_class => "Channel",
|
78
|
-
:description => "The client requested a method that was not " +
|
79
|
-
"allowed because some precondition failed."
|
80
|
-
},
|
81
|
-
501 => {
|
82
|
-
:name => "frame-error",
|
83
|
-
:error_class => "Connection",
|
84
|
-
:description => "The sender sent a malformed frame that the " +
|
85
|
-
"recipient could not decode. This strongly " +
|
86
|
-
"implies a programming error in the sending peer."
|
87
|
-
},
|
88
|
-
502 => {
|
89
|
-
:name => "syntax-error",
|
90
|
-
:error_class => "Connection",
|
91
|
-
:description => "The sender sent a frame that contained illegal " +
|
92
|
-
"values for one or more fields. This strongly " +
|
93
|
-
"implies a programming error in the sending peer."
|
94
|
-
},
|
95
|
-
503 => {
|
96
|
-
:name => "command-invalid",
|
97
|
-
:error_class => "Connection",
|
98
|
-
:description => "The client sent an invalid sequence of frames, " +
|
99
|
-
"attempting to perform an operation that was " +
|
100
|
-
"considered invalid by the server. This usually " +
|
101
|
-
"implies a programming error in the client."
|
102
|
-
},
|
103
|
-
504 => {
|
104
|
-
:name => "channel-error",
|
105
|
-
:error_class => "Connection",
|
106
|
-
:description => "The client attempted to work with a Channel that " +
|
107
|
-
"had not been correctly opened. This most likely " +
|
108
|
-
"indicates a fault in the client layer."
|
109
|
-
},
|
110
|
-
505 => {
|
111
|
-
:name => "unexpected-frame",
|
112
|
-
:error_class => "Connection",
|
113
|
-
:description => "The peer sent a frame that was not expected, " +
|
114
|
-
"usually in the context of a content header and " +
|
115
|
-
"body. This strongly indicates a fault in the " +
|
116
|
-
"peer's content processing."
|
117
|
-
},
|
118
|
-
506 => {
|
119
|
-
:name => "resource-error",
|
120
|
-
:error_class => "Connection",
|
121
|
-
:description => "The server could not complete the method because " +
|
122
|
-
"it lacked sufficient resources. This may be due " +
|
123
|
-
"to the client creating too many of some type of entity."
|
124
|
-
},
|
125
|
-
530 => {
|
126
|
-
:name => "not-allowed",
|
127
|
-
:error_class => "Connection",
|
128
|
-
:description => "The client tried to work with some entity in a " +
|
129
|
-
"manner that is prohibited by the server, due to " +
|
130
|
-
"security settings or by some other criteria."
|
131
|
-
},
|
132
|
-
540 => {
|
133
|
-
:name => "not-implemented",
|
134
|
-
:error_class => "Connection",
|
135
|
-
:description => "The client tried to use functionality that is " +
|
136
|
-
"not implemented in the server."
|
137
|
-
},
|
138
|
-
541 => {
|
139
|
-
:name => "internal-error",
|
140
|
-
:error_class => "Connection",
|
141
|
-
:description => "The server could not complete the method " +
|
142
|
-
"because of an internal error. The server may " +
|
143
|
-
"require intervention by an operator in order " +
|
144
|
-
"to resume normal operations."
|
145
|
-
}
|
146
|
-
}
|
147
|
-
end
|
148
|
-
end
|
data/lib/brown/logger.rb
DELETED
@@ -1,51 +0,0 @@
|
|
1
|
-
# -*- encoding: utf-8 -*-
|
2
|
-
|
3
|
-
require 'logger'
|
4
|
-
|
5
|
-
class Logger
|
6
|
-
VERBOSE = 0.5
|
7
|
-
TRACE = -1
|
8
|
-
|
9
|
-
# Lack of prior planning, peeps!
|
10
|
-
remove_const(:SEV_LABEL)
|
11
|
-
SEV_LABEL = {
|
12
|
-
TRACE => "TRACE",
|
13
|
-
DEBUG => "DEBUG",
|
14
|
-
VERBOSE => "VERB",
|
15
|
-
INFO => "INFO",
|
16
|
-
WARN => "WARN",
|
17
|
-
ERROR => "ERROR",
|
18
|
-
FATAL => "FATAL"
|
19
|
-
}
|
20
|
-
|
21
|
-
def verbose(progname = nil, &block)
|
22
|
-
add(VERBOSE, nil, progname, &block)
|
23
|
-
end
|
24
|
-
|
25
|
-
def trace(progname = nil, &block)
|
26
|
-
add(TRACE, nil, progname, &block)
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
module Brown::Logger
|
31
|
-
def logger
|
32
|
-
@logger ||= begin
|
33
|
-
Logger.new($stderr).tap do |l|
|
34
|
-
l.formatter = proc { |s,dt,n,msg| "#{$$} [#{s[0]}] #{msg}\n" }
|
35
|
-
l.level = Logger.const_get(Brown.log_level.upcase.to_sym)
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
def log_level(level=nil)
|
41
|
-
if level
|
42
|
-
logger.level = Logger.const_get(level.upcase.to_sym)
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
def backtrace(ex)
|
47
|
-
if ex.respond_to?(:backtrace) and ex.backtrace
|
48
|
-
self.debug { ex.backtrace.map { |l| " #{l}" }.join("\n") }
|
49
|
-
end
|
50
|
-
end
|
51
|
-
end
|
data/lib/brown/message.rb
DELETED
@@ -1,73 +0,0 @@
|
|
1
|
-
# -*- encoding: utf-8 -*-
|
2
|
-
|
3
|
-
require 'brown/logger'
|
4
|
-
|
5
|
-
class Brown::Message
|
6
|
-
include Brown::Logger
|
7
|
-
|
8
|
-
attr_reader :payload, :metadata
|
9
|
-
|
10
|
-
def initialize(payload, metadata, requeue_queue, requeue_options, opts = {}, &blk)
|
11
|
-
@metadata = metadata
|
12
|
-
|
13
|
-
@requeue_queue = requeue_queue
|
14
|
-
@requeue_options = requeue_options
|
15
|
-
|
16
|
-
@requeue_options[:strategy] ||= :linear
|
17
|
-
|
18
|
-
@requeue_options[:on_requeue] ||= ->(count, total_count, cumulative_delay) {
|
19
|
-
logger.info { "Requeuing (#{@requeue_options[:strategy]}) message on queue: #{@requeue_queue.name}, count: #{count} of #{total_count}." }
|
20
|
-
}
|
21
|
-
|
22
|
-
@requeue_options[:on_requeue_limit] ||= ->(message, count, total_count, cumulative_delay) {
|
23
|
-
logger.info { "Not attempting any more requeues, requeue limit reached: #{total_count} for queue: #{@requeue_queue.name}, cummulative delay: #{cumulative_delay}s." }
|
24
|
-
}
|
25
|
-
|
26
|
-
klass = Brown::ACLLookup.get_by_hash(metadata.type)
|
27
|
-
raise RuntimeError, "Unknown ACL: #{metadata.type}" if klass.nil?
|
28
|
-
|
29
|
-
@payload = klass.new.parse_from_string(payload)
|
30
|
-
|
31
|
-
blk.call(@payload, self)
|
32
|
-
ack if opts[:auto_ack]
|
33
|
-
end
|
34
|
-
|
35
|
-
def ack(multiple = false)
|
36
|
-
@metadata.ack(multiple)
|
37
|
-
end
|
38
|
-
|
39
|
-
def nak(opts = {})
|
40
|
-
@metadata.reject(opts)
|
41
|
-
end
|
42
|
-
|
43
|
-
alias_method :reject, :nak
|
44
|
-
|
45
|
-
def requeue
|
46
|
-
if current_requeue_number < @requeue_options[:count]
|
47
|
-
cumulative_delay = case @requeue_options[:strategy].to_sym
|
48
|
-
when :linear
|
49
|
-
@requeue_options[:delay] * (current_requeue_number + 1)
|
50
|
-
when :exponential
|
51
|
-
@requeue_options[:delay] * (2 ** current_requeue_number)
|
52
|
-
when :exponential_no_initial_delay
|
53
|
-
@requeue_options[:delay] * (2 ** current_requeue_number - 1)
|
54
|
-
else
|
55
|
-
raise RuntimeError, "Unknown requeue strategy #{@requeue_options[:strategy].to_sym.inspect}"
|
56
|
-
end
|
57
|
-
|
58
|
-
EM.add_timer(cumulative_delay) do
|
59
|
-
new_headers = (@metadata.headers || {}).merge('requeue' => current_requeue_number + 1)
|
60
|
-
@requeue_queue.publish(@payload, @metadata.to_hash.merge(:headers => new_headers))
|
61
|
-
end
|
62
|
-
|
63
|
-
@requeue_options[:on_requeue].call(current_requeue_number + 1, @requeue_options[:count], cumulative_delay)
|
64
|
-
else
|
65
|
-
@requeue_options[:on_requeue_limit].call(@payload, current_requeue_number + 1, @requeue_options[:count], @requeue_options[:delay] * current_requeue_number)
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
private
|
70
|
-
def current_requeue_number
|
71
|
-
(@metadata.headers['requeue'] rescue nil) || 0
|
72
|
-
end
|
73
|
-
end
|
data/lib/brown/module_methods.rb
DELETED
@@ -1,134 +0,0 @@
|
|
1
|
-
# Remove any pre-existing activation of eventmachine, so that `eventmachine-le`
|
2
|
-
# takes priority
|
3
|
-
$:.delete_if { |d| d =~ /\/eventmachine-\d/ }
|
4
|
-
|
5
|
-
require 'eventmachine-le'
|
6
|
-
require 'amqp'
|
7
|
-
require 'uri'
|
8
|
-
|
9
|
-
require 'brown/logger'
|
10
|
-
|
11
|
-
module Brown::ModuleMethods
|
12
|
-
include Brown::Logger
|
13
|
-
|
14
|
-
attr_reader :connection, :log_level
|
15
|
-
|
16
|
-
def compile_acls
|
17
|
-
end
|
18
|
-
|
19
|
-
def config
|
20
|
-
Class.new.tap do |cfg|
|
21
|
-
cfg.send(:define_method, :method_missing) do |*_args|
|
22
|
-
Class.new.tap do |group|
|
23
|
-
group.send(:define_method, :method_missing) do |*_args|
|
24
|
-
""
|
25
|
-
end
|
26
|
-
end.new
|
27
|
-
end
|
28
|
-
end.new
|
29
|
-
end
|
30
|
-
|
31
|
-
def running?
|
32
|
-
EM.reactor_running?
|
33
|
-
end
|
34
|
-
|
35
|
-
def start(opts={})
|
36
|
-
@log_level = opts[:log_level] || "info"
|
37
|
-
|
38
|
-
# Why these are not the defaults, I will never know
|
39
|
-
EM.epoll if EM.epoll?
|
40
|
-
EM.kqueue if EM.kqueue?
|
41
|
-
|
42
|
-
connection_settings = {
|
43
|
-
:on_tcp_connection_failure => method(:tcp_connection_failure_handler),
|
44
|
-
:on_possible_authentication_failure => method(:authentication_failure_handler)
|
45
|
-
}
|
46
|
-
|
47
|
-
AMQP.start(opts[:server_url], connection_settings) do |connection|
|
48
|
-
EM.threadpool_size = 1
|
49
|
-
@connection = connection
|
50
|
-
|
51
|
-
connection.on_connection do
|
52
|
-
logger.info { "Connected to: AMQP Broker: #{broker_identifier(connection)}" }
|
53
|
-
end
|
54
|
-
|
55
|
-
connection.on_tcp_connection_loss do |connection, settings|
|
56
|
-
logger.info { "Reconnecting to AMQP Broker: #{broker_identifier(connection)} in 5s" }
|
57
|
-
connection.reconnect(false, 5)
|
58
|
-
end
|
59
|
-
|
60
|
-
connection.after_recovery do |connection|
|
61
|
-
logger.info { "Connection with AMQP Broker restored: #{broker_identifier(connection)}" }
|
62
|
-
end
|
63
|
-
|
64
|
-
connection.on_error do |connection, connection_close|
|
65
|
-
# If the broker is gracefully shutdown we get a 320. Log a nice message.
|
66
|
-
if connection_close.reply_code == 320
|
67
|
-
logger.info { "AMQP Broker shutdown: #{broker_identifier(connection)}" }
|
68
|
-
else
|
69
|
-
logger.warn { connection_close.reply_text }
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
# This will be the last thing run by the reactor.
|
74
|
-
shutdown_hook { logger.debug { "Reactor Stopped" } }
|
75
|
-
|
76
|
-
yield if block_given?
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
|
-
def shutdown_hook(&block)
|
81
|
-
EM.add_shutdown_hook(&block)
|
82
|
-
end
|
83
|
-
|
84
|
-
def stop(immediately=false, &blk)
|
85
|
-
shutdown_hook(&blk) if blk
|
86
|
-
|
87
|
-
if running?
|
88
|
-
if immediately
|
89
|
-
EM.next_tick do
|
90
|
-
@connection.close { EM.stop_event_loop }
|
91
|
-
end
|
92
|
-
else
|
93
|
-
EM.add_timer(1) do
|
94
|
-
@connection.close { EM.stop_event_loop }
|
95
|
-
end
|
96
|
-
end
|
97
|
-
else
|
98
|
-
logger.fatal { "Eventmachine is not running, exiting with prejudice" }
|
99
|
-
exit!
|
100
|
-
end
|
101
|
-
end
|
102
|
-
|
103
|
-
private
|
104
|
-
|
105
|
-
def tcp_connection_failure_handler(settings)
|
106
|
-
# Only display the following settings.
|
107
|
-
s = settings.select { |k,v| ([:user, :pass, :vhost, :host, :port, :ssl].include?(k)) }
|
108
|
-
|
109
|
-
logger.fatal { "Cannot connect to the AMQP server." }
|
110
|
-
logger.fatal { "Is the server running and are the connection details correct?" }
|
111
|
-
logger.info { "Details:" }
|
112
|
-
s.each do |k,v|
|
113
|
-
logger.info { " Setting: %-7s%s" % [k, v] }
|
114
|
-
end
|
115
|
-
EM.stop
|
116
|
-
end
|
117
|
-
|
118
|
-
def authentication_failure_handler(settings)
|
119
|
-
# Only display the following settings.
|
120
|
-
s = settings.select { |k,v| [:user, :pass, :vhost, :host].include?(k) }
|
121
|
-
|
122
|
-
logger.fatal { "Authentication failure." }
|
123
|
-
logger.info { "Details:" }
|
124
|
-
s.each do |k,v|
|
125
|
-
logger.info { " Setting: %-7s%s" % [k, v] }
|
126
|
-
end
|
127
|
-
EM.stop
|
128
|
-
end
|
129
|
-
|
130
|
-
def broker_identifier(connection)
|
131
|
-
broker = connection.broker.properties
|
132
|
-
"#{connection.broker_endpoint}, (#{broker['product']}/v#{broker['version']})"
|
133
|
-
end
|
134
|
-
end
|