mimi-messaging 1.1.0 → 1.2.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 54a536d257b3a394b605e80e1b24167e5912f785
4
- data.tar.gz: 03374246a36903692068863563ec7a111cd18b8b
3
+ metadata.gz: 1cca5d45f4668e13cb9a7072fc1bdae16329f2d9
4
+ data.tar.gz: 45a1bd3e161c1072b0687ee59c6d943b6005360d
5
5
  SHA512:
6
- metadata.gz: '0295bb31beb00e6370340e4db43bab2a145e9d463d514bcdf1eba944a171edb614133afc7384a9e1e3010b832c4ff4b547ae9a27e307efb19d4abe3acee0782d'
7
- data.tar.gz: 5e3a7f512fc58d688551c9601c26b863872dfeafaf860554796f2493ba30234045c591520c453fa973cae529069516cc19653553cf369eca7f31bc7c5ac29395
6
+ metadata.gz: 587895823e3c9fa32f3a423db9e56c7820c10aeed71de238e83b232a94b5b19c34148b546995c0a63d3c3c731183069858245736eed6aae0f473fd3d8c214ef2
7
+ data.tar.gz: fe4278d21c1ddc4e31b739d45e907292fab595d1a77192ad8057333b47c1669695fa65db53e817a82fe3ff2cb1e7e5e927b7da7c0551364d17717e4d219fb2e4
data/README.md CHANGED
@@ -57,7 +57,7 @@ there are several available adapters:
57
57
  * [Kafka](https://github.com/kukushkin/mimi-messaging-kafka)
58
58
  * RabbitMQ (TBD)
59
59
  * NATS (TBD)
60
- * Amazon SQS/SNS
60
+ * [Amazon SQS/SNS](https://github.com/kukushkin/mimi-messaging-sqs_sns)
61
61
  * in-memory (single process)
62
62
 
63
63
  ## Designing apps
@@ -65,10 +65,11 @@ there are several available adapters:
65
65
 
66
66
  There are only two hard problems in distributed systems:
67
67
 
68
+ ```
68
69
  2. Exactly-once delivery
69
70
  1. Guaranteed order of messages
70
71
  2. Exactly-once delivery
71
-
72
+ ```
72
73
 
73
74
  ## License
74
75
 
@@ -14,14 +14,25 @@ module Mimi
14
14
  # Usage: [TBD]
15
15
  #
16
16
  module Messaging
17
- # Target validation pattern:
18
- # "[<name>.][...]<name>/<name>"
19
- # Where <name> consists of valid identifier characters: A-Za-z0-9_
17
+ # Request target validation pattern:
18
+ # "[<name>.][...]<name>/<identifier>"
19
+ # Where <name> consists of characters: A-Za-z0-9_-
20
+ # and <method_name> can be any of: A-Za-z0-9_
20
21
  #
21
22
  # Example:
22
23
  # "shop.orders/list"
23
24
  #
24
- TARGET_REGEX = %r{^((\w+)\.)*(\w+)\/(\w+)$}.freeze
25
+ REQUEST_TARGET_REGEX = %r{^([\w\-]+\.)*([\w\-]+)\/(\w+)$}.freeze
26
+
27
+ # Event target validation pattern:
28
+ # "[<name>.][...]<name>#<identifier>"
29
+ # Where <name> consists of characters: A-Za-z0-9_-
30
+ # and <method_name> can be any of: A-Za-z0-9_
31
+ #
32
+ # Example:
33
+ # "shop.orders#created"
34
+ #
35
+ EVENT_TARGET_REGEX = %r{^([\w\-]+\.)*([\w\-]+)\#(\w+)$}.freeze
25
36
 
26
37
  # By default Mimi::Messaging logs at given level
27
38
  DEFAULT_LOG_AT_LEVEL = :info
@@ -179,13 +190,13 @@ module Mimi
179
190
  # Mimi::Messaging.command("users/create", name: "John Smith")
180
191
  #
181
192
  # @param target [String] "<queue>/<method>"
182
- # @param message [Hash]
193
+ # @param message [Hash,Mimi::Messaging::Message]
183
194
  # @param opts [Hash] additional adapter-specific options
184
195
  #
185
196
  # @return nil
186
197
  #
187
198
  def self.command(target, message = {}, opts = {})
188
- raise ArgumentError, "Invalid target argument" unless TARGET_REGEX.match(target)
199
+ raise ArgumentError, "Invalid target argument" unless REQUEST_TARGET_REGEX.match(target)
189
200
  raise ArgumentError, "Invalid message, Hash or Message is expected" unless message.is_a?(Hash)
190
201
  raise Error, "Failed to send command, adapter is not started" unless started?(:adapter)
191
202
 
@@ -196,6 +207,9 @@ module Mimi
196
207
  #
197
208
  # Raises Timeout::Error if the response from the target was not received in time.
198
209
  #
210
+ # Example:
211
+ # result = Mimi::Messaging.query("users/find", id: 157)
212
+ #
199
213
  # @param target [String] "<queue>/<method>"
200
214
  # @param message [Hash,Mimi::Messaging::Message]
201
215
  # @param opts [Hash] additional options, e.g. :timeout
@@ -203,7 +217,7 @@ module Mimi
203
217
  # @return [Hash]
204
218
  #
205
219
  def self.query(target, message = {}, opts = {})
206
- raise ArgumentError, "Invalid target argument" unless TARGET_REGEX.match(target)
220
+ raise ArgumentError, "Invalid target argument" unless REQUEST_TARGET_REGEX.match(target)
207
221
  raise ArgumentError, "Invalid message, Hash or Message is expected" unless message.is_a?(Hash)
208
222
  raise Error, "Failed to send query, adapter is not started" unless started?(:adapter)
209
223
 
@@ -212,12 +226,12 @@ module Mimi
212
226
 
213
227
  # Broadcasts the event with the given target
214
228
  #
215
- # @param target [String] "<topic>/<event_type>", e.g. "customers/created"
216
- # @param message [Hash]
229
+ # @param target [String] "<topic>#<event_type>", e.g. "customers#created"
230
+ # @param message [Hash,Mimi::Messaging::Message]
217
231
  # @param opts [Hash] additional options
218
232
  #
219
233
  def self.event(target, message = {}, opts = {})
220
- raise ArgumentError, "Invalid target argument" unless TARGET_REGEX.match(target)
234
+ raise ArgumentError, "Invalid target argument" unless EVENT_TARGET_REGEX.match(target)
221
235
  raise ArgumentError, "Invalid message, Hash or Message is expected" unless message.is_a?(Hash)
222
236
  raise Error, "Failed to broadcast event, adapter is not started" unless started?(:adapter)
223
237
 
@@ -438,24 +452,27 @@ module Mimi
438
452
  end
439
453
  private_class_method :start_message_processor
440
454
 
441
- # Starts (registers) all message processors
455
+ # Starts all registered message processors at the adapter
442
456
  #
443
457
  def self.start_all_message_processors
444
458
  message_processors.each { |p| start_message_processor(p) }
445
459
  end
446
460
  private_class_method :start_all_message_processors
447
461
 
448
- # Stops (deregisters) all message processors
462
+ # Stops all registered message processors at the adapter
449
463
  #
450
464
  def self.stop_all_processors
451
465
  log "#{self} stopping all message processors"
452
466
  adapter.stop_all_processors
467
+ message_processors.each { |p| p[:started] = false }
453
468
  end
454
469
  private_class_method :stop_all_processors
455
470
 
456
- # Resets the internal state, private
471
+ # Deregisters all message processors
457
472
  #
458
- def self.reset
473
+ def self.unregister_all_processors
474
+ stop_all_processors
475
+ message_processors.replace([])
459
476
  end
460
477
  end # module Messaging
461
478
  end # module Mimi
@@ -63,7 +63,7 @@ module Mimi
63
63
  # Sends the command to the given target
64
64
  #
65
65
  # @param target [String] "<queue>/<method>"
66
- # @param message [Hash]
66
+ # @param message [Mimi::Messaging::Message]
67
67
  # @param opts [Hash] additional options
68
68
  #
69
69
  # @return nil
@@ -76,7 +76,7 @@ module Mimi
76
76
  # Executes the query to the given target and returns response
77
77
  #
78
78
  # @param target [String] "<queue>/<method>"
79
- # @param message [Hash]
79
+ # @param message [Mimi::Messaging::Message]
80
80
  # @param opts [Hash] additional options, e.g. :timeout
81
81
  #
82
82
  # @return [Hash]
@@ -88,8 +88,8 @@ module Mimi
88
88
 
89
89
  # Broadcasts the event with the given target
90
90
  #
91
- # @param target [String] "<topic>/<event_type>", e.g. "customers/created"
92
- # @param message [Hash]
91
+ # @param target [String] "<topic>#<event_type>", e.g. "customers#created"
92
+ # @param message [Mimi::Messaging::Message]
93
93
  # @param opts [Hash] additional options
94
94
  #
95
95
  def event(_target, _message, _opts = {})
@@ -124,7 +124,7 @@ module Mimi
124
124
  raise(
125
125
  ArgumentError,
126
126
  "Invalid request processor passed to #{self.class}##{__method__}(), " \
127
- "expected to respond to #call_command(...) AND #call_query(method_name, request, opts)"
127
+ "expected to respond to #call_command(method_name, message, opts) AND #call_query(...)"
128
128
  )
129
129
  end
130
130
 
@@ -149,7 +149,7 @@ module Mimi
149
149
  raise(
150
150
  ArgumentError,
151
151
  "Invalid event processor passed to #{self.class}##{__method__}(), " \
152
- "expected to respond to #call_event(method_name, request, opts)"
152
+ "expected to respond to #call_event(event_type, message, opts)"
153
153
  )
154
154
  end
155
155
 
@@ -175,7 +175,7 @@ module Mimi
175
175
  raise(
176
176
  ArgumentError,
177
177
  "Invalid event processor passed to #{self.class}##{__method__}(), " \
178
- "expected to respond to #call_event(method_name, request, opts)"
178
+ "expected to respond to #call_event(event_type, message, opts)"
179
179
  )
180
180
  end
181
181
 
@@ -23,21 +23,39 @@ module Mimi
23
23
  def stop
24
24
  end
25
25
 
26
+ # Sends COMMAND to target
27
+ #
28
+ # @param target [String]
29
+ # @param message [Mimi::Messaging::Message]
30
+ # @param opts [Hash]
31
+ #
26
32
  def command(target, message, opts = {})
27
- message_serialized = serialize(message)
28
- dispatch_command(target, message_serialized, opts)
33
+ raise ArgumentError, "Message is expected" unless message.is_a?(Mimi::Messaging::Message)
34
+ dispatch_command(target, message, opts)
29
35
  nil
30
36
  end
31
37
 
38
+ # Sends QUERY to target
39
+ #
40
+ # @param target [String]
41
+ # @param message [Mimi::Messaging::Message]
42
+ # @param opts [Hash]
43
+ #
32
44
  def query(target, message, opts = {})
33
- message_serialized = serialize(message)
34
- response_serialized = dispatch_query(target, message_serialized, opts)
45
+ raise ArgumentError, "Message is expected" unless message.is_a?(Mimi::Messaging::Message)
46
+ response_serialized = dispatch_query(target, message, opts)
35
47
  deserialize(response_serialized)
36
48
  end
37
49
 
50
+ # Sends EVENT to target
51
+ #
52
+ # @param target [String]
53
+ # @param message [Mimi::Messaging::Message]
54
+ # @param opts [Hash]
55
+ #
38
56
  def event(target, message, opts = {})
39
- message_serialized = serialize(message)
40
- dispatch_event(target, message_serialized, opts)
57
+ raise ArgumentError, "Message is expected" unless message.is_a?(Mimi::Messaging::Message)
58
+ dispatch_event(target, message, opts)
41
59
  end
42
60
 
43
61
  def start_request_processor(queue_name, processor, _opts = {})
@@ -67,38 +85,48 @@ module Mimi
67
85
 
68
86
  private
69
87
 
70
- def dispatch_command(target, message_serialized, _opts = {})
88
+ # Simulates a transmitted message, following serialization/deserialization:
89
+ # message out -> message in
90
+ #
91
+ # @param message [Mimi::Messaging::Message]
92
+ # @return [Mimi::Messaging::Message]
93
+ #
94
+ def transmitted_message(message)
95
+ Mimi::Messaging::Message.new(
96
+ deserialize(serialize(message)),
97
+ message.headers
98
+ )
99
+ end
100
+
101
+ def dispatch_command(target, message, _opts = {})
71
102
  queue_name, method_name = target.split("/")
72
- message = deserialize(message_serialized)
73
103
  return unless request_processors[queue_name]
74
104
 
75
105
  # pick random processor serving the target
76
106
  processor = request_processors[queue_name].sample
77
- processor.call_command(method_name, message, {})
107
+ processor.call_command(method_name, transmitted_message(message), {})
78
108
  end
79
109
 
80
- def dispatch_query(target, message_serialized, _opts = {})
110
+ def dispatch_query(target, message, _opts = {})
81
111
  queue_name, method_name = target.split("/")
82
- message = deserialize(message_serialized)
83
112
  raise Timeout::Error unless request_processors[queue_name]
84
113
 
85
114
  # pick random processor serving the target
86
115
  processor = request_processors[queue_name].sample
87
- response = processor.call_query(method_name, message, {})
116
+ response = processor.call_query(method_name, transmitted_message(message), {})
88
117
  serialize(response)
89
118
  end
90
119
 
91
120
  def dispatch_event(target, message_serialized, _opts = {})
92
- topic_name, event_type = target.split("/")
121
+ topic_name, event_type = target.split("#")
93
122
  processors = event_processors[topic_name] || []
94
123
  processor_queues = event_processors_with_queue[topic_name] || {}
95
124
  processor_queues.values.each do |same_queue_processors|
96
125
  processors << same_queue_processors.sample
97
126
  end
98
127
 
99
- message = deserialize(message_serialized)
100
128
  processors.each do |processor|
101
- processor.call_event(event_type, message, {})
129
+ processor.call_event(event_type, transmitted_message(message), {})
102
130
  end
103
131
  end
104
132
 
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Mimi
4
4
  module Messaging
5
- VERSION = "1.1.0"
5
+ VERSION = "1.2.5"
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mimi-messaging
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0
4
+ version: 1.2.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alex Kukushkin
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-10-08 00:00:00.000000000 Z
11
+ date: 2019-10-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: mimi-core