rt-tackle 1.0 → 1.1.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/README.md +73 -6
- data/lib/tackle/consumer/params.rb +6 -0
- data/lib/tackle/consumer.rb +18 -8
- data/lib/tackle/version.rb +1 -1
- data/lib/tackle.rb +3 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2b957a205e2dd52731c5a94cd871aa56e2f6a3e8
|
4
|
+
data.tar.gz: 2457adef2b1e810c72a5eee49706ce9ea5b5d483
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bf96bfc2e3acde0a9b3351c602136322063e44344ecb01e46fd2d9e5732508db36807eb562dc79232b767ee40a406d87779f6c30bd73d439fb4d63cfaa859917
|
7
|
+
data.tar.gz: 88220350832e5214e7120089828ebb4d174b420247e89a29b8b5c0a2c092d353036ec6de66899511951dc9b21d5bd4eeb3f13b7a31766c87953e404f20bd6a90
|
data/README.md
CHANGED
@@ -5,6 +5,15 @@
|
|
5
5
|
Tackles the problem of processing asynchronous jobs in reliable manner
|
6
6
|
by relying on RabbitMQ.
|
7
7
|
|
8
|
+
You should also take a look at [Elixir Tackle](https://github.com/renderedtext/ex-tackle).
|
9
|
+
|
10
|
+
## Why should I use tackle?
|
11
|
+
|
12
|
+
- It is ideal for fast microservice prototyping
|
13
|
+
- It uses sane defaults for queue and exchange creation
|
14
|
+
- It retries messages that fail to be processed
|
15
|
+
- It stores unprocessed messages into a __dead__ queue for later inspection
|
16
|
+
|
8
17
|
## Installation
|
9
18
|
|
10
19
|
Add this line to your application's Gemfile:
|
@@ -13,9 +22,7 @@ Add this line to your application's Gemfile:
|
|
13
22
|
gem "rt-tackle", :require => "tackle"
|
14
23
|
```
|
15
24
|
|
16
|
-
##
|
17
|
-
|
18
|
-
### Publishing a message
|
25
|
+
## Publishing messages
|
19
26
|
|
20
27
|
With tackle, you can publish a message to an AMQP exchange. For example, to
|
21
28
|
publish `"Hello World!"` do the following:
|
@@ -44,10 +51,12 @@ options = {
|
|
44
51
|
Tackle.publish("Hello World!", options)
|
45
52
|
```
|
46
53
|
|
47
|
-
|
54
|
+
## Consume messages
|
48
55
|
|
49
56
|
Tackle enables you to connect to an AMQP exchange and consume messages from it.
|
50
57
|
|
58
|
+

|
59
|
+
|
51
60
|
```ruby
|
52
61
|
require "tackle"
|
53
62
|
|
@@ -80,8 +89,6 @@ The above code snippet creates the following AMQP resources:
|
|
80
89
|
where your service can't consume the message, tackle will store them in a
|
81
90
|
dedicated dead queue. You can consume this messages manually.
|
82
91
|
|
83
|
-

|
84
|
-
|
85
92
|
You can pass additional configuration to tackle in order to control the number
|
86
93
|
of retries, and the delay between each retry.
|
87
94
|
|
@@ -125,6 +132,66 @@ Tackle.consume(options) do |message|
|
|
125
132
|
end
|
126
133
|
```
|
127
134
|
|
135
|
+
## Manually ack-ing messages
|
136
|
+
|
137
|
+
By default, Tackle assumes that a message was successfully processed if no
|
138
|
+
exceptions were raised in the consume block. This behaviour is well suited for
|
139
|
+
handling unknown exceptions.
|
140
|
+
|
141
|
+
Sometimes however, we want to send a message to the retry queue without raising
|
142
|
+
an exception (and polluting our exception tracker with false positives).
|
143
|
+
|
144
|
+
For this purpose, tackle can be configured to consume messages in a "manual ack"
|
145
|
+
fashion. Pass `:manual_ack => true` to the consumer to activate the manual_ack
|
146
|
+
mode.
|
147
|
+
|
148
|
+
```ruby
|
149
|
+
require "tackle"
|
150
|
+
|
151
|
+
options = {
|
152
|
+
:url => "amqp://localhost",
|
153
|
+
:exchange => "users",
|
154
|
+
:routing_key => "signed-up",
|
155
|
+
:service => "user-mailer"
|
156
|
+
:manual_ack => true
|
157
|
+
}
|
158
|
+
|
159
|
+
Tackle.consume(options) do |message|
|
160
|
+
puts message
|
161
|
+
|
162
|
+
Tackle::ACK
|
163
|
+
end
|
164
|
+
```
|
165
|
+
|
166
|
+
When Tackle consumes messages in the manual_ack mode, the return value of the
|
167
|
+
consumer block must be either `Tackle::ACK` or `Tackle::NACK`. In case the
|
168
|
+
response is `Tackle::NACK` the message is put on the retry queue.
|
169
|
+
|
170
|
+
```ruby
|
171
|
+
require "tackle"
|
172
|
+
|
173
|
+
options = {
|
174
|
+
:url => "amqp://localhost",
|
175
|
+
:exchange => "numbers",
|
176
|
+
:routing_key => "positive-numbers",
|
177
|
+
:service => "number-processor",
|
178
|
+
:manual_ack => true
|
179
|
+
}
|
180
|
+
|
181
|
+
Tackle.consume(options) do |message|
|
182
|
+
# accept only positive numbers
|
183
|
+
|
184
|
+
if message["value"].even?
|
185
|
+
Tackle::ACK
|
186
|
+
else
|
187
|
+
Tackle::NACK
|
188
|
+
end
|
189
|
+
end
|
190
|
+
```
|
191
|
+
|
192
|
+
If neither Tackle::ACK nor Tackle::NACK are returned, tackle assumes
|
193
|
+
that the response is negative.
|
194
|
+
|
128
195
|
## Development
|
129
196
|
|
130
197
|
After checking out the repo, run `bin/setup` to install dependencies. Then,
|
@@ -10,6 +10,7 @@ module Tackle
|
|
10
10
|
attr_reader :retry_delay
|
11
11
|
attr_reader :logger
|
12
12
|
attr_reader :exception_handler
|
13
|
+
attr_reader :manual_ack
|
13
14
|
|
14
15
|
def initialize(params = {})
|
15
16
|
# required
|
@@ -22,10 +23,15 @@ module Tackle
|
|
22
23
|
@retry_limit = params[:retry_limit] || 8
|
23
24
|
@retry_delay = params[:retry_delay] || 30
|
24
25
|
@logger = params[:logger] || Logger.new(STDOUT)
|
26
|
+
@manual_ack = params.fetch(:manual_ack, false)
|
25
27
|
|
26
28
|
@exception_handler = params[:exception_handler]
|
27
29
|
end
|
28
30
|
|
31
|
+
def manual_ack?
|
32
|
+
@manual_ack == true
|
33
|
+
end
|
34
|
+
|
29
35
|
end
|
30
36
|
end
|
31
37
|
end
|
data/lib/tackle/consumer.rb
CHANGED
@@ -43,20 +43,28 @@ module Tackle
|
|
43
43
|
def process_message(message, &block)
|
44
44
|
message.log_info "Calling message processor"
|
45
45
|
|
46
|
-
block.call(message.payload)
|
46
|
+
response = block.call(message.payload)
|
47
47
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
redeliver_message(message)
|
48
|
+
unless @params.manual_ack?
|
49
|
+
response = Tackle::ACK
|
50
|
+
end
|
53
51
|
|
54
|
-
|
52
|
+
case response
|
53
|
+
when Tackle::ACK
|
54
|
+
message.ack
|
55
|
+
when Tackle::NACK
|
56
|
+
redeliver_message(message, "Received Tackle::NACK")
|
57
|
+
else
|
58
|
+
raise "Response must be either Tackle::ACK or Tackle::NACK"
|
59
|
+
end
|
60
|
+
rescue Exception => ex
|
61
|
+
redeliver_message(message, "Received exception '#{ex}'")
|
55
62
|
|
56
63
|
raise ex
|
57
64
|
end
|
58
65
|
|
59
|
-
def redeliver_message(message)
|
66
|
+
def redeliver_message(message, reason)
|
67
|
+
message.log_error "Failed to process message. #{reason}"
|
60
68
|
message.log_error "Retry count #{message.retry_count}/#{@params.retry_limit}"
|
61
69
|
|
62
70
|
if message.retry_count < @params.retry_limit
|
@@ -64,6 +72,8 @@ module Tackle
|
|
64
72
|
else
|
65
73
|
@dead_queue.publish(message)
|
66
74
|
end
|
75
|
+
|
76
|
+
message.nack
|
67
77
|
end
|
68
78
|
|
69
79
|
end
|
data/lib/tackle/version.rb
CHANGED
data/lib/tackle.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rt-tackle
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Rendered Text
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2017-08-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bunny
|