liebre 0.1.3
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 +7 -0
- data/.gitignore +51 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +47 -0
- data/LICENSE +22 -0
- data/README.md +268 -0
- data/lib/liebre.rb +24 -0
- data/lib/liebre/common.rb +7 -0
- data/lib/liebre/common/utils.rb +24 -0
- data/lib/liebre/config.rb +48 -0
- data/lib/liebre/connection_manager.rb +64 -0
- data/lib/liebre/publisher.rb +88 -0
- data/lib/liebre/runner.rb +59 -0
- data/lib/liebre/runner/consumers.rb +36 -0
- data/lib/liebre/runner/starter.rb +40 -0
- data/lib/liebre/runner/starter/consumer.rb +91 -0
- data/lib/liebre/runner/starter/consumer/handler.rb +35 -0
- data/lib/liebre/runner/starter/resources.rb +39 -0
- data/lib/liebre/runner/starter/resources/queue_builder.rb +58 -0
- data/lib/liebre/runner/starter/rpc.rb +45 -0
- data/lib/liebre/tasks.rb +12 -0
- data/lib/liebre/version.rb +5 -0
- data/liebre.gemspec +26 -0
- data/spec/config/liebre.yml +47 -0
- data/spec/config/rabbitmq.yml +35 -0
- data/spec/integration_spec.rb +73 -0
- data/spec/liebre/config_spec.rb +62 -0
- data/spec/liebre/connection_manager_spec.rb +40 -0
- data/spec/liebre/publisher_spec.rb +86 -0
- data/spec/liebre/runner/consumers_spec.rb +59 -0
- data/spec/liebre/runner/starter/consumer_spec.rb +140 -0
- data/spec/liebre/runner/starter/resources/queue_builder_spec.rb +69 -0
- data/spec/liebre/runner/starter/resources_spec.rb +36 -0
- data/spec/liebre/runner/starter/rpc_spec.rb +92 -0
- data/spec/liebre/runner/starter_spec.rb +59 -0
- data/spec/liebre/runner_spec.rb +50 -0
- data/spec/spec_helper.rb +23 -0
- metadata +172 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: cea30bec0897de16f0f5c622dfc40dd4918e10a4
|
4
|
+
data.tar.gz: 129b44949789081686fd1331701bca94c1a498b5
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: fb2469f49b0b8583ce5b73fb20c6396b4791d395d2ad2dfc7f8d9486d8bc675a7dc2b666fe16cd5950d709bc05cf7cc1f0d9da24b6fe2eced3ef92ad71227d4d
|
7
|
+
data.tar.gz: ec76d7163561e469037e61b12ab3f2c35968fec5217b756119729e51981692fe7dc691a2d80f0c7e4d0ab1da6f5c5d3668936226cd315e7644ec7b087b4588ae
|
data/.gitignore
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
/.config
|
4
|
+
/coverage/
|
5
|
+
/InstalledFiles
|
6
|
+
/pkg/
|
7
|
+
/spec/reports/
|
8
|
+
/spec/examples.txt
|
9
|
+
/test/tmp/
|
10
|
+
/test/version_tmp/
|
11
|
+
/tmp/
|
12
|
+
|
13
|
+
# Used by dotenv library to load environment variables.
|
14
|
+
# .env
|
15
|
+
|
16
|
+
## Specific to RubyMotion:
|
17
|
+
.dat*
|
18
|
+
.repl_history
|
19
|
+
build/
|
20
|
+
*.bridgesupport
|
21
|
+
build-iPhoneOS/
|
22
|
+
build-iPhoneSimulator/
|
23
|
+
|
24
|
+
## Specific to RubyMotion (use of CocoaPods):
|
25
|
+
#
|
26
|
+
# We recommend against adding the Pods directory to your .gitignore. However
|
27
|
+
# you should judge for yourself, the pros and cons are mentioned at:
|
28
|
+
# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
|
29
|
+
#
|
30
|
+
# vendor/Pods/
|
31
|
+
|
32
|
+
## Documentation cache and generated files:
|
33
|
+
/.yardoc/
|
34
|
+
/_yardoc/
|
35
|
+
/doc/
|
36
|
+
/rdoc/
|
37
|
+
|
38
|
+
## Environment normalization:
|
39
|
+
/.bundle/
|
40
|
+
/vendor/bundle
|
41
|
+
/lib/bundler/man/
|
42
|
+
|
43
|
+
# for a library or gem, you might want to ignore these files since the code is
|
44
|
+
# intended to run in multiple environments; otherwise, check them in:
|
45
|
+
# Gemfile.lock
|
46
|
+
.ruby-version
|
47
|
+
.ruby-gemset
|
48
|
+
|
49
|
+
# unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
|
50
|
+
.rvmrc
|
51
|
+
/nbproject
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
liebre (0.1.2)
|
5
|
+
bunny (~> 2.5, >= 2.5.1)
|
6
|
+
|
7
|
+
GEM
|
8
|
+
remote: https://rubygems.org/
|
9
|
+
specs:
|
10
|
+
amq-protocol (2.0.1)
|
11
|
+
bunny (2.5.1)
|
12
|
+
amq-protocol (>= 2.0.1)
|
13
|
+
coderay (1.1.1)
|
14
|
+
diff-lcs (1.2.5)
|
15
|
+
method_source (0.8.2)
|
16
|
+
pry (0.10.4)
|
17
|
+
coderay (~> 1.1.0)
|
18
|
+
method_source (~> 0.8.1)
|
19
|
+
slop (~> 3.4)
|
20
|
+
rake (11.2.2)
|
21
|
+
rspec (3.5.0)
|
22
|
+
rspec-core (~> 3.5.0)
|
23
|
+
rspec-expectations (~> 3.5.0)
|
24
|
+
rspec-mocks (~> 3.5.0)
|
25
|
+
rspec-core (3.5.2)
|
26
|
+
rspec-support (~> 3.5.0)
|
27
|
+
rspec-expectations (3.5.0)
|
28
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
29
|
+
rspec-support (~> 3.5.0)
|
30
|
+
rspec-mocks (3.5.0)
|
31
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
32
|
+
rspec-support (~> 3.5.0)
|
33
|
+
rspec-support (3.5.0)
|
34
|
+
slop (3.6.0)
|
35
|
+
|
36
|
+
PLATFORMS
|
37
|
+
ruby
|
38
|
+
|
39
|
+
DEPENDENCIES
|
40
|
+
bundler (~> 1.6)
|
41
|
+
liebre!
|
42
|
+
pry
|
43
|
+
rake
|
44
|
+
rspec
|
45
|
+
|
46
|
+
BUNDLED WITH
|
47
|
+
1.12.5
|
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2016 jcabotc
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,268 @@
|
|
1
|
+
# Liebre
|
2
|
+
|
3
|
+
## Intro
|
4
|
+
|
5
|
+
**Liebre stands for hare in spanish.**
|
6
|
+
|
7
|
+
This is a gem that handles RabbitMQ consumers, publishers and RPCs, based on [bunny](https://github.com/ruby-amqp/bunny).
|
8
|
+
|
9
|
+
* It allows to create classes that will be invoked everytime a message it's received in its subscribed queue.
|
10
|
+
* It handles RPCs as a special Consumer where a callback message is returned to the exchange.
|
11
|
+
* You can use its Publisher to send message to an exchange.
|
12
|
+
* There is also a Publisher RPC method to send a message and wait for its response.
|
13
|
+
|
14
|
+
## Configuration
|
15
|
+
It is based on 2 config files:
|
16
|
+
|
17
|
+
* rabbitmq.yml: it contains RabbitMQ connection configurations and can be enviroment dependant (default path `config/rabbitmq.yml`), it must contain, at least the `default` connection
|
18
|
+
* without environment set:
|
19
|
+
```
|
20
|
+
default:
|
21
|
+
:host: localhost
|
22
|
+
:port: 5672
|
23
|
+
:user: guest
|
24
|
+
:pass: guest
|
25
|
+
:vhost: /
|
26
|
+
:threaded: true
|
27
|
+
:heartbeat: 2
|
28
|
+
```
|
29
|
+
* with environment set:
|
30
|
+
```
|
31
|
+
development:
|
32
|
+
default:
|
33
|
+
:host: localhost
|
34
|
+
:port: 5672
|
35
|
+
:user: guest
|
36
|
+
:pass: guest
|
37
|
+
:vhost: /
|
38
|
+
:threaded: true
|
39
|
+
:heartbeat: 2
|
40
|
+
rpc:
|
41
|
+
:host: localhost
|
42
|
+
:port: 5672
|
43
|
+
:user: guest
|
44
|
+
:pass: guest
|
45
|
+
:vhost: rpc
|
46
|
+
:threaded: true
|
47
|
+
:heartbeat: 2
|
48
|
+
test:
|
49
|
+
default:
|
50
|
+
:host: localhost
|
51
|
+
:port: 5672
|
52
|
+
:user: guest
|
53
|
+
:pass: guest
|
54
|
+
:vhost: /
|
55
|
+
:threaded: true
|
56
|
+
:heartbeat: 2
|
57
|
+
rpc:
|
58
|
+
:host: localhost
|
59
|
+
:port: 5672
|
60
|
+
:user: guest
|
61
|
+
:pass: guest
|
62
|
+
:vhost: rpc
|
63
|
+
:threaded: true
|
64
|
+
:heartbeat: 2
|
65
|
+
|
66
|
+
production:
|
67
|
+
...
|
68
|
+
```
|
69
|
+
|
70
|
+
* liebre.yml (default path `config/liebre.yml`)
|
71
|
+
```
|
72
|
+
rpc_request_timeout: 5
|
73
|
+
|
74
|
+
consumers:
|
75
|
+
some_consumer:
|
76
|
+
class_name: MyConsumer
|
77
|
+
rpc: false
|
78
|
+
pool_size: 1
|
79
|
+
num_threads: 4
|
80
|
+
exchange:
|
81
|
+
name: "consumer_exchange"
|
82
|
+
type: "fanout"
|
83
|
+
opts:
|
84
|
+
durable: false
|
85
|
+
queue:
|
86
|
+
name: "consumer_queue"
|
87
|
+
opts:
|
88
|
+
durable: false
|
89
|
+
bind:
|
90
|
+
routing_key: #key a string or an array of strings
|
91
|
+
- key_1
|
92
|
+
- key_2
|
93
|
+
|
94
|
+
some_rpc:
|
95
|
+
class_name: MyRPC
|
96
|
+
rpc: true
|
97
|
+
connection_name: rpc
|
98
|
+
pool_size: 1
|
99
|
+
exchange:
|
100
|
+
name: "rpc_exchange"
|
101
|
+
type: "fanout"
|
102
|
+
opts:
|
103
|
+
durable: false
|
104
|
+
queue:
|
105
|
+
name: "rpc_queue"
|
106
|
+
opts:
|
107
|
+
durable: false
|
108
|
+
|
109
|
+
publishers:
|
110
|
+
some_publisher:
|
111
|
+
exchange:
|
112
|
+
name: "consumer_exchange"
|
113
|
+
type: "fanout"
|
114
|
+
opts:
|
115
|
+
durable: false
|
116
|
+
rpc_publisher:
|
117
|
+
connection_name: rpc
|
118
|
+
exchange:
|
119
|
+
name: "rpc_exchange"
|
120
|
+
type: "fanout"
|
121
|
+
opts:
|
122
|
+
durable: false
|
123
|
+
```
|
124
|
+
|
125
|
+
### Consumers
|
126
|
+
|
127
|
+
An entry for each consumer in your app, consumer options:
|
128
|
+
* `class_name` (mandatory): The class that will be invoked everytime a message is received
|
129
|
+
* `rpc` is a flag to specify the consumer behaviour (default false)
|
130
|
+
* `connection_name`: the name of the connection to use (default `default`)
|
131
|
+
* `pool_size` of the connection channel (default 1)
|
132
|
+
* `num_threads`: number of consumers of the queue (default 1)
|
133
|
+
* `exchange` a hash of options:
|
134
|
+
* `name`: the exchange name
|
135
|
+
* `type`: the exchange type (fanout, direct or topic)
|
136
|
+
* `opts`: options hash to pass to bunny exchange function
|
137
|
+
* `queue` a hash of options:
|
138
|
+
* `name`: the queue name
|
139
|
+
* `opts`: options hash to pass to bunny queue function
|
140
|
+
* `bind` a hash of options (optional):
|
141
|
+
* `routing_key`: the binding routing key, it can be a single string or an array of strings
|
142
|
+
|
143
|
+
### Publishers
|
144
|
+
|
145
|
+
An entry for each exchange you want to publish to, options:
|
146
|
+
* `connection_name`: the name of the connection to use (default `default`)
|
147
|
+
* `exchange` a hash of options:
|
148
|
+
* `name`: the exchange name
|
149
|
+
* `type`: the exchange type (fanout, direct or topic)
|
150
|
+
* `opts`: options hash to pass to bunny exchange function
|
151
|
+
|
152
|
+
### Other configurations
|
153
|
+
|
154
|
+
`rpc_request_timeout`: set the timeout for an RPC request
|
155
|
+
|
156
|
+
### Change default paths and set env and Logger
|
157
|
+
|
158
|
+
You can change these defaults in an initializer with something like:
|
159
|
+
|
160
|
+
```
|
161
|
+
Liebre::Config.config_path = "your/custom/path"
|
162
|
+
Liebre::Config.connection_path = "your/custom/path"
|
163
|
+
|
164
|
+
Liebre::Config.env = "production"
|
165
|
+
Liebre::Config.logger = Logger.new(...)
|
166
|
+
|
167
|
+
```
|
168
|
+
|
169
|
+
## Usage
|
170
|
+
|
171
|
+
There are 2 different consumer usages: `Consumer` and `RPC`.
|
172
|
+
|
173
|
+
### Consumer
|
174
|
+
|
175
|
+
You only need to create a class with this simple interface:
|
176
|
+
|
177
|
+
```
|
178
|
+
class MyConsumer
|
179
|
+
|
180
|
+
def initialize payload, meta
|
181
|
+
@payload = payload #the content of the message
|
182
|
+
@meta = meta #the meta information (also called properties)
|
183
|
+
end
|
184
|
+
|
185
|
+
def call
|
186
|
+
#do your stuff here
|
187
|
+
#return :ack to anknowledge the message,
|
188
|
+
#return :reject to requeue it
|
189
|
+
#or return :error to send it to the dead-letter-exchange
|
190
|
+
:ack
|
191
|
+
end
|
192
|
+
|
193
|
+
end
|
194
|
+
```
|
195
|
+
|
196
|
+
Every time a message is received, a new instance of this class will be created.
|
197
|
+
|
198
|
+
### RPC
|
199
|
+
|
200
|
+
You only need to create a class with this simple interface:
|
201
|
+
|
202
|
+
```
|
203
|
+
class MyRPC
|
204
|
+
|
205
|
+
def initialize payload, meta, callback
|
206
|
+
@payload = payload #the content of the message
|
207
|
+
@meta = meta #the meta information (also called properties)
|
208
|
+
@callback = callback #a Proc that will publish an answer
|
209
|
+
end
|
210
|
+
|
211
|
+
def call
|
212
|
+
#do your stuff here
|
213
|
+
@callback.call("your response")
|
214
|
+
end
|
215
|
+
|
216
|
+
end
|
217
|
+
```
|
218
|
+
|
219
|
+
Every time a message is received, a new instance of this class will be created.
|
220
|
+
|
221
|
+
There are 2 ways to publish a message: `enqueue` and `enqueue_and_wait`.
|
222
|
+
|
223
|
+
### `enqueue`
|
224
|
+
|
225
|
+
```
|
226
|
+
publisher = Liebre::Publisher.new("some_publisher_name")
|
227
|
+
|
228
|
+
publisher.enqueue "hello", :routing_key => "consumer_queue"
|
229
|
+
|
230
|
+
publisher.enqueue "bye", :routing_key => "consumer_queue"
|
231
|
+
|
232
|
+
```
|
233
|
+
|
234
|
+
### `enqueue_and_wait` (alias `rpc`)
|
235
|
+
|
236
|
+
```
|
237
|
+
rpc_publisher = Liebre::Publisher.new("rpc_publisher")
|
238
|
+
|
239
|
+
response = publisher.enqueue_and_wait "hello", :routing_key => "consumer_queue"
|
240
|
+
|
241
|
+
another_response = publisher.rpc "bye", :routing_key => "consumer_queue"
|
242
|
+
|
243
|
+
```
|
244
|
+
|
245
|
+
### Installation and Execution
|
246
|
+
|
247
|
+
Add the following to your Gemfile:
|
248
|
+
```
|
249
|
+
gem "liebre", ">~ 0.1"
|
250
|
+
```
|
251
|
+
|
252
|
+
In your Raketask add:
|
253
|
+
|
254
|
+
```
|
255
|
+
require "liebre/tasks"
|
256
|
+
```
|
257
|
+
|
258
|
+
Then you just need to run:
|
259
|
+
```
|
260
|
+
rake liebre:run
|
261
|
+
```
|
262
|
+
|
263
|
+
Alternative way:
|
264
|
+
```
|
265
|
+
require 'liebre'
|
266
|
+
|
267
|
+
Liebre::Runner.new.start
|
268
|
+
```
|
data/lib/liebre.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
require "liebre/version"
|
2
|
+
require "bunny"
|
3
|
+
|
4
|
+
module Liebre
|
5
|
+
|
6
|
+
autoload :Common, 'liebre/common'
|
7
|
+
autoload :Config, 'liebre/config'
|
8
|
+
autoload :ConnectionManager, 'liebre/connection_manager'
|
9
|
+
autoload :Publisher, 'liebre/publisher'
|
10
|
+
autoload :Runner, 'liebre/runner'
|
11
|
+
|
12
|
+
def self.config
|
13
|
+
@config ||= Config.new
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.env
|
17
|
+
Config.env
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.logger
|
21
|
+
Config.logger
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Liebre
|
2
|
+
module Common
|
3
|
+
module Utils
|
4
|
+
def self.create_exchange channel, config
|
5
|
+
exchange_name = config.fetch "name"
|
6
|
+
|
7
|
+
type = config.fetch("type")
|
8
|
+
opts = config.fetch("opts", {})
|
9
|
+
exchange_opts = symbolize_keys(opts.merge("type" => type))
|
10
|
+
|
11
|
+
channel.exchange exchange_name, exchange_opts
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.symbolize_keys hash
|
15
|
+
result = {}
|
16
|
+
hash.each do |k, v|
|
17
|
+
result[k.to_sym] = v.is_a?(Hash) ? symbolize_keys(v) : v
|
18
|
+
end
|
19
|
+
result
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
end
|