liebre 0.1.3
Sign up to get free protection for your applications and to get access to all the features.
- 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
|