omf_common 6.0.2.pre.2 → 6.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/file_broadcaster.rb +5 -0
- data/bin/file_receiver.rb +5 -0
- data/bin/omf_keygen +3 -3
- data/bin/omf_send_configure +114 -0
- data/bin/omf_send_request +19 -4
- data/example/engine_alt.rb +13 -7
- data/example/viz/garage_monitor.rb +69 -0
- data/example/viz/garage_viz.rb +52 -0
- data/example/viz/htdocs/image/garage.png +0 -0
- data/example/viz/htdocs/template/garage_banner.html +2 -0
- data/example/viz/layout.yaml +44 -0
- data/example/vm_alt.rb +5 -0
- data/lib/omf_common.rb +17 -8
- data/lib/omf_common/auth.rb +5 -0
- data/lib/omf_common/auth/certificate.rb +21 -2
- data/lib/omf_common/auth/certificate_store.rb +50 -20
- data/lib/omf_common/auth/ssh_pub_key_convert.rb +7 -0
- data/lib/omf_common/comm.rb +6 -1
- data/lib/omf_common/comm/amqp/amqp_communicator.rb +88 -12
- data/lib/omf_common/comm/amqp/amqp_file_transfer.rb +5 -0
- data/lib/omf_common/comm/amqp/amqp_topic.rb +37 -18
- data/lib/omf_common/comm/local/local_communicator.rb +5 -0
- data/lib/omf_common/comm/local/local_topic.rb +5 -0
- data/lib/omf_common/comm/topic.rb +32 -13
- data/lib/omf_common/comm/xmpp/communicator.rb +11 -1
- data/lib/omf_common/comm/xmpp/topic.rb +5 -0
- data/lib/omf_common/comm/xmpp/xmpp_mp.rb +5 -0
- data/lib/omf_common/command.rb +5 -0
- data/lib/omf_common/core_ext/string.rb +5 -0
- data/lib/omf_common/default_logging.rb +23 -5
- data/lib/omf_common/eventloop.rb +40 -23
- data/lib/omf_common/eventloop/em.rb +18 -5
- data/lib/omf_common/eventloop/local_evl.rb +18 -15
- data/lib/omf_common/exec_app.rb +44 -24
- data/lib/omf_common/key.rb +5 -0
- data/lib/omf_common/measure.rb +5 -0
- data/lib/omf_common/message.rb +5 -0
- data/lib/omf_common/message/json/json_message.rb +13 -5
- data/lib/omf_common/message/xml/message.rb +19 -4
- data/lib/omf_common/message/xml/relaxng_schema.rb +5 -0
- data/lib/omf_common/message/xml/topic_message.rb +5 -0
- data/lib/omf_common/version.rb +6 -1
- data/omf_common.gemspec +3 -2
- data/test/fixture/1st_level.pem +20 -0
- data/test/fixture/2nd_level.pem +19 -0
- data/test/fixture/3rd_level.pem +19 -0
- data/test/fixture/pubsub.rb +5 -0
- data/test/fixture/rc.pem +18 -0
- data/test/fixture/root.pem +17 -0
- data/test/omf_common/auth/certificate_spec.rb +27 -0
- data/test/omf_common/auth/certificate_store_spec.rb +58 -0
- data/test/omf_common/auth/ssh_pub_key_convert_spec.rb +5 -0
- data/test/omf_common/comm/topic_spec.rb +7 -1
- data/test/omf_common/comm/xmpp/communicator_spec.rb +5 -0
- data/test/omf_common/comm/xmpp/topic_spec.rb +5 -0
- data/test/omf_common/comm_spec.rb +5 -0
- data/test/omf_common/command_spec.rb +5 -0
- data/test/omf_common/core_ext/string_spec.rb +5 -0
- data/test/omf_common/message/xml/message_spec.rb +5 -0
- data/test/omf_common/message_spec.rb +8 -3
- data/test/test_helper.rb +5 -0
- metadata +48 -11
data/lib/omf_common/auth.rb
CHANGED
@@ -1,3 +1,8 @@
|
|
1
|
+
# Copyright (c) 2012 National ICT Australia Limited (NICTA).
|
2
|
+
# This software may be used and distributed solely under the terms of the MIT license (License).
|
3
|
+
# You should find a copy of the License in LICENSE.TXT or at http://opensource.org/licenses/MIT.
|
4
|
+
# By downloading or using this software you accept the terms and the liability disclaimer in the License.
|
5
|
+
|
1
6
|
|
2
7
|
|
3
8
|
module OmfCommon
|
@@ -1,3 +1,8 @@
|
|
1
|
+
# Copyright (c) 2012 National ICT Australia Limited (NICTA).
|
2
|
+
# This software may be used and distributed solely under the terms of the MIT license (License).
|
3
|
+
# You should find a copy of the License in LICENSE.TXT or at http://opensource.org/licenses/MIT.
|
4
|
+
# By downloading or using this software you accept the terms and the liability disclaimer in the License.
|
5
|
+
|
1
6
|
require 'openssl'
|
2
7
|
require 'omf_common/auth'
|
3
8
|
require 'omf_common/auth/ssh_pub_key_convert'
|
@@ -32,9 +37,11 @@ module OmfCommon::Auth
|
|
32
37
|
# @param [String] pem is the content of existing x509 cert
|
33
38
|
# @param [OpenSSL::PKey::RSA|String] key is the private key which can be attached to the instance for signing.
|
34
39
|
def self.create_from_x509(pem, key = nil)
|
35
|
-
|
40
|
+
# Some command list generated cert can use \r\n as newline char
|
41
|
+
unless pem =~ /^-----BEGIN CERTIFICATE-----/
|
36
42
|
pem = "#{BEGIN_CERT}#{pem}#{END_CERT}"
|
37
43
|
end
|
44
|
+
|
38
45
|
cert = OpenSSL::X509::Certificate.new(pem)
|
39
46
|
|
40
47
|
key = OpenSSL::PKey::RSA.new(key) if key && key.is_a?(String)
|
@@ -64,7 +71,9 @@ module OmfCommon::Auth
|
|
64
71
|
|
65
72
|
# Create a X509 certificate
|
66
73
|
#
|
67
|
-
# @param [] address
|
74
|
+
# @param [String] address
|
75
|
+
# @param [String] subject
|
76
|
+
# @param [OpenSSL::PKey::RSA] key
|
68
77
|
# @return {cert, key}
|
69
78
|
#
|
70
79
|
def self._create_x509_cert(address, subject, key, digest = nil,
|
@@ -127,8 +136,18 @@ module OmfCommon::Auth
|
|
127
136
|
@cert ||= _create_x509_cert(@address, @subject, @key, @digest)[:cert]
|
128
137
|
end
|
129
138
|
|
139
|
+
# @param [OpenSSL::PKey::RSA|String] key is most likely the public key of the resource.
|
140
|
+
#
|
130
141
|
def create_for(address, name, type, domain = DEF_DOMAIN_NAME, duration = 3600, key = nil)
|
131
142
|
raise ArgumentError, "Address required" unless address
|
143
|
+
|
144
|
+
begin
|
145
|
+
key = OpenSSL::PKey::RSA.new(key) if key && key.is_a?(String)
|
146
|
+
rescue OpenSSL::PKey::RSAError
|
147
|
+
# It might be a SSH pub key, try that
|
148
|
+
key = OmfCommon::Auth::SSHPubKeyConvert.convert(key)
|
149
|
+
end
|
150
|
+
|
132
151
|
cert = self.class.create(address, name, type, domain, self, Time.now, duration, key)
|
133
152
|
CertificateStore.instance.register(cert, address)
|
134
153
|
cert
|
@@ -1,27 +1,19 @@
|
|
1
|
+
# Copyright (c) 2012 National ICT Australia Limited (NICTA).
|
2
|
+
# This software may be used and distributed solely under the terms of the MIT license (License).
|
3
|
+
# You should find a copy of the License in LICENSE.TXT or at http://opensource.org/licenses/MIT.
|
4
|
+
# By downloading or using this software you accept the terms and the liability disclaimer in the License.
|
5
|
+
|
1
6
|
require 'openssl'
|
7
|
+
require 'monitor'
|
2
8
|
|
3
9
|
require 'omf_common/auth'
|
4
10
|
|
5
|
-
#require 'singleton'
|
6
|
-
|
7
|
-
# module OmfCommon
|
8
|
-
# class Key
|
9
|
-
# include Singleton
|
10
|
-
#
|
11
|
-
# attr_accessor :private_key
|
12
|
-
#
|
13
|
-
# def import(filename)
|
14
|
-
# self.private_key = OpenSSL::PKey.read(File.read(filename))
|
15
|
-
# end
|
16
|
-
# end
|
17
|
-
# end
|
18
|
-
|
19
11
|
module OmfCommon::Auth
|
20
12
|
|
21
13
|
class MissingPrivateKeyException < AuthException; end
|
22
14
|
|
23
15
|
class CertificateStore
|
24
|
-
|
16
|
+
include MonitorMixin
|
25
17
|
|
26
18
|
@@instance = nil
|
27
19
|
|
@@ -38,12 +30,27 @@ module OmfCommon::Auth
|
|
38
30
|
end
|
39
31
|
|
40
32
|
def register(certificate, address = nil)
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
33
|
+
@@instance.synchronize do
|
34
|
+
begin
|
35
|
+
@x509_store.add_cert(certificate.to_x509) if @certs[address].nil? && @certs[certificate.subject].nil?
|
36
|
+
rescue OpenSSL::X509::StoreError => e
|
37
|
+
if e.message == "cert already in hash table"
|
38
|
+
raise "X509 cert '#{address}' already registered in X509 store"
|
39
|
+
else
|
40
|
+
raise e
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
address ||= certificate.address
|
45
|
+
|
46
|
+
if address
|
47
|
+
@certs[address] ||= certificate
|
48
|
+
else
|
49
|
+
debug "Register certificate without address - #{certificate}, is it a CA cert?"
|
50
|
+
end
|
51
|
+
|
52
|
+
@certs[certificate.subject] ||= certificate
|
45
53
|
end
|
46
|
-
@certs[certificate.subject] = certificate
|
47
54
|
end
|
48
55
|
|
49
56
|
def register_x509(cert_pem, address = nil)
|
@@ -57,15 +64,38 @@ module OmfCommon::Auth
|
|
57
64
|
@certs[url]
|
58
65
|
end
|
59
66
|
|
67
|
+
# @param [OpenSSL::X509::Certificate] cert
|
68
|
+
#
|
69
|
+
def verify(cert)
|
70
|
+
cert = cert.to_x509 if cert.kind_of? OmfCommon::Auth::Certificate
|
71
|
+
v_result = @x509_store.verify(cert)
|
72
|
+
warn "Cert verification failed: '#{@x509_store.error_string}'" unless v_result
|
73
|
+
v_result
|
74
|
+
end
|
75
|
+
|
76
|
+
# Load a set of CA certs into cert store from a given location
|
77
|
+
#
|
78
|
+
# @param [String] folder contains all the CA certs
|
79
|
+
#
|
80
|
+
def register_default_certs(folder)
|
81
|
+
Dir["#{folder}/*"].each do |cert|
|
82
|
+
register_x509(File.read(cert))
|
83
|
+
end
|
84
|
+
end
|
60
85
|
|
61
86
|
private
|
87
|
+
|
62
88
|
def initialize(opts)
|
89
|
+
@x509_store = OpenSSL::X509::Store.new
|
90
|
+
|
63
91
|
@certs = {}
|
64
92
|
if store = opts[:store]
|
65
93
|
else
|
66
94
|
@store = {private: {}, public: {}}
|
67
95
|
end
|
68
96
|
@serial = 0
|
97
|
+
|
98
|
+
super()
|
69
99
|
end
|
70
100
|
end # class
|
71
101
|
|
@@ -1,3 +1,8 @@
|
|
1
|
+
# Copyright (c) 2012 National ICT Australia Limited (NICTA).
|
2
|
+
# This software may be used and distributed solely under the terms of the MIT license (License).
|
3
|
+
# You should find a copy of the License in LICENSE.TXT or at http://opensource.org/licenses/MIT.
|
4
|
+
# By downloading or using this software you accept the terms and the liability disclaimer in the License.
|
5
|
+
|
1
6
|
require 'base64'
|
2
7
|
require 'openssl'
|
3
8
|
require 'omf_common/auth'
|
@@ -42,6 +47,8 @@ module OmfCommon::Auth
|
|
42
47
|
#
|
43
48
|
def self.convert(keystring)
|
44
49
|
(type, b64, id) = keystring.split(' ')
|
50
|
+
raise ArgumentError, "Invalid SSH public key '#{keystring}'" if b64.nil?
|
51
|
+
|
45
52
|
decoded_key = Base64.decode64(b64)
|
46
53
|
(n, bytes) = unpack_u32(decoded_key)
|
47
54
|
(keytype, bytes) = unpack_string(bytes, n)
|
data/lib/omf_common/comm.rb
CHANGED
@@ -1,3 +1,8 @@
|
|
1
|
+
# Copyright (c) 2012 National ICT Australia Limited (NICTA).
|
2
|
+
# This software may be used and distributed solely under the terms of the MIT license (License).
|
3
|
+
# You should find a copy of the License in LICENSE.TXT or at http://opensource.org/licenses/MIT.
|
4
|
+
# By downloading or using this software you accept the terms and the liability disclaimer in the License.
|
5
|
+
|
1
6
|
require 'omf_common/comm/topic'
|
2
7
|
|
3
8
|
module OmfCommon
|
@@ -122,7 +127,7 @@ module OmfCommon
|
|
122
127
|
|
123
128
|
# Returning connection information
|
124
129
|
#
|
125
|
-
# @
|
130
|
+
# @return [Hash] connection information hash, with type, user and domain.
|
126
131
|
def conn_info
|
127
132
|
{ proto: nil, user: nil, domain: nil }
|
128
133
|
end
|
@@ -1,3 +1,8 @@
|
|
1
|
+
# Copyright (c) 2012 National ICT Australia Limited (NICTA).
|
2
|
+
# This software may be used and distributed solely under the terms of the MIT license (License).
|
3
|
+
# You should find a copy of the License in LICENSE.TXT or at http://opensource.org/licenses/MIT.
|
4
|
+
# By downloading or using this software you accept the terms and the liability disclaimer in the License.
|
5
|
+
|
1
6
|
require 'amqp'
|
2
7
|
require 'omf_common/comm/amqp/amqp_topic'
|
3
8
|
#require 'omf_common/comm/monkey_patches'
|
@@ -11,23 +16,25 @@ module OmfCommon
|
|
11
16
|
# # ignore arguments
|
12
17
|
# end
|
13
18
|
|
19
|
+
attr_reader :channel
|
20
|
+
|
14
21
|
# Initialize comms layer
|
15
22
|
#
|
16
23
|
def init(opts = {})
|
17
|
-
|
24
|
+
@opts = {
|
25
|
+
#:ssl (Hash) � TLS (SSL) parameters to use.
|
26
|
+
heartbeat: 20, # (Fixnum) � default: 0 � Connection heartbeat, in seconds. 0 means no heartbeat. Can also be configured server-side starting with RabbitMQ 3.0.
|
27
|
+
#:on_tcp_connection_failure (#call) � A callable object that will be run if connection to server fails
|
28
|
+
#:on_possible_authentication_failure (#call) � A callable object that will be run if authentication fails (see Authentication failure section)
|
29
|
+
reconnect_delay: 20 # (Fixnum) Delay in seconds before attempting reconnect on detected failure
|
30
|
+
}.merge(opts)
|
31
|
+
|
32
|
+
unless (@url = @opts.delete(:url))
|
18
33
|
raise "Missing 'url' option for AQMP layer"
|
19
34
|
end
|
20
35
|
@address_prefix = @url + '/'
|
21
|
-
|
22
|
-
|
23
|
-
@on_connected_procs.each do |proc|
|
24
|
-
proc.arity == 1 ? proc.call(self) : proc.call
|
25
|
-
end
|
26
|
-
|
27
|
-
OmfCommon.eventloop.on_stop do
|
28
|
-
connection.close
|
29
|
-
end
|
30
|
-
end
|
36
|
+
_connect()
|
37
|
+
#AMQP::Session#on_skipped_heartbeats callback that can be used to handle skipped heartbeats
|
31
38
|
super
|
32
39
|
end
|
33
40
|
|
@@ -44,13 +51,25 @@ module OmfCommon
|
|
44
51
|
@on_connected_procs << block
|
45
52
|
end
|
46
53
|
|
54
|
+
# register callbacks to be called when the underlying AMQP layer
|
55
|
+
# needs to reconnect to the AMQP server. This may require some additional
|
56
|
+
# repairs. If 'block' is nil, the callback is removed
|
57
|
+
#
|
58
|
+
def on_reconnect(key, &block)
|
59
|
+
if block.nil?
|
60
|
+
@on_reconnect.delete(key)
|
61
|
+
else
|
62
|
+
@on_reconnect[key] = block
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
47
66
|
# Create a new pubsub topic with additional configuration
|
48
67
|
#
|
49
68
|
# @param [String] topic Pubsub topic name
|
50
69
|
def create_topic(topic, opts = {})
|
51
70
|
raise "Topic can't be nil or empty" if topic.nil? || topic.empty?
|
52
71
|
opts = opts.dup
|
53
|
-
opts[:
|
72
|
+
opts[:communicator] = self
|
54
73
|
topic = topic.to_s
|
55
74
|
if topic.start_with? 'amqp:'
|
56
75
|
# absolute address
|
@@ -95,8 +114,65 @@ module OmfCommon
|
|
95
114
|
private
|
96
115
|
def initialize(opts = {})
|
97
116
|
@on_connected_procs = []
|
117
|
+
@on_reconnect = {}
|
98
118
|
super
|
99
119
|
end
|
120
|
+
|
121
|
+
def _connect()
|
122
|
+
last_reported_timestamp = nil
|
123
|
+
@session = ::AMQP.connect(@url, @opts) do |connection|
|
124
|
+
connection.on_tcp_connection_loss do |conn, settings|
|
125
|
+
now = Time.now
|
126
|
+
if last_reported_timestamp == nil || (now - last_reported_timestamp) > 60
|
127
|
+
warn "Lost connectivity. Trying to reconnect..."
|
128
|
+
last_reported_timestamp = now
|
129
|
+
end
|
130
|
+
conn.reconnect(false, 2)
|
131
|
+
end
|
132
|
+
@channel = ::AMQP::Channel.new(connection)
|
133
|
+
@channel.auto_recovery = true
|
134
|
+
|
135
|
+
|
136
|
+
@on_connected_procs.each do |proc|
|
137
|
+
proc.arity == 1 ? proc.call(self) : proc.call
|
138
|
+
end
|
139
|
+
|
140
|
+
OmfCommon.eventloop.on_stop do
|
141
|
+
connection.close
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
rec_delay = @opts[:reconnect_delay]
|
146
|
+
@session.on_tcp_connection_failure do
|
147
|
+
warn "Cannot connect to AMQP server '#{@url}'. Attempt to retry in #{rec_delay} sec"
|
148
|
+
@session = nil
|
149
|
+
OmfCommon.eventloop.after(rec_delay) do
|
150
|
+
info 'Retrying'
|
151
|
+
_connect
|
152
|
+
end
|
153
|
+
end
|
154
|
+
# @session.on_tcp_connection_loss do
|
155
|
+
# _reconnect "Appear to have lost tcp connection. Attempt to reconnect in #{rec_delay} sec"
|
156
|
+
# end
|
157
|
+
# @session.on_skipped_heartbeats do
|
158
|
+
# _reconnect "Appear to have lost heartbeat. Attempt to reconnect in #{rec_delay} sec"
|
159
|
+
# end
|
160
|
+
@session.on_recovery do
|
161
|
+
info 'Recovered!'
|
162
|
+
last_reported_timestamp = nil
|
163
|
+
@on_reconnect.values.each do |block|
|
164
|
+
block.call()
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
# def _reconnect(warn_message = nil)
|
170
|
+
# warn(warn_message) if warn_message
|
171
|
+
# OmfCommon.eventloop.after(@opts[:reconnect_delay]) do
|
172
|
+
# info 'Reconnecting'
|
173
|
+
# @session.reconnect
|
174
|
+
# end
|
175
|
+
# end
|
100
176
|
end
|
101
177
|
end
|
102
178
|
end
|
@@ -1,3 +1,8 @@
|
|
1
|
+
# Copyright (c) 2012 National ICT Australia Limited (NICTA).
|
2
|
+
# This software may be used and distributed solely under the terms of the MIT license (License).
|
3
|
+
# You should find a copy of the License in LICENSE.TXT or at http://opensource.org/licenses/MIT.
|
4
|
+
# By downloading or using this software you accept the terms and the liability disclaimer in the License.
|
5
|
+
|
1
6
|
require 'set'
|
2
7
|
require 'monitor'
|
3
8
|
|
@@ -1,3 +1,8 @@
|
|
1
|
+
# Copyright (c) 2012 National ICT Australia Limited (NICTA).
|
2
|
+
# This software may be used and distributed solely under the terms of the MIT license (License).
|
3
|
+
# You should find a copy of the License in LICENSE.TXT or at http://opensource.org/licenses/MIT.
|
4
|
+
# By downloading or using this software you accept the terms and the liability disclaimer in the License.
|
5
|
+
|
1
6
|
|
2
7
|
|
3
8
|
module OmfCommon
|
@@ -8,17 +13,17 @@ module OmfCommon
|
|
8
13
|
def to_s
|
9
14
|
"AMQP::Topic<#{id}>"
|
10
15
|
end
|
11
|
-
|
16
|
+
|
12
17
|
def address
|
13
18
|
@address
|
14
19
|
end
|
15
|
-
|
20
|
+
|
16
21
|
# Call 'block' when topic is subscribed to underlying messaging
|
17
|
-
# infrastructure.
|
22
|
+
# infrastructure.
|
18
23
|
#
|
19
24
|
def on_subscribed(&block)
|
20
25
|
return unless block
|
21
|
-
|
26
|
+
|
22
27
|
call_now = false
|
23
28
|
@lock.synchronize do
|
24
29
|
if @subscribed
|
@@ -30,24 +35,35 @@ module OmfCommon
|
|
30
35
|
if call_now
|
31
36
|
after(0, &block)
|
32
37
|
end
|
33
|
-
end
|
34
|
-
|
35
|
-
|
38
|
+
end
|
39
|
+
|
40
|
+
|
36
41
|
private
|
37
|
-
|
42
|
+
|
38
43
|
def initialize(id, opts = {})
|
39
|
-
unless
|
40
|
-
raise "Missing :
|
44
|
+
unless @communicator = opts.delete(:communicator)
|
45
|
+
raise "Missing :communicator option"
|
41
46
|
end
|
42
47
|
super
|
43
48
|
@address = opts[:address]
|
44
|
-
@exchange = channel.topic(id, :auto_delete => true)
|
45
49
|
@lock = Monitor.new
|
46
50
|
@subscribed = false
|
47
51
|
@on_subscribed_handlers = []
|
48
|
-
|
49
|
-
#
|
50
|
-
|
52
|
+
|
53
|
+
# @communicator.on_reconnect(self) do
|
54
|
+
# info "Resubscribe '#{self}'"
|
55
|
+
# _init_amqp
|
56
|
+
# end
|
57
|
+
_init_amqp
|
58
|
+
end
|
59
|
+
|
60
|
+
def _init_amqp()
|
61
|
+
channel = @communicator.channel
|
62
|
+
@exchange = channel.topic(id, :auto_delete => true)
|
63
|
+
# @exchange.on_connection_interruption do |ex|
|
64
|
+
# warn "Exchange #{ex.name} detected connection interruption"
|
65
|
+
# @exchange = nil
|
66
|
+
# end
|
51
67
|
channel.queue("", :exclusive => true) do |queue|
|
52
68
|
#puts "QQ1(#{id}): #{queue}"
|
53
69
|
queue.bind(@exchange)
|
@@ -70,15 +86,18 @@ module OmfCommon
|
|
70
86
|
end
|
71
87
|
end
|
72
88
|
end
|
73
|
-
|
74
|
-
|
89
|
+
|
75
90
|
def _send_message(msg, block = nil)
|
76
91
|
super
|
77
92
|
content_type, content = msg.marshall(self)
|
78
93
|
debug "(#{id}) Send message (#{content_type}) #{msg.inspect}"
|
79
|
-
@exchange
|
94
|
+
if @exchange
|
95
|
+
@exchange.publish(content, content_type: content_type, message_id: msg.mid)
|
96
|
+
else
|
97
|
+
warn "Unavailable AMQP channel. Dropping message '#{msg}'"
|
98
|
+
end
|
80
99
|
end
|
81
100
|
end # class
|
82
|
-
end # module
|
101
|
+
end # module
|
83
102
|
end # module
|
84
103
|
end # module
|