liebre 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +51 -0
  3. data/Gemfile +4 -0
  4. data/Gemfile.lock +47 -0
  5. data/LICENSE +22 -0
  6. data/README.md +268 -0
  7. data/lib/liebre.rb +24 -0
  8. data/lib/liebre/common.rb +7 -0
  9. data/lib/liebre/common/utils.rb +24 -0
  10. data/lib/liebre/config.rb +48 -0
  11. data/lib/liebre/connection_manager.rb +64 -0
  12. data/lib/liebre/publisher.rb +88 -0
  13. data/lib/liebre/runner.rb +59 -0
  14. data/lib/liebre/runner/consumers.rb +36 -0
  15. data/lib/liebre/runner/starter.rb +40 -0
  16. data/lib/liebre/runner/starter/consumer.rb +91 -0
  17. data/lib/liebre/runner/starter/consumer/handler.rb +35 -0
  18. data/lib/liebre/runner/starter/resources.rb +39 -0
  19. data/lib/liebre/runner/starter/resources/queue_builder.rb +58 -0
  20. data/lib/liebre/runner/starter/rpc.rb +45 -0
  21. data/lib/liebre/tasks.rb +12 -0
  22. data/lib/liebre/version.rb +5 -0
  23. data/liebre.gemspec +26 -0
  24. data/spec/config/liebre.yml +47 -0
  25. data/spec/config/rabbitmq.yml +35 -0
  26. data/spec/integration_spec.rb +73 -0
  27. data/spec/liebre/config_spec.rb +62 -0
  28. data/spec/liebre/connection_manager_spec.rb +40 -0
  29. data/spec/liebre/publisher_spec.rb +86 -0
  30. data/spec/liebre/runner/consumers_spec.rb +59 -0
  31. data/spec/liebre/runner/starter/consumer_spec.rb +140 -0
  32. data/spec/liebre/runner/starter/resources/queue_builder_spec.rb +69 -0
  33. data/spec/liebre/runner/starter/resources_spec.rb +36 -0
  34. data/spec/liebre/runner/starter/rpc_spec.rb +92 -0
  35. data/spec/liebre/runner/starter_spec.rb +59 -0
  36. data/spec/liebre/runner_spec.rb +50 -0
  37. data/spec/spec_helper.rb +23 -0
  38. 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
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in liebre.gemspec
4
+ gemspec
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,7 @@
1
+ module Liebre
2
+ module Common
3
+
4
+ autoload :Utils, 'liebre/common/utils'
5
+
6
+ end
7
+ 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