mimi-messaging 0.1.9 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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 +429 -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/message.rb +25 -65
- data/lib/mimi/messaging/version.rb +3 -1
- data/mimi-messaging.gemspec +25 -23
- metadata +34 -77
- data/lib/mimi/messaging/connection.rb +0 -181
- data/lib/mimi/messaging/listener.rb +0 -72
- 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 -18
- 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: 54a536d257b3a394b605e80e1b24167e5912f785
|
4
|
+
data.tar.gz: 03374246a36903692068863563ec7a111cd18b8b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: '0295bb31beb00e6370340e4db43bab2a145e9d463d514bcdf1eba944a171edb614133afc7384a9e1e3010b832c4ff4b547ae9a27e307efb19d4abe3acee0782d'
|
7
|
+
data.tar.gz: 5e3a7f512fc58d688551c9601c26b863872dfeafaf860554796f2493ba30234045c591520c453fa973cae529069516cc19653553cf369eca7f31bc7c5ac29395
|
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
|
+
![Command pattern diagram](./img/pattern--command.png)
|
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
|
+
![Query pattern diagram](./img/pattern--query.png)
|
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
|
+
![Event pattern diagram](./img/pattern--event.png)
|
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
|
+
![Event directly diagram](./img/pattern--event-direct.png)
|
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
|
+
![Event using a queue diagram](./img/pattern--event-using-queue.png)
|
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
|