mimi-messaging 0.1.12 → 1.0.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.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.rubocop.yml +66 -0
- data/README.md +68 -3
- data/TODO.md +8 -0
- data/docs/Messaging_Layer_Properties.md +141 -0
- data/docs/Why_HTTP_is_a_bad_choice.md +20 -0
- data/docs/diagrams/Pattern -- Command.drawio +1 -0
- data/docs/diagrams/Pattern -- Event direct.drawio +1 -0
- data/docs/diagrams/Pattern -- Event with Queue.drawio +1 -0
- data/docs/diagrams/Pattern -- Event.drawio +1 -0
- data/docs/diagrams/Pattern -- Query.drawio +1 -0
- data/docs/img/pattern--command.png +0 -0
- data/docs/img/pattern--event-direct.png +0 -0
- data/docs/img/pattern--event-using-queue.png +0 -0
- data/docs/img/pattern--event.png +0 -0
- data/docs/img/pattern--query.png +0 -0
- data/examples/basic_event_listener.rb +35 -0
- data/examples/basic_request_processor.rb +38 -0
- data/examples/using_messaging_low.rb +59 -0
- data/examples/using_pure_adapter.rb +62 -0
- data/lib/mimi/messaging.rb +428 -92
- data/lib/mimi/messaging/adapters.rb +22 -0
- data/lib/mimi/messaging/adapters/base.rb +233 -0
- data/lib/mimi/messaging/adapters/memory.rb +119 -0
- data/lib/mimi/messaging/adapters/test.rb +50 -0
- data/lib/mimi/messaging/errors.rb +24 -12
- data/lib/mimi/messaging/json_serializer.rb +45 -0
- data/lib/mimi/messaging/version.rb +3 -1
- data/mimi-messaging.gemspec +25 -23
- metadata +34 -78
- data/lib/mimi/messaging/connection.rb +0 -182
- data/lib/mimi/messaging/listener.rb +0 -72
- data/lib/mimi/messaging/message.rb +0 -74
- data/lib/mimi/messaging/mock.rb +0 -13
- data/lib/mimi/messaging/mock/connection.rb +0 -153
- data/lib/mimi/messaging/mock/request.rb +0 -19
- data/lib/mimi/messaging/mock/request_processor.rb +0 -92
- data/lib/mimi/messaging/model.rb +0 -27
- data/lib/mimi/messaging/model_provider.rb +0 -100
- data/lib/mimi/messaging/msgpack/msgpack_ext.rb +0 -14
- data/lib/mimi/messaging/msgpack/type_packer.rb +0 -104
- data/lib/mimi/messaging/notification.rb +0 -35
- data/lib/mimi/messaging/provider.rb +0 -48
- data/lib/mimi/messaging/request.rb +0 -56
- data/lib/mimi/messaging/request_processor.rb +0 -216
- data/lib/mimi/messaging/request_processor/context.rb +0 -39
- data/lib/mimi/messaging/request_processor/dsl.rb +0 -121
- data/lib/tasks/console_ext.rake +0 -6
- data/lib/tasks/console_helpers.rb +0 -116
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 81b174d0230b57feade2b45ddf7ba624bcaae33e
|
4
|
+
data.tar.gz: 810f82256c0e7b94e7c6f5df9b2f66b87bd640fb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 326f345bb63e01400930c1127f2fecc27769bc3c3ce43e04c96abedcafc054c74b25c459acc1079a6e20249dd1b3614c67d8410be9e0b0e05dd77beb7f57aef2
|
7
|
+
data.tar.gz: 124ad7375b0465e09cbe7b23c184ff484572d0bab3f4f85e6c4da9750026d2b7ae62ff03d2078a2ece20d6d3ff8e0e7fc1b91d95a16c1fe118adbd420e336ae4
|
data/.gitignore
CHANGED
data/.rubocop.yml
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
---
|
2
|
+
|
3
|
+
require:
|
4
|
+
- rubocop-performance
|
5
|
+
|
6
|
+
AllCops:
|
7
|
+
Exclude:
|
8
|
+
- tmp/**/*
|
9
|
+
|
10
|
+
DisplayCopNames: true
|
11
|
+
DisplayStyleGuide: true
|
12
|
+
|
13
|
+
TargetRubyVersion: 2.5
|
14
|
+
|
15
|
+
Layout/ExtraSpacing:
|
16
|
+
AllowForAlignment: true
|
17
|
+
|
18
|
+
Lint/InterpolationCheck:
|
19
|
+
Enabled: false
|
20
|
+
|
21
|
+
Metrics:
|
22
|
+
Enabled: true
|
23
|
+
|
24
|
+
Metrics/LineLength:
|
25
|
+
Max: 100
|
26
|
+
|
27
|
+
Metrics/MethodLength:
|
28
|
+
Max: 25
|
29
|
+
|
30
|
+
Metrics/AbcSize:
|
31
|
+
Max: 25
|
32
|
+
|
33
|
+
Metrics/ModuleLength:
|
34
|
+
Max: 300
|
35
|
+
|
36
|
+
Naming/FileName:
|
37
|
+
Exclude:
|
38
|
+
- .simplecov
|
39
|
+
|
40
|
+
TrivialAccessors:
|
41
|
+
ExactNameMatch: true
|
42
|
+
|
43
|
+
Style/ModuleFunction:
|
44
|
+
EnforcedStyle: extend_self
|
45
|
+
|
46
|
+
# https://github.com/bbatsov/rubocop/pull/72
|
47
|
+
Style/AsciiComments:
|
48
|
+
Enabled: false
|
49
|
+
|
50
|
+
Style/StringLiterals:
|
51
|
+
EnforcedStyle: double_quotes
|
52
|
+
|
53
|
+
# Don't see why storing context information in the exception is a bad thing
|
54
|
+
Style/RaiseArgs:
|
55
|
+
Enabled: false
|
56
|
+
|
57
|
+
# Allow adding comments at `end` of classes and modules
|
58
|
+
Style/CommentedKeyword:
|
59
|
+
Enabled: false
|
60
|
+
|
61
|
+
# Allow `!!value` for casting to Boolean
|
62
|
+
Style/DoubleNegation:
|
63
|
+
Enabled: false
|
64
|
+
|
65
|
+
EmptyMethod:
|
66
|
+
EnforcedStyle: expanded
|
data/README.md
CHANGED
@@ -1,8 +1,73 @@
|
|
1
|
-
# mimi-messaging
|
1
|
+
# [WIP] mimi-messaging
|
2
2
|
|
3
|
-
|
3
|
+
Interservice communication via message bus for microservices.
|
4
4
|
|
5
|
-
|
5
|
+
## What
|
6
|
+
|
7
|
+
`mimi-messaging` is a Messaging layer -- an interservice
|
8
|
+
communication layer based on message bus, for connecting microservice applications.
|
9
|
+
|
10
|
+
* Command, Query, Event communication patterns
|
11
|
+
* "at-least-once" message delivery guarantees
|
12
|
+
* Abstract message bus interface, not bound to specific message broker implementation
|
13
|
+
|
14
|
+
See also: [Overview of Messaging layer properties](docs/Messaging_Layer_Properties.md)
|
15
|
+
|
16
|
+
## Why
|
17
|
+
|
18
|
+
[Why HTTP is a bad choice for interservice communication?](docs/Why_HTTP_is_a_bad_choice.md)
|
19
|
+
|
20
|
+
TBD: Message bus pro's and con's.
|
21
|
+
|
22
|
+
## How
|
23
|
+
|
24
|
+
Concepts:
|
25
|
+
|
26
|
+
* Command: one-to-one, send and forget
|
27
|
+
* Query: one-to-one, call and wait for response
|
28
|
+
* Event: one-to-many, broadcast
|
29
|
+
|
30
|
+
## Setup
|
31
|
+
|
32
|
+
```
|
33
|
+
gem "mimi-messaging", "~> 1.0"
|
34
|
+
gem "mimi-messaging-<ADAPTER>"
|
35
|
+
```
|
36
|
+
|
37
|
+
```
|
38
|
+
require "mimi/messaging"
|
39
|
+
require "mimi/messaging/<ADAPTER>"
|
40
|
+
|
41
|
+
Mimi::Messaging.use serializer: Mimi::Messaging::JsonSerializer
|
42
|
+
Mimi::Messaging.configure mq_adapter: "<ADAPTER>", ... # extra adapter specific options
|
43
|
+
Mimi::Messaging.start
|
44
|
+
```
|
45
|
+
|
46
|
+
## Usage
|
47
|
+
|
48
|
+
```
|
49
|
+
response = Mimi::Messaging.query("orders/show", id: 123)
|
50
|
+
```
|
51
|
+
|
52
|
+
## Adapters
|
53
|
+
|
54
|
+
`mimi-messaging` is not bound to a specific message broker implementation like RabbitMQ or Kafka. It interacts with a message broker using an adapter interface and
|
55
|
+
there are several available adapters:
|
56
|
+
|
57
|
+
* [Kafka](https://github.com/kukushkin/mimi-messaging-kafka)
|
58
|
+
* RabbitMQ (TBD)
|
59
|
+
* NATS (TBD)
|
60
|
+
* Amazon SQS/SNS
|
61
|
+
* in-memory (single process)
|
62
|
+
|
63
|
+
## Designing apps
|
64
|
+
|
65
|
+
|
66
|
+
There are only two hard problems in distributed systems:
|
67
|
+
|
68
|
+
2. Exactly-once delivery
|
69
|
+
1. Guaranteed order of messages
|
70
|
+
2. Exactly-once delivery
|
6
71
|
|
7
72
|
|
8
73
|
## License
|
data/TODO.md
ADDED
@@ -0,0 +1,8 @@
|
|
1
|
+
# TODO
|
2
|
+
|
3
|
+
* Terminology:
|
4
|
+
* what is target: for command, query, event
|
5
|
+
* what is target base: for command, query, event
|
6
|
+
* event or broadcast?
|
7
|
+
* Higher level processor: Command/QueryProcessor? EventProcessor
|
8
|
+
* Higher level message for producers: Mimi::Messaging::Message, Mimi::Messaging::Event ?
|
@@ -0,0 +1,141 @@
|
|
1
|
+
# Messaging Layer Properties
|
2
|
+
|
3
|
+
## Communication Patterns
|
4
|
+
|
5
|
+
Messaging Layer provides an intersevice communucation layer based on abstracted
|
6
|
+
message bus, implementing the range of communication patterns:
|
7
|
+
|
8
|
+
* Command
|
9
|
+
* Query
|
10
|
+
* Event
|
11
|
+
|
12
|
+
### Command
|
13
|
+
|
14
|
+

|
15
|
+
* one-to-one, send and forget
|
16
|
+
|
17
|
+
*Command* is a communication pattern where application A (producer) asynchronously
|
18
|
+
sends a message to a queue, from which application B (consumer) receives the message.
|
19
|
+
|
20
|
+
In this case the application A sends the message and continues the execution immediately
|
21
|
+
after the message has been accepted by the Messaging Layer.
|
22
|
+
|
23
|
+
There can be multiple instances of application B running and processing messages from
|
24
|
+
the same queue. The Messaging Layer guarantees that only one instance of application B
|
25
|
+
will receive this message.
|
26
|
+
|
27
|
+
### Query
|
28
|
+
|
29
|
+

|
30
|
+
* one-to-one, request/response
|
31
|
+
|
32
|
+
*Query* is a communication pattern where application A sends a message (request) to
|
33
|
+
a queue, from which application B receives the message, and waits for another
|
34
|
+
message (response) from B.
|
35
|
+
|
36
|
+
In this case application A sends the message and stops execution until
|
37
|
+
the response from application B is received or the timeout is fired.
|
38
|
+
|
39
|
+
This communication pattern is synchronous, and there are several things that
|
40
|
+
may go wrong during this communication: the target queue name is wrong,
|
41
|
+
the application B may be down, or the application B just could not produce a response
|
42
|
+
in time and the timeout is fired.
|
43
|
+
|
44
|
+
There can be multiple instances of application B running and processing messages from
|
45
|
+
the same queue. The Messaging Layer guarantees that only one instance of application B
|
46
|
+
will receive this message, and the response message will be delivered to the same
|
47
|
+
instance of application A, that produced the request.
|
48
|
+
|
49
|
+
|
50
|
+
### Event
|
51
|
+
|
52
|
+

|
53
|
+
* one-to-many, pub/sub
|
54
|
+
|
55
|
+
*Event* is a communication pattern where application A sends a message (event) to
|
56
|
+
a topic, to which many other applications may subscribe and listen for events.
|
57
|
+
There can be multiple instances of the same application B subscribed to this topic,
|
58
|
+
or it may be different applications B and C subscribed to the same topic.
|
59
|
+
|
60
|
+
In this case the application A sends the message and continues the execution immediately
|
61
|
+
after the message has been accepted by the Messaging Layer. The Messaging Layer
|
62
|
+
delivers the message to the topic and all the subscribed listeners, if there are any.
|
63
|
+
|
64
|
+
#### Listening for events
|
65
|
+
|
66
|
+
While producing an event is simple and it only means posting a message to a topic,
|
67
|
+
listening for events has two variants:
|
68
|
+
|
69
|
+

|
70
|
+
* Listening for events on a topic directly
|
71
|
+
|
72
|
+
An application can listen for events on a topic directly. That means that
|
73
|
+
whenever the event is published on a topic, every application instance listening for the
|
74
|
+
events directly will receive this event. If the application listening for the
|
75
|
+
events in such a way is down, it is not guaranteed that the events published while it
|
76
|
+
was offline will be delivered after it gets back online.
|
77
|
+
|
78
|
+

|
79
|
+
* Listening for events on a topic using a queue
|
80
|
+
|
81
|
+
An application can listen for events on a topic using a bound queue. That means
|
82
|
+
that every event published on the given topic will be additionally put into specified
|
83
|
+
queue, from which the message is consumed by only one instance of the application.
|
84
|
+
In this case the queue will keep the messages (events) even while the listening
|
85
|
+
applications/instances are down, and the messages will be delivered once the
|
86
|
+
application gets back online.
|
87
|
+
|
88
|
+
## Logical names for message targets
|
89
|
+
|
90
|
+
Whenever a message (command, query or event) is sent, Messaging Layer expects
|
91
|
+
a "target" for the message to be specified. This target is a logical name
|
92
|
+
that defines the destination of a message.
|
93
|
+
|
94
|
+
For commands and queries, the target of the message consists of a queue name
|
95
|
+
and a method name (e.g. `"customers/create"`).
|
96
|
+
|
97
|
+
For events, the target of the message consists of a topic name and an
|
98
|
+
event type (e.g. `"customers/created"`).
|
99
|
+
|
100
|
+
This allows to model the communication around your business domain concepts,
|
101
|
+
and not the implementation details like application or host names.
|
102
|
+
|
103
|
+
## Delivery guarantee
|
104
|
+
|
105
|
+
Messaging Layer guarantees "at-least-once" message delivery.
|
106
|
+
|
107
|
+
Once the call to `command()`, `query()`, `event()` successfully completes,
|
108
|
+
it is guaranteed that the Messaging Layer accepted the message,
|
109
|
+
and the message will eventually be delivered to the recipient.
|
110
|
+
|
111
|
+
"at-least-once" means that in certain cases the same message may be delivered
|
112
|
+
more than once, and the applications consuming the messages must be prepared to
|
113
|
+
deal with it, which in most cases means implementing idempotent message processors.
|
114
|
+
|
115
|
+
|
116
|
+
### Notes:
|
117
|
+
|
118
|
+
> `query()` method successfully returns only after the response has been received,
|
119
|
+
at which point the caller may be sure that not only the message has been accepted
|
120
|
+
by the Messaging Layer, but that it has been delivered and successfully processed
|
121
|
+
by the recepient.
|
122
|
+
|
123
|
+
> `event()` method successfully completing guarantees only that the message
|
124
|
+
will be delivered to the topic -- the message may still be lost by the listener if
|
125
|
+
it does not use a queue for keeping the messages
|
126
|
+
|
127
|
+
|
128
|
+
## Load balancing
|
129
|
+
|
130
|
+
The Messaging Layer ensures best-effort load balancing of messages in case there
|
131
|
+
are multiple message processors for the same request target (for Command and Query
|
132
|
+
processors), or multiple listeners (for Event processors with a queue).
|
133
|
+
|
134
|
+
|
135
|
+
## Ordering of messages
|
136
|
+
|
137
|
+
The Messaging Layer does NOT guarantee that the messages will be delivered
|
138
|
+
in the same order as they were produced.
|
139
|
+
|
140
|
+
|
141
|
+
--
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# Why HTTP is a bad choice for interservice communication
|
2
|
+
|
3
|
+
[WIP]
|
4
|
+
|
5
|
+
Downsides of HTTP:
|
6
|
+
* inherently synchronous
|
7
|
+
* timeouts
|
8
|
+
* retries
|
9
|
+
* one-to-one, no pub/sub
|
10
|
+
* additional work required:
|
11
|
+
* network
|
12
|
+
* service discovery
|
13
|
+
* routing
|
14
|
+
* load balancing
|
15
|
+
* authentication/authorization
|
16
|
+
|
17
|
+
|
18
|
+
Pro's of HTTP:
|
19
|
+
* synchronous communication is simple
|
20
|
+
* HTTP as technology is well known by engineers
|
@@ -0,0 +1 @@
|
|
1
|
+
<mxfile modified="2019-07-14T14:14:39.587Z" host="www.draw.io" agent="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36" etag="lgARSmjxxzsn12OMDTwz" version="10.9.6" type="google"><diagram id="y9hzfK7Ta8yHCBsTJmj-" name="Page-1">5Zbfk5owEMf/Gh7bASKoj4rae+lcp85Nbd8ysEqmgdAQT+hf32ASfuUc7c31rp0+mf2yu9l8dg04KMqqDxwX6UeWAHV8N6kctHJ833P9UP40Sq2UwA+UcOAk0U6dsCU/wURq9UgSKAeOgjEqSDEUY5bnEIuBhjlnp6HbntHhrgU+gCVsY0xt9QtJRKrUmTlWo98BOaRmZy+cqycZNs76JGWKE3bqSWjtoIgzJtQqqyKgDTzDRcVtLjxtC+OQi1sCZg+f774VafWQ4cX9fb5cpLB7p7M8YnrUB17oakVtEJxSImBb4LixT7LNDlqmIqPS8uQSl4UCvycVyL2We0JpxCjj53C02Wz8KJJ6KTj7DoMny2Dqyie6COACqoun81pmctiAZSB4LV1MgMFcj+xT17VAS2mvYUbDek4ObeYOpVxomr9B1rfILv9NshP0l5FFFtkfR5DLMV3OjnnScFs1JK6wthBO14tw7drQV5O1twleBq0/GaKd2WRb2q+CNrDQWlQhTxbNvSqtmOKyJPEQJFRE7Hrrrw3/94G2VpVux9mojZHL4nd9oxfVmF3Y2TJxqjhIrCt81AB5AHbkMVy/CAXmBxDXhs9u6I3/BQ4UC/I4LPepLuodPjEiD3LxkrMGQR1TR/XfBeNE01Eid5RIcbASyc7juudWNA7l5YLb17i5O9xgNKMqYzexLdPnD3H43w4xunGI/bccYjQPhjPhPXOIJ+EwUfhnZhjNX3SGpdl98yn37ssZrX8B</diagram></mxfile>
|
@@ -0,0 +1 @@
|
|
1
|
+
<mxfile modified="2019-07-14T14:29:20.445Z" host="www.draw.io" agent="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36" etag="UPJeEwyjqKJsfKu6Yc1A" version="10.9.6" type="google"><diagram id="y9hzfK7Ta8yHCBsTJmj-" name="Page-1">7VhNc5swEP01HNtBYIh9xNhuLp10muk07U2FjdFUSIyQY9xfX8mIT9l1mniSNM0JdqWVdt8+iV0cP86rDwIX2UeeAnU8N60cf+F4HnK9UD20ZldrAi+oFWtBUjOpU1yTX9BYGu2GpFAOJkrOqSTFUJlwxiCRAx0Wgm+H0245He5a4DVYiusEU1v7laQyq7XTJiytvwSyzpqdUTirR3LcTDaRlBlO+ban8peOHwvOZf2WVzFQDV6DS223OjLaOiaAyfsYTL98vvxeZNWXHEdXV2weZXDzroH5DtONiTg27spdg8E2IxKuC5xoeavy7PjzTOZUSUi94rKokb8lFajN5reE0phTLvbm/mq18uJY6Usp+E8YjMyDC1eNGCdASKiOhoda0BTbgOcgxU5NMQYT34RiiNbivu3SFhhV1stYo8OGKOt25Q5L9WLg/AtoZxay89eBLJo8M7LIQjb6N5GdvTBgvddK2ekzA+tbwEpekMQCV/ANSzVsCw3ECagtBC+WUbh0bcwXkyVaBedB1nNPcxZ5T4ltYGFrwQosjXQtoKSE4rJUyA+QhIrIm977N52A94GRFpXJx17YNQJTzt/0hZ6VFjuzvdTY1c5BapUdowyoAPhGJHD6HpRYrEGeYp+d0XseBgEUS3I3dPdQFs0OnzhRgbSEmQ754nsjHtRRGqN++TJaB42/7xejhWoYrIVU4vGuN63QE0qLdS0uDydi+N8S0b8nEb3nJKI/C4Y3F3ogEyfhcKHwsUQ85u/opnWDEWvrFc/KYWSXAG8kPlDXv5DbdOKe6Tb1x5/nc5F45DAKn4LEdrn1RuJDff8bix/GYm/yFCy2C9tIs2Lzg5Iyg1JT5g72bnKmg9F5P9hVqGpf/ql1YJzBqGswKkzJmukjovYBpZ/r3oEkmEZmICdpqrc52KsMuxnn8c0HQkc+4f3mAx3g7bjoPN+vCLvoU0nZ+4yLgiqoJKmzw1K9FislZgojfYQSUCdIp1Fm0CXzteauvTuOt+Roep7UKbH7rVofx+7ntL/8DQ==</diagram></mxfile>
|
@@ -0,0 +1 @@
|
|
1
|
+
<mxfile modified="2019-07-14T14:31:44.611Z" host="www.draw.io" agent="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36" etag="knmCqr-WVQHLlz4MjdX8" version="10.9.6" type="google"><diagram id="y9hzfK7Ta8yHCBsTJmj-" name="Page-1">5VnLctowFP0alu34DSx5JtOZJm2YTGl3ii2wprLlygJMv76SLYMtOUATNwG6snT1Puf43iu7Y4+i7IaCJPxMAog7lhFkHXvcsSzTsDz+EJZtYXEttzAsKQpkp71hhn7DcqS0rlAA01pHRghmKKkbfRLH0Gc1G6CUbOrdFgTXV03AEmqGmQ+wbv2GAhYW1l55LGG/hWgZliubXr9oiUDZWZ4kDUFANhWTPenYI0oIK0pRNoJYgFfiUoybPtO62xiFMTtlQO/x4fZHEmaPERjc38fDQQjnH0qY1wCv5IlHcrtsW2KwCRGDswT4or7hPHfsYcgizGsmL4I0KZBfoAzyxYYLhPGIYELz4fZ0OrVGI25PGSU/Ya1l6HYN3qKfRR5vDSmDWcUkz3YDSQQZ3fIustXty6NIoe1w3+xpc6UprDBW2oAUynI38x5LXpBw/gW0fQ3Z4XUgazrvjKypITu4TGTPDVjrWiXbe2dgbQ1YRhLka+BSsooDAdtYAHEEag3B7mTgTQwd87EzMaduO8haxnHNmtZbYutq2GqwwjgYiFyA13wM0pQjX0MSZojNK+XvgoCPrqyNM8lHXtmWlZhvfl6tVEaJ6n5YXivHPctBSlbUh8fdHgN0CdlxscGgltnojJ74MlCIAUPrej7UxKJc4QtB/GQ7wfTqerEtRQfFseWgavqizGPaSnzvKhMVuGgTceLBttItER1STXU7XF4uRO9/EaKtC3HmxRPM/Dv6tb+IvDv8CT8YZTg5EyHafbfuucwXKtHx6hN5rxXiM/v1mj3tXrXFjK1q2NQj1eWLuFGcp3rTUiVnomLFnTpGS+7UVuNzSyp2XcVtO26rKj7EbUXEv1aQFy1Dv9yef8plqzdbQ0+5+g2Kc1rIuA759QZ49evC5cFrNnw4eFN4r9EFvyqPMM/KAytysVUdnOyBHeW17v+jPEL1wFa7eUQjZc4VaviQLzyaRpxXLnxpGnaVdUzjDbII/cPCQIhk9YRRGsJUsLmG+S5JLM4iZND4VYcHInYo0MUkhkqMkyaA0TIWLwhfB3L7UIQ15AM8kA0RCgKxTGNkrcfeFkLlLjSqV6jqxx+zQbbqpb+1WKnfuUtOUJqTlRdjRvjjScDBn3mykl4vS+odoXxZ3o+lrsYSifE2f3Fgzk/KQOyLIlkUWSR3cD7k/k2QyELREsE0Ff/qLGNBSbQzy8zzWrl0DK/GZbenU9lrh0pe3f+MLHzo/peuPfkD</diagram></mxfile>
|
@@ -0,0 +1 @@
|
|
1
|
+
<mxfile modified="2019-07-14T14:31:23.619Z" host="www.draw.io" agent="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36" etag="mj5YSntAqhnDTmg4xXPi" version="10.9.6" type="google"><diagram id="y9hzfK7Ta8yHCBsTJmj-" name="Page-1">7VnLdpswEP0aL9sDEs+ljR/ZtOlpmtbJTgcUwwkgKuQY9+srgjAg+ZEmxE7irqwZvZg716OLGEAvKWYUZeEXEuB4ALSgGMDxAABdAxb/KT3rymMCs3IsaBSIQY3jKvqD65nCu4wCnHcGMkJiFmVdp0/SFPus40OUklV32B2Ju7tmaIEVx5WPYtX7KwpYWHmdOqzSf4GjRVjvrFtu1ZOgerCIJA9RQFYtF5wMoEcJYVUrKTwcl+DVuFTzpjt6Nw9GccqeMsG5/n5xm4XFdYKGl5fpaBji+aca5gcUL0XEI/G4bF1jsAojhq8y5Jf2iud5AEchS2Ju6byJ8qxC/i4qMN9sdBfFsUdiQh+nw+l0CjyP+3NGyT3u9IxMW+M9aiwivAdMGS5aLhHbDJMEM7rmQ0SvAUUogmhAE/aqSZspXGErY7UPCaIsNis3WPKGgPMfoHU/KrK6cWJkdQXZ4ftE1pGANU8MLPiolHVODCxUgGUki3wFXEqWaVDCNi6BOAC1gqA9GVoTTcV8bEz0qdkPspuyuoezOjgmtqaCrQIrToNhqQW45ccozznyHSRxEbF5q31TJuCzKaxxIfLxaKxrI+UPP28brVml2Ux7tOp5O3OQkyX18eGyxxBdYHaYbDjoKBs1o0/8M1AcIxY9dPXQtiyKHb6RiEe2q8ZBIPGgCltMassXaR1dPt9taaEKF2Uhnni0bg3LygH57ufVbYngtilRtFqxIewG0udz2DoXDsMnchi8KQ5D1+xyQn8miQ2ru5D1OhyGrsRh7Qgc1lVZ5r1P9WBKZxw4tS7TVWF25vXBfVP1QTrjDK2nMw7KjOqrPsgvHtYx6oMqgs+cxPUp8p/FvbAYgGOw2DhjFoOvq+zn7P4HAWPHSeybWTEf168lH4zEmwvoXe8tfZHYkEjsdm5xX0zifSlrcfj3EvOmTOSjXEcoumwLXXdKNWg5XfhsVaq5W9hm9CDVtkKrKrXTieAXISuLYKgfTwRvRfZdygepKh6sxPv+rof1xJuqvLAv+eC8TuU1ZPnwsosebjbf8qrhzRdROPkL</diagram></mxfile>
|
@@ -0,0 +1 @@
|
|
1
|
+
<mxfile modified="2019-07-14T14:14:30.733Z" host="www.draw.io" agent="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36" etag="VIpIcM9pChy9e7uzRAZn" version="10.9.6" type="google"><diagram id="y9hzfK7Ta8yHCBsTJmj-" name="Page-1">5VdNc5swEP01HJsBZLBzNDZ2Lp106sk07U0BGTQRiAoR4/z6SkYYhOzE8cQdd+qLtU+7+nj7kFYWmGX1ksEi/UpjRCzXjmsLzC3XdWzXF38S2TaI53oNkDAcK6cOWOFX1EYqtMIxKjVHTinhuNDBiOY5iriGQcboRndbU6LPWsAEGcAqgsREf+CYpw06abcl8TuEk7Sd2fFvm54Mts5qJ2UKY7rpQSC0wIxRyptWVs8QkeS1vDRxiyO9+4UxlPNTAiYP3+9+FWn9kMHp/X0eTFP0+EWN8gJJpTY8Vavl25aCTYo5WhUwkvZGpNkCQcozIixHNGFZNMSvcY3EXMEaEzKjhLJdOFgsFu5sJvCSM/qMtJ7AG9uix9xKuy7EOKp7kNraEtEMcbYVLm1vS/N2YG+6rHkKSnsJazGodJLsR+6oFA3F5geYdQ1mg3+T2RG4MmaBwezvConmkF1GqzyWvM0lE+9wbVA4Dqd+aJukz0ehs/A+h1p3pFM7MZnds/1XqPUMag1WUR5P5bkqrIjAssSRTiSqMX/stX9K/m88Zc1rlY6dsW2NXCz+sW/0oqTZhe2sNu5oCkpasQi9f+5xyBLE39cairVbwkzoid8CQwRy/KLfLYeyqGb4RrHY2dFDzhBCs28V1b8LhgONBwPZg4EaYoyBRObhtudWSIfy+IL313h7dtjeQKPNiJ1i95yeL2L/fxExOFHE7lWJGNx6uiacM0U88vWB/MtoGNxeVsN3i3n+EPoAb5YurtgSVqvwwB13toZtTcPjE0Xs6CIeX07F7okqdq5LxYOjGJyrYjA8ik+U8WcpbWQojaGyoHlpFlSiquG6xoQrfoVPOwepAvUtCW8vsLy5rGEJTnIpUaELJEqoQFZHWLyvpqojw3Es4wMCnxAJYPSc7Aq3Xsm13v0OiuzNj2dYh+1fiWrFVv8hdqg+s29sMPE+RS+Do0oPp+t1iT6YXWF2b8fGvXuBg/AP</diagram></mxfile>
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Base class for an event listener with DSL magic
|
4
|
+
#
|
5
|
+
# Usage:
|
6
|
+
# class HelloListener < BasicEventListener
|
7
|
+
# topic "hello", using_queue: "listener.hello"
|
8
|
+
#
|
9
|
+
# def world
|
10
|
+
# puts "hello/world event received: #{message}"
|
11
|
+
# end
|
12
|
+
# end
|
13
|
+
#
|
14
|
+
class BasicEventListener
|
15
|
+
attr_reader :message
|
16
|
+
|
17
|
+
def initialize(message, _opts = {})
|
18
|
+
@message = message
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.call_event(method_name, message, opts)
|
22
|
+
new(message, opts).send(method_name.to_sym)
|
23
|
+
end
|
24
|
+
|
25
|
+
# Subclass exposes itself by declaring the event topic that it is going to listen for,
|
26
|
+
# and an optional :using_queue parameter.
|
27
|
+
#
|
28
|
+
def self.topic(topic_name, params = {})
|
29
|
+
if params[:using_queue]
|
30
|
+
Mimi::Messaging.register_event_processor_with_queue(topic_name, params[:using_queue], self)
|
31
|
+
else
|
32
|
+
Mimi::Messaging.register_event_processor(topic_name, params[:using_queue], self)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end # class BasicEventListener
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Base class for a request (command and query) processor with DSL magic.
|
4
|
+
#
|
5
|
+
# Usage:
|
6
|
+
# class HelloProcessor < BasicRequestProcessor
|
7
|
+
# queue "hello"
|
8
|
+
#
|
9
|
+
# def world
|
10
|
+
# puts "hello/world called with the message: #{message}"
|
11
|
+
# end
|
12
|
+
# end
|
13
|
+
#
|
14
|
+
#
|
15
|
+
class BasicRequestProcessor
|
16
|
+
attr_reader :message
|
17
|
+
|
18
|
+
def initialize(message, _opts = {})
|
19
|
+
@message = message
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.call_command(method_name, message, opts)
|
23
|
+
new(message, opts).send(method_name.to_sym)
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.call_query(method_name, message, opts)
|
27
|
+
result = new(message, opts).send(method_name.to_sym)
|
28
|
+
return result if result.is_a?(Hash)
|
29
|
+
|
30
|
+
raise "#{name}##{method_name}() is expected to return a Hash, but returned #{result.class}"
|
31
|
+
end
|
32
|
+
|
33
|
+
# Subclass exposes itself by declaring the queue that is used to accept requests
|
34
|
+
#
|
35
|
+
def self.queue(queue_name)
|
36
|
+
Mimi::Messaging.register_request_processor(queue_name, self)
|
37
|
+
end
|
38
|
+
end # class BasicRequestProcessor
|
@@ -0,0 +1,59 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
#
|
4
|
+
# Using Mimi::Messaging lower-level abstraction,
|
5
|
+
# without using the adapter directly
|
6
|
+
#
|
7
|
+
|
8
|
+
require "mimi/messaging"
|
9
|
+
require "logger"
|
10
|
+
require_relative "basic_request_processor"
|
11
|
+
require_relative "basic_event_listener"
|
12
|
+
|
13
|
+
#
|
14
|
+
# An example request processor class
|
15
|
+
#
|
16
|
+
class HelloProcessor < BasicRequestProcessor
|
17
|
+
queue "hello"
|
18
|
+
|
19
|
+
def world
|
20
|
+
puts "hello/world request received: #{message}"
|
21
|
+
{ a: 1 }
|
22
|
+
end
|
23
|
+
|
24
|
+
def command
|
25
|
+
puts "hello/command request received: #{message}"
|
26
|
+
end
|
27
|
+
end # class HelloProcessor
|
28
|
+
|
29
|
+
#
|
30
|
+
# An example event listener class
|
31
|
+
#
|
32
|
+
class HelloListener < BasicEventListener
|
33
|
+
topic "hello", using_queue: "listener.hello"
|
34
|
+
|
35
|
+
def world
|
36
|
+
puts "hello/world event received: #{message}"
|
37
|
+
end
|
38
|
+
end # class HelloListener
|
39
|
+
|
40
|
+
#
|
41
|
+
Mimi::Messaging.use(
|
42
|
+
serializer: Mimi::Messaging::JsonSerializer,
|
43
|
+
logger: Logger.new(STDOUT)
|
44
|
+
)
|
45
|
+
Mimi::Messaging.configure(mq_adapter: :memory)
|
46
|
+
Mimi::Messaging.start
|
47
|
+
|
48
|
+
result = Mimi::Messaging.command("hello/world", a: 123)
|
49
|
+
puts "Response: #{result}"
|
50
|
+
puts
|
51
|
+
|
52
|
+
result = Mimi::Messaging.query("hello/world", b: 456)
|
53
|
+
puts "Response: #{result}"
|
54
|
+
puts
|
55
|
+
|
56
|
+
Mimi::Messaging.event("hello/world", c: 789)
|
57
|
+
puts
|
58
|
+
|
59
|
+
Mimi::Messaging.stop
|