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 +4 -4
- data/README.md +3 -2
- data/lib/mimi/messaging.rb +31 -14
- data/lib/mimi/messaging/adapters/base.rb +7 -7
- data/lib/mimi/messaging/adapters/memory.rb +43 -15
- data/lib/mimi/messaging/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1cca5d45f4668e13cb9a7072fc1bdae16329f2d9
|
4
|
+
data.tar.gz: 45a1bd3e161c1072b0687ee59c6d943b6005360d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
|
data/lib/mimi/messaging.rb
CHANGED
@@ -14,14 +14,25 @@ module Mimi
|
|
14
14
|
# Usage: [TBD]
|
15
15
|
#
|
16
16
|
module Messaging
|
17
|
-
#
|
18
|
-
# "[<name>.][...]<name>/<
|
19
|
-
# Where <name> consists of
|
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
|
-
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
-
#
|
471
|
+
# Deregisters all message processors
|
457
472
|
#
|
458
|
-
def self.
|
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 [
|
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 [
|
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
|
92
|
-
# @param message [
|
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(
|
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(
|
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(
|
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
|
-
|
28
|
-
dispatch_command(target,
|
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
|
-
|
34
|
-
response_serialized = dispatch_query(target,
|
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
|
-
|
40
|
-
dispatch_event(target,
|
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
|
-
|
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,
|
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
|
|
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.
|
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-
|
11
|
+
date: 2019-10-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: mimi-core
|