mimi-messaging 0.1.9 → 1.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.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.rubocop.yml +66 -0
  4. data/README.md +68 -3
  5. data/TODO.md +8 -0
  6. data/docs/Messaging_Layer_Properties.md +141 -0
  7. data/docs/Why_HTTP_is_a_bad_choice.md +20 -0
  8. data/docs/diagrams/Pattern -- Command.drawio +1 -0
  9. data/docs/diagrams/Pattern -- Event direct.drawio +1 -0
  10. data/docs/diagrams/Pattern -- Event with Queue.drawio +1 -0
  11. data/docs/diagrams/Pattern -- Event.drawio +1 -0
  12. data/docs/diagrams/Pattern -- Query.drawio +1 -0
  13. data/docs/img/pattern--command.png +0 -0
  14. data/docs/img/pattern--event-direct.png +0 -0
  15. data/docs/img/pattern--event-using-queue.png +0 -0
  16. data/docs/img/pattern--event.png +0 -0
  17. data/docs/img/pattern--query.png +0 -0
  18. data/examples/basic_event_listener.rb +35 -0
  19. data/examples/basic_request_processor.rb +38 -0
  20. data/examples/using_messaging_low.rb +59 -0
  21. data/examples/using_pure_adapter.rb +62 -0
  22. data/lib/mimi/messaging.rb +429 -92
  23. data/lib/mimi/messaging/adapters.rb +22 -0
  24. data/lib/mimi/messaging/adapters/base.rb +233 -0
  25. data/lib/mimi/messaging/adapters/memory.rb +119 -0
  26. data/lib/mimi/messaging/adapters/test.rb +50 -0
  27. data/lib/mimi/messaging/errors.rb +24 -12
  28. data/lib/mimi/messaging/json_serializer.rb +45 -0
  29. data/lib/mimi/messaging/message.rb +25 -65
  30. data/lib/mimi/messaging/version.rb +3 -1
  31. data/mimi-messaging.gemspec +25 -23
  32. metadata +34 -77
  33. data/lib/mimi/messaging/connection.rb +0 -181
  34. data/lib/mimi/messaging/listener.rb +0 -72
  35. data/lib/mimi/messaging/mock.rb +0 -13
  36. data/lib/mimi/messaging/mock/connection.rb +0 -153
  37. data/lib/mimi/messaging/mock/request.rb +0 -18
  38. data/lib/mimi/messaging/mock/request_processor.rb +0 -92
  39. data/lib/mimi/messaging/model.rb +0 -27
  40. data/lib/mimi/messaging/model_provider.rb +0 -100
  41. data/lib/mimi/messaging/msgpack/msgpack_ext.rb +0 -14
  42. data/lib/mimi/messaging/msgpack/type_packer.rb +0 -104
  43. data/lib/mimi/messaging/notification.rb +0 -35
  44. data/lib/mimi/messaging/provider.rb +0 -48
  45. data/lib/mimi/messaging/request.rb +0 -56
  46. data/lib/mimi/messaging/request_processor.rb +0 -216
  47. data/lib/mimi/messaging/request_processor/context.rb +0 -39
  48. data/lib/mimi/messaging/request_processor/dsl.rb +0 -121
  49. data/lib/tasks/console_ext.rake +0 -6
  50. data/lib/tasks/console_helpers.rb +0 -116
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "json"
4
+
5
+ module Mimi
6
+ module Messaging
7
+ #
8
+ # JSON serializer.
9
+ #
10
+ # De/Serializes a message (Hash) from/into a JSON object
11
+ #
12
+ module JsonSerializer
13
+ #
14
+ # Serialize given message into JSON object
15
+ #
16
+ # @param message [Hash]
17
+ # @return [String]
18
+ #
19
+ def self.serialize(message)
20
+ unless message.is_a?(Hash)
21
+ raise ArgumentError, "Invalid message passed to #{self}#serialize, Hash is expected"
22
+ end
23
+
24
+ message.to_json
25
+ rescue StandardError => e
26
+ raise "#{self} failed to serialize a message: #{e}"
27
+ end
28
+
29
+ # Deserializes a JSON into a message
30
+ #
31
+ # @param message [String]
32
+ # @return [Hash]
33
+ #
34
+ def self.deserialize(message)
35
+ unless message.is_a?(String)
36
+ raise ArgumentError, "Invalid message passed to #{self}#deserialize, String is expected"
37
+ end
38
+
39
+ JSON.parse(message)
40
+ rescue StandardError => e
41
+ raise "#{self} failed to deserialize a message: #{e}"
42
+ end
43
+ end # module JsonSerializer
44
+ end # module Messaging
45
+ end # module Mimi
@@ -1,74 +1,34 @@
1
- require 'json'
2
- require 'msgpack'
1
+ # frozen_string_literal: true
3
2
 
4
3
  module Mimi
5
4
  module Messaging
6
- class Message < Hashie::Mash
7
- def self.queue(name, _opts = {})
8
- @queue_name = name
9
- end
10
-
11
- def self.queue_name
12
- @queue_name || default_queue_name
13
- end
14
-
15
- def self.default_queue_name
16
- Mimi::Messaging::RequestProcessor.class_name_to_resource_name(self, 'message')
17
- end
18
-
19
- def self.get(name, data = {}, opts = {})
20
- headers = {
21
- method_name: name.to_s,
22
- Mimi::Messaging::CONTEXT_ID_KEY => Mimi::Messaging.logger.context_id
23
- }
24
- _d, _m, response = Mimi::Messaging.get(
25
- queue_name, encode(data), opts.deep_merge(headers: headers)
26
- )
27
- raise Timeout::Error unless response
28
- message = new(decode(response))
29
- raise RequestError.new(message.error, Message.new(message.params)) if message.error?
30
- message
31
- end
32
-
33
- def self.post(name, data = {}, opts = {})
34
- headers = {
35
- method_name: name.to_s,
36
- Mimi::Messaging::CONTEXT_ID_KEY => Mimi::Messaging.logger.context_id
37
- }
38
- Mimi::Messaging.post(
39
- queue_name, encode(data), opts.deep_merge(headers: headers)
40
- )
41
- end
42
-
43
- def self.add_method(name, &block)
44
- self.class.instance_eval do
45
- define_method(name, &block)
5
+ #
6
+ # A Message is a Hash and additional headers structure.
7
+ #
8
+ class Message < Hash
9
+ attr_reader :headers
10
+
11
+ # Creates a Message out of Hash or another Message.
12
+ #
13
+ # @param message_or_hash [Hash,Message]
14
+ # @param headers [Hash,nil] additional headers to attach to the message
15
+ #
16
+ def initialize(message_or_hash, headers = nil)
17
+ unless message_or_hash.is_a?(Hash) # or a Message
18
+ raise ArgumentError, "Message or Hash is expected as argument"
46
19
  end
47
- end
48
20
 
49
- def self.methods(*names)
50
- names.each do |method_name|
51
- add_method(method_name) do |*params|
52
- get(method_name, *params)
53
- end
54
- add_method("#{method_name}!") do |*params|
55
- post(method_name, *params)
56
- nil
57
- end
58
- end
59
- end
21
+ # copy attributes
22
+ message_or_hash.each { |k, v| self[k] = v.dup }
60
23
 
61
- def self.encode(data)
62
- MessagePack.pack(data) # data.to_json
63
- end
64
-
65
- def self.decode(raw_message)
66
- MessagePack.unpack(raw_message) # JSON.parse(raw_message)
67
- end
68
-
69
- def to_s
70
- to_hash.to_s
24
+ # copy headers
25
+ headers ||= {}
26
+ if message_or_hash.is_a?(Mimi::Messaging::Message)
27
+ @headers = message_or_hash.headers.merge(headers)
28
+ else
29
+ @headers = headers
30
+ end
71
31
  end
72
32
  end # class Message
73
33
  end # module Messaging
74
- end # module Mimi
34
+ end # module Mimi
@@ -1,5 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Mimi
2
4
  module Messaging
3
- VERSION = '0.1.9'.freeze
5
+ VERSION = "1.1.0"
4
6
  end
5
7
  end
@@ -1,39 +1,41 @@
1
- # coding: utf-8
2
- lib = File.expand_path('../lib', __FILE__)
1
+ # frozen_string_literal: true
2
+
3
+ lib = File.expand_path("lib", __dir__)
3
4
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
- require 'mimi/messaging/version'
5
+ require "mimi/messaging/version"
5
6
 
6
7
  Gem::Specification.new do |spec|
7
- spec.name = 'mimi-messaging'
8
+ spec.name = "mimi-messaging"
8
9
  spec.version = Mimi::Messaging::VERSION
9
- spec.authors = ['Alex Kukushkin']
10
- spec.email = ['alex@kukushk.in']
10
+ spec.authors = ["Alex Kukushkin"]
11
+ spec.email = ["alex@kukushk.in"]
11
12
 
12
- spec.summary = 'Communications via RabbitMQ for mimi'
13
- spec.description = 'Communications via RabbitMQ for mimi'
14
- spec.homepage = 'https://github.com/kukushkin/mimi-messaging'
15
- spec.license = 'MIT'
13
+ spec.summary = "Interservice communication via message bus for microservices"
14
+ spec.description = "Interservice communication via message bus for microservices"
15
+ spec.homepage = "https://github.com/kukushkin/mimi-messaging"
16
+ spec.license = "MIT"
16
17
 
17
18
  # Prevent pushing this gem to RubyGems.org by setting 'allowed_push_host', or
18
19
  # delete this section to allow pushing this gem to any host.
19
20
  if spec.respond_to?(:metadata)
20
- spec.metadata['allowed_push_host'] = 'https://rubygems.org/'
21
+ spec.metadata["allowed_push_host"] = "https://rubygems.org/"
21
22
  else
22
- raise 'RubyGems 2.0 or newer is required to protect against public gem pushes.'
23
+ raise "RubyGems 2.0 or newer is required to protect against public gem pushes."
23
24
  end
24
25
 
25
- spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
26
- spec.bindir = 'exe'
26
+ # Specify which files should be added to the gem when it is released.
27
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
28
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
29
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
30
+ end
31
+ spec.bindir = "exe"
27
32
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
28
- spec.require_paths = ['lib']
33
+ spec.require_paths = ["lib"]
29
34
 
30
- spec.add_dependency 'bunny', '~> 2.9'
31
- spec.add_dependency 'mimi-core', '~> 0.1'
32
- spec.add_dependency 'mimi-logger', '~> 0.2', '>= 0.2.3'
33
- spec.add_dependency 'msgpack', '~> 1.2'
35
+ spec.add_dependency "mimi-core", "~> 1.1"
34
36
 
35
- spec.add_development_dependency 'bundler', '~> 1.11'
36
- spec.add_development_dependency 'pry', '~> 0.10'
37
- spec.add_development_dependency 'rake', '~> 10.0'
38
- spec.add_development_dependency 'rspec', '~> 3.0'
37
+ spec.add_development_dependency "bundler", "~> 2.0"
38
+ spec.add_development_dependency "pry", "~> 0.12"
39
+ spec.add_development_dependency "rake", "~> 10.0"
40
+ spec.add_development_dependency "rspec", "~> 3.0"
39
41
  end
metadata CHANGED
@@ -1,105 +1,57 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mimi-messaging
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.9
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alex Kukushkin
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-05-23 00:00:00.000000000 Z
11
+ date: 2019-10-08 00:00:00.000000000 Z
12
12
  dependencies:
13
- - !ruby/object:Gem::Dependency
14
- name: bunny
15
- requirement: !ruby/object:Gem::Requirement
16
- requirements:
17
- - - "~>"
18
- - !ruby/object:Gem::Version
19
- version: '2.9'
20
- type: :runtime
21
- prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - "~>"
25
- - !ruby/object:Gem::Version
26
- version: '2.9'
27
13
  - !ruby/object:Gem::Dependency
28
14
  name: mimi-core
29
15
  requirement: !ruby/object:Gem::Requirement
30
16
  requirements:
31
17
  - - "~>"
32
18
  - !ruby/object:Gem::Version
33
- version: '0.1'
34
- type: :runtime
35
- prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - "~>"
39
- - !ruby/object:Gem::Version
40
- version: '0.1'
41
- - !ruby/object:Gem::Dependency
42
- name: mimi-logger
43
- requirement: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - "~>"
46
- - !ruby/object:Gem::Version
47
- version: '0.2'
48
- - - ">="
49
- - !ruby/object:Gem::Version
50
- version: 0.2.3
51
- type: :runtime
52
- prerelease: false
53
- version_requirements: !ruby/object:Gem::Requirement
54
- requirements:
55
- - - "~>"
56
- - !ruby/object:Gem::Version
57
- version: '0.2'
58
- - - ">="
59
- - !ruby/object:Gem::Version
60
- version: 0.2.3
61
- - !ruby/object:Gem::Dependency
62
- name: msgpack
63
- requirement: !ruby/object:Gem::Requirement
64
- requirements:
65
- - - "~>"
66
- - !ruby/object:Gem::Version
67
- version: '1.2'
19
+ version: '1.1'
68
20
  type: :runtime
69
21
  prerelease: false
70
22
  version_requirements: !ruby/object:Gem::Requirement
71
23
  requirements:
72
24
  - - "~>"
73
25
  - !ruby/object:Gem::Version
74
- version: '1.2'
26
+ version: '1.1'
75
27
  - !ruby/object:Gem::Dependency
76
28
  name: bundler
77
29
  requirement: !ruby/object:Gem::Requirement
78
30
  requirements:
79
31
  - - "~>"
80
32
  - !ruby/object:Gem::Version
81
- version: '1.11'
33
+ version: '2.0'
82
34
  type: :development
83
35
  prerelease: false
84
36
  version_requirements: !ruby/object:Gem::Requirement
85
37
  requirements:
86
38
  - - "~>"
87
39
  - !ruby/object:Gem::Version
88
- version: '1.11'
40
+ version: '2.0'
89
41
  - !ruby/object:Gem::Dependency
90
42
  name: pry
91
43
  requirement: !ruby/object:Gem::Requirement
92
44
  requirements:
93
45
  - - "~>"
94
46
  - !ruby/object:Gem::Version
95
- version: '0.10'
47
+ version: '0.12'
96
48
  type: :development
97
49
  prerelease: false
98
50
  version_requirements: !ruby/object:Gem::Requirement
99
51
  requirements:
100
52
  - - "~>"
101
53
  - !ruby/object:Gem::Version
102
- version: '0.10'
54
+ version: '0.12'
103
55
  - !ruby/object:Gem::Dependency
104
56
  name: rake
105
57
  requirement: !ruby/object:Gem::Requirement
@@ -128,7 +80,7 @@ dependencies:
128
80
  - - "~>"
129
81
  - !ruby/object:Gem::Version
130
82
  version: '3.0'
131
- description: Communications via RabbitMQ for mimi
83
+ description: Interservice communication via message bus for microservices
132
84
  email:
133
85
  - alex@kukushk.in
134
86
  executables: []
@@ -137,36 +89,41 @@ extra_rdoc_files: []
137
89
  files:
138
90
  - ".gitignore"
139
91
  - ".rspec"
92
+ - ".rubocop.yml"
140
93
  - ".travis.yml"
141
94
  - CODE_OF_CONDUCT.md
142
95
  - Gemfile
143
96
  - LICENSE.txt
144
97
  - README.md
145
98
  - Rakefile
99
+ - TODO.md
146
100
  - bin/console
147
101
  - bin/setup
102
+ - docs/Messaging_Layer_Properties.md
103
+ - docs/Why_HTTP_is_a_bad_choice.md
104
+ - docs/diagrams/Pattern -- Command.drawio
105
+ - docs/diagrams/Pattern -- Event direct.drawio
106
+ - docs/diagrams/Pattern -- Event with Queue.drawio
107
+ - docs/diagrams/Pattern -- Event.drawio
108
+ - docs/diagrams/Pattern -- Query.drawio
109
+ - docs/img/pattern--command.png
110
+ - docs/img/pattern--event-direct.png
111
+ - docs/img/pattern--event-using-queue.png
112
+ - docs/img/pattern--event.png
113
+ - docs/img/pattern--query.png
114
+ - examples/basic_event_listener.rb
115
+ - examples/basic_request_processor.rb
116
+ - examples/using_messaging_low.rb
117
+ - examples/using_pure_adapter.rb
148
118
  - lib/mimi/messaging.rb
149
- - lib/mimi/messaging/connection.rb
119
+ - lib/mimi/messaging/adapters.rb
120
+ - lib/mimi/messaging/adapters/base.rb
121
+ - lib/mimi/messaging/adapters/memory.rb
122
+ - lib/mimi/messaging/adapters/test.rb
150
123
  - lib/mimi/messaging/errors.rb
151
- - lib/mimi/messaging/listener.rb
124
+ - lib/mimi/messaging/json_serializer.rb
152
125
  - lib/mimi/messaging/message.rb
153
- - lib/mimi/messaging/mock.rb
154
- - lib/mimi/messaging/mock/connection.rb
155
- - lib/mimi/messaging/mock/request.rb
156
- - lib/mimi/messaging/mock/request_processor.rb
157
- - lib/mimi/messaging/model.rb
158
- - lib/mimi/messaging/model_provider.rb
159
- - lib/mimi/messaging/msgpack/msgpack_ext.rb
160
- - lib/mimi/messaging/msgpack/type_packer.rb
161
- - lib/mimi/messaging/notification.rb
162
- - lib/mimi/messaging/provider.rb
163
- - lib/mimi/messaging/request.rb
164
- - lib/mimi/messaging/request_processor.rb
165
- - lib/mimi/messaging/request_processor/context.rb
166
- - lib/mimi/messaging/request_processor/dsl.rb
167
126
  - lib/mimi/messaging/version.rb
168
- - lib/tasks/console_ext.rake
169
- - lib/tasks/console_helpers.rb
170
127
  - mimi-messaging.gemspec
171
128
  homepage: https://github.com/kukushkin/mimi-messaging
172
129
  licenses:
@@ -189,8 +146,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
189
146
  version: '0'
190
147
  requirements: []
191
148
  rubyforge_project:
192
- rubygems_version: 2.6.14.1
149
+ rubygems_version: 2.6.14.4
193
150
  signing_key:
194
151
  specification_version: 4
195
- summary: Communications via RabbitMQ for mimi
152
+ summary: Interservice communication via message bus for microservices
196
153
  test_files: []
@@ -1,181 +0,0 @@
1
- require 'bunny'
2
-
3
- module Mimi
4
- module Messaging
5
- class Connection
6
- attr_reader :queue_prefix
7
-
8
- # Creates a Connection with given connection params
9
- #
10
- # @param params [Hash] Connection params as accepted by Bunny
11
- # @param params[:queue_prefix] [String] (optional) Use this connection for all communication
12
- # related to queues, having names starting with given
13
- # prefix
14
- #
15
- def initialize(params = {})
16
- @queue_prefix = params[:queue_prefix]
17
- @channel_pool = {}
18
- bunny_params = {
19
- host: params[:mq_host],
20
- port: params[:mq_port],
21
- username: params[:mq_username],
22
- password: params[:mq_password],
23
- vhost: params[:mq_vhost]
24
- }
25
- @connection = Bunny.new(bunny_params)
26
- end
27
-
28
- # Starts the connection, opening actual connection to RabbitMQ
29
- #
30
- def start
31
- @connection.start
32
- end
33
-
34
- # Stops the connection
35
- #
36
- def stop
37
- @connection.close
38
- @channel_pool = {}
39
- end
40
-
41
- def started?
42
- @connection.status == :open
43
- end
44
-
45
- def channel
46
- raise ConnectionError unless started?
47
- @channel_pool[Thread.current.object_id] ||= create_channel
48
- end
49
-
50
- def create_channel(opts = {})
51
- Channel.new(@connection, opts)
52
- end
53
-
54
- def reply_queue
55
- raise ConnectionError unless started?
56
- channel.reply_queue
57
- end
58
-
59
- def post(queue_name, raw_message, params = {})
60
- channel.post(queue_name, raw_message, params)
61
- end
62
-
63
- def get(queue_name, raw_message, params = {})
64
- channel.get(queue_name, raw_message, params)
65
- end
66
-
67
- def broadcast(queue_name, raw_message, params = {})
68
- channel.broadcast(queue_name, raw_message, params)
69
- end
70
-
71
- class Channel
72
- attr_reader :options, :connection
73
-
74
- DEFAULT_OPTIONS = {
75
- concurrency: 1
76
- }
77
- DEFAULT_GET_TIMEOUT = 60 # seconds
78
-
79
- def initialize(connection, opts = {})
80
- @connection = connection
81
- @options = DEFAULT_OPTIONS.merge(opts)
82
- @channel = @connection.create_channel(nil, options[:concurrency])
83
- @mutex = Mutex.new
84
- end
85
-
86
- def create_queue(name, opts = {})
87
- @channel.queue(name, opts)
88
- end
89
-
90
- def reply_queue
91
- @reply_queue ||= create_queue('', exclusive: true)
92
- end
93
-
94
- def ack(tag)
95
- @channel.ack(tag)
96
- end
97
-
98
- def fanout(name)
99
- @channel.fanout(name)
100
- end
101
-
102
- def active?
103
- @channel && @channel.active
104
- end
105
-
106
- # Sends a raw RabbitMQ message to a given direct exchange
107
- #
108
- # @param queue_name [String] Queue name to send the message to
109
- # @param raw_message [String]
110
- # @param params [Hash] Message params (metadata)
111
- #
112
- def post(queue_name, raw_message, params = {})
113
- x = @channel.default_exchange
114
- params = { routing_key: queue_name }.merge(params.dup)
115
- publish(x, raw_message, params)
116
- end
117
-
118
- # Sends a raw RabbitMQ message to a given direct exchange and listens for response
119
- #
120
- # @param queue_name [String] Queue name to send the message to
121
- # @param raw_message [String]
122
- # @param params [Hash] Message params (metadata)
123
- #
124
- # @param params[:timeout] [Integer] (optional) Timeout in seconds
125
- #
126
- # @return [nil,Array]
127
- #
128
- def get(queue_name, raw_message, params = {})
129
- correlation_id = Time.now.utc.to_f.to_s
130
- params = params.dup.merge(
131
- reply_to: reply_queue.name,
132
- correlation_id: correlation_id
133
- )
134
- post(queue_name, raw_message, params)
135
- response = nil
136
- begin
137
- Timeout.timeout(params[:timeout] || DEFAULT_GET_TIMEOUT) do
138
- loop do
139
- d, m, p = reply_queue.pop
140
- next if d && m.correlation_id != correlation_id
141
- response = [d, m, p] if d
142
- break if response
143
- sleep 0.001 # s
144
- end
145
- end
146
- rescue Timeout::Error
147
- # respond with nil
148
- end
149
- response
150
- end
151
-
152
- # Sends a raw RabbitMQ message to a given fanout exchange
153
- #
154
- # @param fanout_name [String] Fanout exchange name to send the message to
155
- # @param raw_message [String]
156
- # @param params [Hash] Message params (metadata)
157
- #
158
- def broadcast(fanout_name, raw_message, params = {})
159
- x = @channel.fanout(fanout_name)
160
- publish(x, raw_message, params)
161
- end
162
-
163
- private
164
-
165
- def publish(exchange, raw_message, params = {})
166
- # HACK: Connection-level mutex reduces throughoutput, hopefully improves stability (ku)
167
- @mutex.synchronize do
168
- # TODO: may be make publishing an atomic operation using a separate thread? (ku)
169
- exchange.publish(raw_message, params)
170
- end
171
- rescue StandardError => e
172
- # Raising fatal error:
173
- unless Thread.main == Thread.current
174
- Thread.main.raise ConnectionError, "failed to publish message in a child thread: #{e}"
175
- end
176
- raise ConnectionError, "failed to publish message: #{e}"
177
- end
178
- end # class Channel
179
- end # class Connection
180
- end # module Messaging
181
- end # module Mimi