mimi-messaging 0.1.12 → 1.2.2

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 +69 -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 +441 -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 +147 -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 -182
  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 -19
  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,62 @@
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # In this example we're going to use only the adapter for communication
5
+ # between several components.
6
+ #
7
+ require "mimi/messaging"
8
+
9
+ #
10
+ # Simplistic processor for command/query/event messages.
11
+ #
12
+ class HelloProcessor
13
+ def initialize(name)
14
+ @name = name
15
+ end
16
+
17
+ def to_s
18
+ "<#{@name}>"
19
+ end
20
+
21
+ def call_command(method_name, message, _opts)
22
+ puts "#{self}: COMMAND #{method_name} #{message.to_h}"
23
+ end
24
+
25
+ def call_query(method_name, message, _opts)
26
+ puts "#{self}: QUERY #{method_name} #{message.to_h}"
27
+ { b: "hello" }
28
+ end
29
+
30
+ def call_event(method_name, message, _opts)
31
+ puts "#{self}: EVENT #{method_name} #{message.to_h}"
32
+ end
33
+ end # class HelloProcessor
34
+
35
+ adapter = Mimi::Messaging::Adapters::Memory.new
36
+ adapter.register_message_serializer(Mimi::Messaging::JsonSerializer)
37
+ adapter.start
38
+
39
+ adapter.start_request_processor("hello", HelloProcessor.new("A"))
40
+ adapter.start_request_processor("hello", HelloProcessor.new("B"))
41
+ adapter.start_request_processor("hello", HelloProcessor.new("C"))
42
+
43
+ adapter.start_event_processor("hello", HelloProcessor.new("D"))
44
+ adapter.start_event_processor("hello", HelloProcessor.new("E"))
45
+ adapter.start_event_processor("hello", HelloProcessor.new("F"))
46
+
47
+ adapter.start_event_processor_with_queue("hello", "event_queue", HelloProcessor.new("G"))
48
+ adapter.start_event_processor_with_queue("hello", "event_queue", HelloProcessor.new("H"))
49
+ adapter.start_event_processor_with_queue("hello", "event_queue", HelloProcessor.new("I"))
50
+
51
+ result = adapter.command("hello/world", a: 123)
52
+ puts "Response: #{result}"
53
+ puts
54
+
55
+ result = adapter.query("hello/world", b: 456)
56
+ puts "Response: #{result}"
57
+ puts
58
+
59
+ adapter.event("hello/world", c: 789)
60
+ puts
61
+
62
+ adapter.stop
@@ -1,124 +1,473 @@
1
- require 'mimi/core'
2
- require 'mimi/logger'
1
+ # frozen_string_literal: true
2
+
3
+ require "mimi/core"
4
+ require_relative "messaging/adapters"
5
+ require_relative "messaging/errors"
6
+ require_relative "messaging/json_serializer"
7
+ require_relative "messaging/message"
8
+ require_relative "messaging/version"
3
9
 
4
10
  module Mimi
11
+ #
12
+ # Mimi::Messaging implements a messaging layer of a microservice application.
13
+ #
14
+ # Usage: [TBD]
15
+ #
5
16
  module Messaging
6
- include Mimi::Core::Module
7
- include Mimi::Logger::Instance
8
-
9
- # key in the message headers that is used to pass context id
10
- CONTEXT_ID_KEY = 'c'.freeze
11
-
12
- default_options(
13
- require_files: 'app/messaging/**/*.rb',
14
- mq_host: 'localhost',
15
- mq_port: 5672,
16
- mq_username: nil,
17
- mq_password: nil,
18
- mq_vhost: nil
19
- )
20
-
21
- def self.module_path
22
- Pathname.new(__dir__).join('..').join('..').expand_path
23
- end
24
-
25
- def self.module_manifest
26
- {
27
- mq_host: {
28
- desc: 'RabbitMQ host',
29
- default: 'localhost'
30
- },
31
- mq_port: {
32
- desc: 'RabbitMQ port',
33
- default: 5672
34
- },
35
- mq_username: {
36
- desc: 'RabbitMQ username',
37
- default: nil
38
- },
39
- mq_password: {
40
- desc: 'RabbitMQ password',
41
- default: nil
42
- }
43
- }
17
+ # Request target validation pattern:
18
+ # "[<name>.][...]<name>/<name>"
19
+ # Where <name> consists of valid identifier characters: A-Za-z0-9_
20
+ #
21
+ # Example:
22
+ # "shop.orders/list"
23
+ #
24
+ REQUEST_TARGET_REGEX = %r{^((\w+)\.)*(\w+)\/(\w+)$}.freeze
25
+
26
+ # Event target validation pattern:
27
+ # "[<name>.][...]<name>#<name>"
28
+ # Where <name> consists of valid identifier characters: A-Za-z0-9_
29
+ #
30
+ # Example:
31
+ # "shop.orders#created"
32
+ #
33
+ EVENT_TARGET_REGEX = %r{^((\w+)\.)*(\w+)\#(\w+)$}.freeze
34
+
35
+ # By default Mimi::Messaging logs at given level
36
+ DEFAULT_LOG_AT_LEVEL = :info
37
+
38
+ #
39
+ # Configure up the Messaging module
40
+ #
41
+ # Sets up Messaging layer dependencies configuration, e.g.
42
+ # configures logger, message serializer etc.
43
+ #
44
+ def self.use(options)
45
+ @serializer = options[:serializer] if options.key?(:serializer)
46
+ @logger = options[:logger] if options.key?(:logger)
44
47
  end
45
48
 
46
- def self.configure(*)
47
- super
48
- connections << Mimi::Messaging::Connection.new(module_options)
49
+ # Configure the Messaging layer
50
+ #
51
+ # Configures the adapter (type) and the adapter specific options.
52
+ #
53
+ # @param options [Hash] options passed to the adapter
54
+ # @option options [String,Symbol] :mq_adapter Adapter type, one of "memory", "test" etc
55
+ #
56
+ def self.configure(options)
57
+ raise ArgumentError, "Hash is expected as options" unless options.is_a?(Hash)
58
+ raise ConfigurationError, ":mq_adapter is expected to be set" unless options.key?(:mq_adapter)
59
+
60
+ @options = options.dup
61
+ adapter_name = options[:mq_adapter].to_s
62
+ adapter_class = Mimi::Messaging::Adapters.registered_adapters[adapter_name]
63
+ unless adapter_class
64
+ registered_adapter_names = Mimi::Messaging::Adapters.registered_adapters.keys
65
+ raise(
66
+ ConfigurationError,
67
+ "Failed to find adapter with name '#{adapter_name}', " \
68
+ " registered adapters are: #{registered_adapter_names.join(', ')}"
69
+ )
70
+ end
71
+
72
+ @adapter = adapter_class.new(@options)
73
+ raise ConfigurationError, "Message serializer is not registered" unless @serializer
74
+
75
+ @adapter.register_message_serializer(@serializer)
49
76
  end
50
77
 
51
- # @return [Array<Mimi::Messaging::Connection>]
78
+ # Returns the configured adapter
79
+ #
80
+ # @return [Mimi::Messaging::Adapter]
52
81
  #
53
- def self.connections
54
- @connections ||= []
82
+ def self.adapter
83
+ raise Error, "Mimi::Messaging adapter is not configured" unless @adapter
84
+
85
+ @adapter
55
86
  end
56
87
 
57
- # @return [Array<Class < Mimi::Messaging::RequestProcessor>]
88
+ # Returns the module configured options
89
+ #
90
+ # @return [Hash]
58
91
  #
59
- def self.request_processor_classes
60
- @request_processor_classes ||= []
92
+ def self.options
93
+ @options
61
94
  end
62
95
 
63
- # @param [Class < Mimi::Messaging::RequestProcessor]
96
+ # Starts the Messaging module
97
+ #
98
+ # Starts the adapter if it is not started yet, and registers
99
+ # the current message serializer with it. Starting the adapter opens connections
100
+ # with a message broker.
101
+ #
102
+ # Automatically starts all currently registered message processors, unless
103
+ # the :processors option is false.
64
104
  #
65
- def self.register_request_processor_class(request_processor_class)
66
- request_processor_classes << request_processor_class
105
+ # Example:
106
+ # # to only start the adapter, so that we can send messages,
107
+ # # but not process incoming messages:
108
+ # Mimi::Messaging.start(processors: false)
109
+ #
110
+ # # to start everything
111
+ # Mimi::Messaging.start
112
+ #
113
+ # @param params [Hash] additional parameters
114
+ # @option params [true,false] :adapter (default: true)
115
+ # start the adapter
116
+ # @option params [true,false] :processors (default: true)
117
+ # automatically registers message processors
118
+ #
119
+ def self.start(params = {})
120
+ adapter # ensures that adapter is configured
121
+ log("#{name} starting with adapter '#{options[:mq_adapter]}'")
122
+ params = { # defaults
123
+ adapter: true,
124
+ processors: true
125
+ }.merge(params)
126
+
127
+ if !started?(:adapter) && params[:adapter]
128
+ adapter.start
129
+ started!(:adapter)
130
+ end
131
+
132
+ if !started?(:processors) && params[:processors]
133
+ start_all_message_processors
134
+ started!(:processors)
135
+ end
136
+
137
+ true
67
138
  end
68
139
 
69
- # Selects the connection to be used for sending/receiving messages from/to given queue
140
+ # Stops the Messaging module
141
+ #
142
+ # Stops all currently registered message processors, unless :processors
143
+ # option is false.
70
144
  #
71
- # @param queue_name [String]
72
- # @return [Mimi::Messaging::Connection]
145
+ # Stops the adapter, unless :adapter option is false. Stopping the adapter
146
+ # closes connections with a message broker.
147
+ #
148
+ # Example:
149
+ # # to start everything
150
+ # Mimi::Messaging.start
151
+ #
152
+ # # to only stop the message processors, so that we can send messages
153
+ # # but not process incoming messages:
154
+ # Mimi::Messaging.stop(adapter: false, processors: true)
155
+ #
156
+ # # to stop everything
157
+ # Mimi::Messaging.stop
158
+ #
159
+ # @param params [Hash] additional parameters
160
+ # @option params [true,false] :processors (default: true)
161
+ # deregister all message processors
162
+ # @option params [true,false] :adapter (default: true)
163
+ # deregister all message processors
164
+ #
165
+ def self.stop(params = {})
166
+ params = { # defaults
167
+ adapter: true,
168
+ processors: true
169
+ }.merge(params)
170
+
171
+ if params[:processors]
172
+ stop_all_processors
173
+ started!(:processors, false)
174
+ end
175
+
176
+ if params[:adapter]
177
+ adapter.stop # TODO: stopping adapter without stopping processors? TBD
178
+ started!(:adapter, false)
179
+ end
180
+
181
+ log("#{name} stopped")
182
+ true
183
+ end
184
+
185
+ # Sends the command to the given target
186
+ #
187
+ # Example:
188
+ # Mimi::Messaging.command("users/create", name: "John Smith")
189
+ #
190
+ # @param target [String] "<queue>/<method>"
191
+ # @param message [Hash,Mimi::Messaging::Message]
192
+ # @param opts [Hash] additional adapter-specific options
193
+ #
194
+ # @return nil
195
+ #
196
+ def self.command(target, message = {}, opts = {})
197
+ raise ArgumentError, "Invalid target argument" unless REQUEST_TARGET_REGEX.match(target)
198
+ raise ArgumentError, "Invalid message, Hash or Message is expected" unless message.is_a?(Hash)
199
+ raise Error, "Failed to send command, adapter is not started" unless started?(:adapter)
200
+
201
+ adapter.command(target, Mimi::Messaging::Message.new(message), opts)
202
+ end
203
+
204
+ # Executes the query to the given target and returns response
205
+ #
206
+ # Raises Timeout::Error if the response from the target was not received in time.
207
+ #
208
+ # Example:
209
+ # result = Mimi::Messaging.query("users/find", id: 157)
210
+ #
211
+ # @param target [String] "<queue>/<method>"
212
+ # @param message [Hash,Mimi::Messaging::Message]
213
+ # @param opts [Hash] additional options, e.g. :timeout
214
+ #
215
+ # @return [Hash]
216
+ #
217
+ def self.query(target, message = {}, opts = {})
218
+ raise ArgumentError, "Invalid target argument" unless REQUEST_TARGET_REGEX.match(target)
219
+ raise ArgumentError, "Invalid message, Hash or Message is expected" unless message.is_a?(Hash)
220
+ raise Error, "Failed to send query, adapter is not started" unless started?(:adapter)
221
+
222
+ adapter.query(target, Mimi::Messaging::Message.new(message), opts)
223
+ end
224
+
225
+ # Broadcasts the event with the given target
226
+ #
227
+ # @param target [String] "<topic>#<event_type>", e.g. "customers#created"
228
+ # @param message [Hash,Mimi::Messaging::Message]
229
+ # @param opts [Hash] additional options
230
+ #
231
+ def self.event(target, message = {}, opts = {})
232
+ raise ArgumentError, "Invalid target argument" unless EVENT_TARGET_REGEX.match(target)
233
+ raise ArgumentError, "Invalid message, Hash or Message is expected" unless message.is_a?(Hash)
234
+ raise Error, "Failed to broadcast event, adapter is not started" unless started?(:adapter)
235
+
236
+ adapter.event(target, Mimi::Messaging::Message.new(message), opts)
237
+ end
238
+
239
+ # Registers the request (command/query) processor.
73
240
  #
74
- def self.connection_for(queue_name)
75
- connection_for_queue = connections.select do |c|
76
- c.queue_prefix && (
77
- (c.queue_prefix.is_a?(String) && queue_name.start_with?(c.queue_prefix)) ||
78
- (c.queue_prefix.is_a?(Array) && c.queue_prefix.any? { |qp| queue_name.start_with?(qp) })
241
+ # If the adapter and the processors are started, the processor
242
+ # will be automatically started (registered with the adapter).
243
+ #
244
+ # Processor must respond to #call_command() AND #call_query()
245
+ # which accepts 3 arguments: (method, message, opts).
246
+ #
247
+ # TBD: It must #ack! or #nack! the message.
248
+ #
249
+ # If the processor raises an error, the message will be NACK-ed and accepted again
250
+ # at a later time.
251
+ #
252
+ # @param queue_name [String] "<queue>"
253
+ # @param processor [#call_command()]
254
+ # @param opts [Hash] additional adapter-specific options
255
+ #
256
+ def self.register_request_processor(queue_name, processor, opts = {})
257
+ # validates processor
258
+ unless (
259
+ processor.respond_to?(:call_command) && processor.method(:call_command).arity >= 3 &&
260
+ processor.respond_to?(:call_query) && processor.method(:call_query).arity >= 3
261
+ )
262
+ raise(
263
+ ArgumentError,
264
+ "Invalid request processor passed to .register_request_processor(), " \
265
+ "expected to respond to #call_command(...) AND #call_query(method_name, request, opts)"
266
+ )
267
+ end
268
+
269
+ message_processor_params = {
270
+ type: :request,
271
+ queue_name: queue_name,
272
+ processor: processor,
273
+ opts: opts.dup,
274
+ started: false
275
+ }
276
+ if started?(:adapter) && started?(:processors)
277
+ start_message_processor(message_processor_params)
278
+ end
279
+ message_processors << message_processor_params
280
+ end
281
+
282
+ # Registers an event processor without a queue
283
+ #
284
+ # If the adapter and the processors are started, the processor
285
+ # will be automatically started (registered with the adapter).
286
+ #
287
+ # Processor must respond to #call_event() which accepts 3 arguments:
288
+ # (method, message, opts).
289
+ #
290
+ # TBD: It must #ack! or #nack! the message.
291
+ #
292
+ # If the processor raises an error, the message will be NACK-ed and accepted again
293
+ # at a later time.
294
+ #
295
+ # @param topic_name [String] "<topic>"
296
+ # @param processor [#call_event()]
297
+ # @param opts [Hash] additional adapter-specific options
298
+ #
299
+ def self.register_event_processor(topic_name, processor, opts = {})
300
+ # validates processor
301
+ if !processor.respond_to?(:call_event) || processor.method(:call_event).arity < 3
302
+ raise(
303
+ ArgumentError,
304
+ "Invalid event processor passed to .register_event_processor(), " \
305
+ "expected to respond to #call_event(method_name, request, opts)"
79
306
  )
80
- end.first
81
- return connection_for_queue if connection_for_queue
82
- connections.select { |c| c.queue_prefix.nil? }.first
307
+ end
308
+
309
+ message_processor_params = {
310
+ type: :event,
311
+ topic_name: topic_name,
312
+ processor: processor,
313
+ opts: opts.dup,
314
+ started: false
315
+ }
316
+ if started?(:adapter) && started?(:processors)
317
+ start_message_processor(message_processor_params)
318
+ end
319
+ message_processors << message_processor_params
320
+ end
321
+
322
+ # Registers an event processor with a queue
323
+ #
324
+ # If the adapter and the processors are started, the processor
325
+ # will be automatically started (registered with the adapter).
326
+ #
327
+ # Processor must respond to #call_event() which accepts 3 arguments:
328
+ # (method, message, opts).
329
+ #
330
+ # TBD: It must #ack! or #nack! the message.
331
+ #
332
+ # If the processor raises an error, the message will be NACK-ed and accepted again
333
+ # at a later time.
334
+ #
335
+ # @param topic_name [String] "<topic>"
336
+ # @param queue_name [String] "<queue>"
337
+ # @param processor [#call_event()]
338
+ # @param opts [Hash] additional adapter-specific options
339
+ #
340
+ def self.register_event_processor_with_queue(topic_name, queue_name, processor, opts = {})
341
+ # validates processor
342
+ if !processor.respond_to?(:call_event) || processor.method(:call_event).arity < 3
343
+ raise(
344
+ ArgumentError,
345
+ "Invalid event processor passed to .register_event_processor_with_queue(), " \
346
+ "expected to respond to #call_event(method_name, request, opts)"
347
+ )
348
+ end
349
+
350
+ message_processor_params = {
351
+ type: :event,
352
+ topic_name: topic_name,
353
+ queue_name: queue_name,
354
+ processor: processor,
355
+ opts: opts.dup,
356
+ started: false
357
+ }
358
+ if started?(:adapter) && started?(:processors)
359
+ start_message_processor(message_processor_params)
360
+ end
361
+ message_processors << message_processor_params
362
+ end
363
+
364
+ # private-ish methods below
365
+ # Not a part of the end-user API, but still accessible by other components
366
+
367
+ # Returns configured logger
368
+ #
369
+ # @return [Logger] or compatible
370
+ #
371
+ def self.logger
372
+ @logger
373
+ end
374
+
375
+ # Logs with configured logger at configured logging level
376
+ #
377
+ # @param message [String]
378
+ #
379
+ def self.log(message)
380
+ return unless logger
381
+
382
+ log_at_level = options[:mq_log_at_level] || DEFAULT_LOG_AT_LEVEL
383
+ log_at_level = log_at_level.to_sym
384
+ return if log_at_level == :none
385
+
386
+ logger.send(log_at_level, message)
387
+ end
388
+
389
+ # Returns true if the given subsystem started
390
+ #
391
+ # Example:
392
+ # started?(:adapter)
393
+ #
394
+ # @param name [Symbol]
395
+ # @return [true,false]
396
+ #
397
+ def self.started?(name)
398
+ @started ||= {}
399
+ @started[name]
83
400
  end
401
+ private_class_method :started?
84
402
 
85
- def self.post(queue_name, raw_message, params = {})
86
- connection_for(queue_name).post(queue_name, raw_message, params)
403
+ # Sets the state of the given subsystem
404
+ #
405
+ # Example:
406
+ # started!(:adapter, false)
407
+ #
408
+ # @param name [Symbol]
409
+ # @param value [true,false] (default: true)
410
+ #
411
+ def self.started!(name, value = true)
412
+ @started ||= {}
413
+ @started[name] = !!value
87
414
  end
415
+ private_class_method :started!
88
416
 
89
- def self.get(queue_name, raw_message, params = {})
90
- connection_for(queue_name).get(queue_name, raw_message, params)
417
+ # Returns the set of registered message processors
418
+ #
419
+ # @return [Array{Hash}]
420
+ #
421
+ def self.message_processors
422
+ @message_processors ||= []
91
423
  end
424
+ private_class_method :message_processors
425
+
426
+ # Starts the message processor at the configured and started adapter
427
+ #
428
+ # @param message_processor_params [Hash]
429
+ #
430
+ def self.start_message_processor(message_processor_params)
431
+ return if message_processor_params[:started] # do not start processor twice
92
432
 
93
- def self.broadcast(queue_name, raw_message, params = {})
94
- connection_for(queue_name).broadcast(queue_name, raw_message, params)
433
+ p = message_processor_params
434
+ case p[:type]
435
+ when :request
436
+ log "#{self} starting request processor #{p[:processor]}@#{p[:queue_name]}"
437
+ adapter.start_request_processor(p[:queue_name], p[:processor], p[:opts])
438
+ when :event
439
+ log "#{self} starting event processor #{p[:processor]}@#{p[:topic_name]}"
440
+ adapter.start_event_processor(p[:topic_name], p[:processor], p[:opts])
441
+ when :event_with_queue
442
+ log "#{self} starting event processor #{p[:processor]}@#{p[:topic_name]}/#{p[:queue_name]}"
443
+ adapter.start_event_processor_with_queue(
444
+ p[:topic_name], p[:queue_name], p[:processor], p[:opts]
445
+ )
446
+ else
447
+ raise "Unexpected message processor type: #{message_processor[:type].inspect}"
448
+ end
449
+ message_processor_params[:started] = true
95
450
  end
451
+ private_class_method :start_message_processor
96
452
 
97
- def self.start
98
- Mimi.require_files(module_options[:require_files]) if module_options[:require_files]
99
- connections.each(&:start)
100
- request_processor_classes.each(&:start)
101
- super
453
+ # Starts (registers) all message processors
454
+ #
455
+ def self.start_all_message_processors
456
+ message_processors.each { |p| start_message_processor(p) }
102
457
  end
458
+ private_class_method :start_all_message_processors
103
459
 
104
- def self.stop
105
- request_processor_classes.each(&:stop)
106
- connections.each(&:stop)
107
- super
460
+ # Stops (deregisters) all message processors
461
+ #
462
+ def self.stop_all_processors
463
+ log "#{self} stopping all message processors"
464
+ adapter.stop_all_processors
465
+ end
466
+ private_class_method :stop_all_processors
467
+
468
+ # Resets the internal state, private
469
+ #
470
+ def self.reset
108
471
  end
109
472
  end # module Messaging
110
473
  end # module Mimi
111
-
112
- require_relative 'messaging/version'
113
- require_relative 'messaging/errors'
114
- require_relative 'messaging/connection'
115
- require_relative 'messaging/message'
116
- require_relative 'messaging/request'
117
- require_relative 'messaging/request_processor'
118
- require_relative 'messaging/provider'
119
- require_relative 'messaging/model'
120
- require_relative 'messaging/model_provider'
121
- require_relative 'messaging/notification'
122
- require_relative 'messaging/listener'
123
- require_relative 'messaging/msgpack/type_packer'
124
- require_relative 'messaging/msgpack/msgpack_ext'