mercury_amqp 0.4.0 → 0.5.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 +212 -1
- data/lib/mercury/fake/queued_message.rb +1 -1
- data/lib/mercury/fake.rb +14 -3
- data/lib/mercury/mercury.rb +41 -13
- data/lib/mercury/monadic.rb +1 -0
- data/lib/mercury/received_message.rb +14 -6
- data/lib/mercury/version.rb +1 -1
- data/mercury_amqp.gemspec +1 -0
- data/spec/lib/mercury/monadic_spec.rb +28 -0
- data/spec/lib/mercury/received_message_spec.rb +2 -2
- metadata +16 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 43d54035bd40df4089510aa9839d554f2e715c8f
|
4
|
+
data.tar.gz: c8e309676dbdb1f4488a23c95a060ca4e2d78f3c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c11bd808a2634847b2a7c1b97975a7c3f2601086a82c2b43ba4fc866aea0a068cae96d4d7ce5cd05a3c7678ff8beb69d17a1cc311a16f9c634ba0780184ef917
|
7
|
+
data.tar.gz: 0d458c16c5ea7706e56ec0d39549bb6cb762989b3c057c9426f5e401bccd05974b49f567cbdf9ec30d44c06d91caeca91d23d221d0074e59d8635b3c65b3e150
|
data/README.md
CHANGED
@@ -81,13 +81,17 @@ Indicates message handling succeeded. The message is removed from the queue.
|
|
81
81
|
**nack**(_msg_)
|
82
82
|
|
83
83
|
Indicates message handling failed, with the assumption that it might succeed at
|
84
|
-
a later time. The message is returned to the queue.
|
84
|
+
a later time. The message is returned to the front of the queue.
|
85
85
|
|
86
86
|
**reject**(_msg_)
|
87
87
|
|
88
88
|
Indicates message handling failed, with the assumption that it can never succeed.
|
89
89
|
The message is removed from the queue.
|
90
90
|
|
91
|
+
**republish**(_msg_)
|
92
|
+
|
93
|
+
Like **nack**, except the message is returned to the _back_ of the queue.
|
94
|
+
|
91
95
|
_Note:_ All operations create the referenced constructs if they do not already exist.
|
92
96
|
|
93
97
|
### Serialization
|
@@ -200,6 +204,212 @@ seql do
|
|
200
204
|
end
|
201
205
|
```
|
202
206
|
|
207
|
+
Monadic Interface
|
208
|
+
-----------------
|
209
|
+
|
210
|
+
The _monad_ is a versatile design pattern. There is plenty of
|
211
|
+
literature online, but for now all you need to know is that mercury
|
212
|
+
uses monad principles to chain together asynchronous operations. It
|
213
|
+
all starts with a `Cps` object.
|
214
|
+
|
215
|
+
```
|
216
|
+
2.2.2 :005 > add1 = Cps.new { |n, &k| k.call(n+1) }
|
217
|
+
=> #<Mercury::Cps:...>
|
218
|
+
```
|
219
|
+
|
220
|
+
Much like `Proc.new`, `Cps.new` merely captures some operation in an
|
221
|
+
object but does not do any actual work. The key difference is that
|
222
|
+
`Cps` captures a "continuation-passing style" ("CPS") operation. That is,
|
223
|
+
instead of returning a value to the caller, the operation takes its
|
224
|
+
continuation as an additional argument `k`. (The actual name doesn't matter,
|
225
|
+
of course, but `k` is traditional.) `k` is simply a `Proc`.
|
226
|
+
You can loosely think of it as the "return _`Proc`_", as opposed to
|
227
|
+
the usual return _statement_.
|
228
|
+
|
229
|
+
To invoke a `Proc` we call `Proc#call`. To invoke a `Cps`, we call
|
230
|
+
`Cps#run`, passing the normal arguments as well as the continuation
|
231
|
+
(the block).
|
232
|
+
|
233
|
+
```
|
234
|
+
2.2.2 :006 > add1.run(2) { |result| puts "result = #{result}" }
|
235
|
+
result = 3
|
236
|
+
```
|
237
|
+
|
238
|
+
As you've seen already, asynchronous APIs are closely tied to CPS. In
|
239
|
+
the case of mercury, an operation may involve a conversation with the
|
240
|
+
server. CPS allows our code to go off and do other things -- namely,
|
241
|
+
handle other independent requests -- but also be notified when the
|
242
|
+
operation finally completes.
|
243
|
+
|
244
|
+
### Combining operations
|
245
|
+
|
246
|
+
`Cps` provides a means of combining operations into a larger
|
247
|
+
operation: `Cps#and_then`.
|
248
|
+
|
249
|
+
```ruby
|
250
|
+
def add1(n)
|
251
|
+
Cps.new { |&k| k.call(n+1) }
|
252
|
+
end
|
253
|
+
|
254
|
+
def print_value(n)
|
255
|
+
Cps.new do |&k|
|
256
|
+
puts "value = #{n}"
|
257
|
+
k.call
|
258
|
+
end
|
259
|
+
end
|
260
|
+
|
261
|
+
def add1_and_print(n)
|
262
|
+
add1(n).and_then { |v| print_value(v) }
|
263
|
+
end
|
264
|
+
```
|
265
|
+
```
|
266
|
+
2.2.2 :028 > add1_and_print(2).run
|
267
|
+
value = 3
|
268
|
+
```
|
269
|
+
|
270
|
+
`Cps#and_then`'s block accepts the result of the previous operation and
|
271
|
+
returns the `Cps` object representing the next operation to perform.
|
272
|
+
|
273
|
+
As it turns out, the best way to factor an operation is as a
|
274
|
+
method that
|
275
|
+
|
276
|
+
- accepts the operation arguments, and
|
277
|
+
- returns a `Cps` object
|
278
|
+
|
279
|
+
as seen above.
|
280
|
+
|
281
|
+
### Sequences
|
282
|
+
|
283
|
+
As you can imagine, long `and_then` chains can get syntactially messy.
|
284
|
+
This is where `seq` comes in.
|
285
|
+
|
286
|
+
```
|
287
|
+
def add1_and_print(n)
|
288
|
+
seq do |th|
|
289
|
+
th.en { add1(n) }
|
290
|
+
th.en { |v| print_value(v) }
|
291
|
+
end
|
292
|
+
end
|
293
|
+
```
|
294
|
+
|
295
|
+
This is still not ideal; it would be nice to have a way to bind `v` to
|
296
|
+
the result of `add1(n)` rather than introducing a parameter on the
|
297
|
+
line below. `seql` contains some magic that allows us to do
|
298
|
+
exactly this. (It also eliminates the weird `th.en`.)
|
299
|
+
|
300
|
+
```ruby
|
301
|
+
def add1_and_print(n)
|
302
|
+
seql do
|
303
|
+
let(:v) { add1(n) }
|
304
|
+
and_then { print_value(v) }
|
305
|
+
end
|
306
|
+
end
|
307
|
+
```
|
308
|
+
|
309
|
+
Another benefit of `seql` and `let` is that it makes `v` visible to
|
310
|
+
_all_ subsequent `and_then` blocks, not just the immediately following
|
311
|
+
one.
|
312
|
+
|
313
|
+
But what if we want to introduce a non-CPS operation into our
|
314
|
+
sequence?
|
315
|
+
|
316
|
+
```ruby
|
317
|
+
def add1_and_print(n)
|
318
|
+
seql do
|
319
|
+
let(:v) { add1(n) }
|
320
|
+
and_then { puts 'added!' }
|
321
|
+
and_then { print_value(v) }
|
322
|
+
end
|
323
|
+
end
|
324
|
+
```
|
325
|
+
```
|
326
|
+
2.2.2 :061 > add1_and_print(2).run
|
327
|
+
added!
|
328
|
+
RuntimeError: 'and_then' block did not return a Cps object.
|
329
|
+
```
|
330
|
+
|
331
|
+
This fails because it violates the requirement that the `and_then`
|
332
|
+
block return a `Cps` object, and `puts` does not. `lift` returns a
|
333
|
+
`Cps` object for a block of direct-style code.
|
334
|
+
|
335
|
+
```ruby
|
336
|
+
def add1_and_print(n)
|
337
|
+
seql do
|
338
|
+
let(:v) { add1(n) }
|
339
|
+
and_then { lift { puts 'added!' } }
|
340
|
+
and_then { print_value(v) }
|
341
|
+
end
|
342
|
+
end
|
343
|
+
```
|
344
|
+
```
|
345
|
+
2.2.2 :053 > add1_and_print(2).run
|
346
|
+
added!
|
347
|
+
value = 3
|
348
|
+
```
|
349
|
+
|
350
|
+
Finally, a little clean up:
|
351
|
+
|
352
|
+
```ruby
|
353
|
+
def add1_and_print(n)
|
354
|
+
seql do
|
355
|
+
let(:v) { add1(n) }
|
356
|
+
and_lift { puts 'added!' }
|
357
|
+
and_then { print_value(v) }
|
358
|
+
end
|
359
|
+
end
|
360
|
+
```
|
361
|
+
|
362
|
+
### `Mercury::Monadic`
|
363
|
+
|
364
|
+
`Mercury::Monadic` simply wraps `Mercury` so that the methods return
|
365
|
+
`Cps` objects rather than accepting an explicit continuation.
|
366
|
+
|
367
|
+
```ruby
|
368
|
+
seql do
|
369
|
+
let(:m) { Mercury::Monadic.open }
|
370
|
+
and_then { m.start_listener(source) }
|
371
|
+
...
|
372
|
+
end
|
373
|
+
```
|
374
|
+
|
375
|
+
It is particularly useful when writing tests.
|
376
|
+
|
377
|
+
|
378
|
+
Design Details
|
379
|
+
--------------
|
380
|
+
|
381
|
+
#### `Mercury#republish`
|
382
|
+
|
383
|
+
This method publishes a copy of the message to the _back_ of the
|
384
|
+
queue, then acks the original message. This is a similar operation to
|
385
|
+
ack/nack/reject. It is only applicable to messages received by
|
386
|
+
workers, since listener messages cannot be acknowledged. Unlike other
|
387
|
+
acknowledgements, `#republish` takes a continuation (due to the
|
388
|
+
publish operation), so the method is located on `Mercury` rather than
|
389
|
+
`Mercury::ReceivedMessage`.
|
390
|
+
|
391
|
+
It is important that the message is republished to the AMQP _queue_
|
392
|
+
and not the _source_. Acknowledgement is a worker concern. If two
|
393
|
+
different worker pools were working off a common source, it wouldn't
|
394
|
+
make sense for pool A to get a duplicate message because pool B failed
|
395
|
+
to handle the message.
|
396
|
+
|
397
|
+
AMQP allows publishing to a particular queue by sending the message to
|
398
|
+
the [default exchange][default_exchange], specifying the queue name as
|
399
|
+
the routing key. Thus, if the message was originally sent with a
|
400
|
+
non-empty routing key, that information is lost. Some clients rely on
|
401
|
+
the routing key/tag to dictate behavior (by reading
|
402
|
+
`Mercury::ReceivedMessage#tag`). To avoid breaking such clients,
|
403
|
+
republish propagates the original tag in a header and reports this value
|
404
|
+
as the tag on the republished message.
|
405
|
+
|
406
|
+
Republishing also introduces a `Republish-Count` header and
|
407
|
+
corresponding attribute `Mercury::ReceivedMessage#republish_count`.
|
408
|
+
This value is incremented each time the message is republished.
|
409
|
+
Clients may want to check this value and act differently if it exceeds
|
410
|
+
some threshold.
|
411
|
+
|
412
|
+
|
203
413
|
Design Decisions
|
204
414
|
----------------
|
205
415
|
|
@@ -216,3 +426,4 @@ is being intentionally ignored.
|
|
216
426
|
[logatron]: https://github.com/indigobio/logatron
|
217
427
|
[em_defer]: http://www.rubydoc.info/github/eventmachine/eventmachine/EventMachine.defer
|
218
428
|
[fiber_defer]: https://github.com/indigobio/abstractivator/blob/master/lib/abstractivator/fiber_defer.rb
|
429
|
+
[default_exchange]: https://www.rabbitmq.com/tutorials/amqp-concepts.html
|
@@ -9,7 +9,7 @@ class Mercury
|
|
9
9
|
|
10
10
|
def initialize(queue, msg, tag, headers, is_ackable)
|
11
11
|
metadata = Metadata.new(tag, headers, proc{queue.ack_or_reject_message(self)}, proc{queue.nack(self)})
|
12
|
-
@received_msg = ReceivedMessage.new(msg, metadata, is_ackable:
|
12
|
+
@received_msg = ReceivedMessage.new(msg, metadata, work_queue_name: is_ackable ? queue.worker : nil)
|
13
13
|
@headers = headers
|
14
14
|
@delivered = false
|
15
15
|
end
|
data/lib/mercury/fake.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
require 'securerandom'
|
2
2
|
require 'delegate'
|
3
|
+
require 'active_support/core_ext/hash/keys'
|
4
|
+
require 'active_support/core_ext/object/deep_dup'
|
3
5
|
require 'mercury/received_message'
|
4
6
|
require 'mercury/fake/domain'
|
5
7
|
require 'mercury/fake/metadata'
|
@@ -43,7 +45,15 @@ class Mercury
|
|
43
45
|
|
44
46
|
def publish(source_name, msg, tag: '', headers: {}, &k)
|
45
47
|
guard_public(k)
|
46
|
-
queues.values.select{|q| q.binds?(source_name, tag)}.each{|q| q.enqueue(roundtrip(msg), tag, headers)}
|
48
|
+
queues.values.select{|q| q.binds?(source_name, tag)}.each{|q| q.enqueue(roundtrip(msg), tag, headers.stringify_keys)}
|
49
|
+
ret(k)
|
50
|
+
end
|
51
|
+
|
52
|
+
def republish(msg, &k)
|
53
|
+
guard_public(k)
|
54
|
+
msg.ack
|
55
|
+
queue = queues.values.detect{|q| q.worker == msg.work_queue_name}
|
56
|
+
queue.enqueue(roundtrip(msg.content), msg.tag, Mercury.increment_republish_count(msg))
|
47
57
|
ret(k)
|
48
58
|
end
|
49
59
|
|
@@ -58,7 +68,7 @@ class Mercury
|
|
58
68
|
def start_worker_or_listener(source_name, handler, tag_filter, worker_group=nil, &k)
|
59
69
|
guard_public(k)
|
60
70
|
tag_filter ||= '#'
|
61
|
-
q = ensure_queue(source_name, tag_filter,
|
71
|
+
q = ensure_queue(source_name, tag_filter, worker_group)
|
62
72
|
ret(k) # it's important we show the "start" operation finishing before delivery starts (in add_subscriber)
|
63
73
|
q.add_subscriber(Subscriber.new(handler, @parallelism))
|
64
74
|
end
|
@@ -102,7 +112,8 @@ class Mercury
|
|
102
112
|
ws.read(ws.write(msg))
|
103
113
|
end
|
104
114
|
|
105
|
-
def ensure_queue(source, tag_filter,
|
115
|
+
def ensure_queue(source, tag_filter, worker)
|
116
|
+
require_ack = worker != nil
|
106
117
|
worker ||= SecureRandom.uuid
|
107
118
|
queues.fetch(unique_queue_name(source, tag_filter, worker)) do |k|
|
108
119
|
queues[k] = Queue.new(source, tag_filter, worker, require_ack)
|
data/lib/mercury/mercury.rb
CHANGED
@@ -5,6 +5,9 @@ require 'mercury/received_message'
|
|
5
5
|
require 'logatron/logatron'
|
6
6
|
|
7
7
|
class Mercury
|
8
|
+
ORIGINAL_TAG_HEADER = 'Original-Tag'.freeze
|
9
|
+
REPUBLISH_COUNT_HEADER = 'Republish-Count'.freeze
|
10
|
+
|
8
11
|
attr_reader :amqp, :channel, :logger
|
9
12
|
|
10
13
|
def self.open(logger: Logatron, **kws, &k)
|
@@ -60,17 +63,34 @@ class Mercury
|
|
60
63
|
# The amqp gem caches exchange objects, so it's fine to
|
61
64
|
# redeclare the exchange every time we publish.
|
62
65
|
with_source(source_name) do |exchange|
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
66
|
+
publish_internal(exchange, msg, tag, headers, &k)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
# Places a copy of the message at the back of the queue, then acks
|
71
|
+
# the original message.
|
72
|
+
def republish(msg, &k)
|
73
|
+
guard_public(k)
|
74
|
+
raise 'Only messages from a work queue can be republished' unless msg.work_queue_name
|
75
|
+
headers = Mercury.increment_republish_count(msg).merge(ORIGINAL_TAG_HEADER => msg.tag)
|
76
|
+
publish_internal(@channel.default_exchange, msg.content, msg.work_queue_name, headers) do
|
77
|
+
msg.ack
|
78
|
+
k.call
|
71
79
|
end
|
72
80
|
end
|
73
81
|
|
82
|
+
def publish_internal(exchange, msg, tag, headers, &k)
|
83
|
+
payload = write(msg)
|
84
|
+
pub_opts = Mercury.publish_opts(tag, headers)
|
85
|
+
if publisher_confirms_enabled
|
86
|
+
expect_publisher_confirm(k)
|
87
|
+
exchange.publish(payload, **pub_opts)
|
88
|
+
else
|
89
|
+
exchange.publish(payload, **pub_opts, &k)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
private :publish_internal
|
93
|
+
|
74
94
|
def self.publish_opts(tag, headers)
|
75
95
|
{ routing_key: tag, persistent: true, headers: Logatron.http_headers.merge(headers) }
|
76
96
|
end
|
@@ -80,7 +100,7 @@ class Mercury
|
|
80
100
|
with_source(source_name) do |exchange|
|
81
101
|
with_listener_queue(exchange, tag_filter) do |queue|
|
82
102
|
queue.subscribe(ack: false) do |metadata, payload|
|
83
|
-
handler.call(make_received_message(payload, metadata
|
103
|
+
handler.call(make_received_message(payload, metadata))
|
84
104
|
end
|
85
105
|
k.call
|
86
106
|
end
|
@@ -92,7 +112,7 @@ class Mercury
|
|
92
112
|
with_source(source_name) do |exchange|
|
93
113
|
with_work_queue(worker_group, exchange, tag_filter) do |queue|
|
94
114
|
queue.subscribe(ack: true) do |metadata, payload|
|
95
|
-
handler.call(make_received_message(payload, metadata,
|
115
|
+
handler.call(make_received_message(payload, metadata, work_queue_name: worker_group))
|
96
116
|
end
|
97
117
|
k.call
|
98
118
|
end
|
@@ -137,6 +157,8 @@ class Mercury
|
|
137
157
|
|
138
158
|
private
|
139
159
|
|
160
|
+
LOGATRAON_MSG_ID_HEADER = 'X-Ascent-Log-Id'.freeze
|
161
|
+
|
140
162
|
# In AMQP, queue consumers ack requests after handling them. Unacked messages
|
141
163
|
# are automatically returned to the queue, guaranteeing they are eventually handled.
|
142
164
|
# Services often ack one request while publishing related messages. Ideally, these
|
@@ -189,9 +211,9 @@ class Mercury
|
|
189
211
|
end
|
190
212
|
end
|
191
213
|
|
192
|
-
def make_received_message(payload, metadata,
|
193
|
-
msg = ReceivedMessage.new(read(payload), metadata,
|
194
|
-
Logatron.msg_id = msg.headers[
|
214
|
+
def make_received_message(payload, metadata, work_queue_name: nil)
|
215
|
+
msg = ReceivedMessage.new(read(payload), metadata, work_queue_name: work_queue_name)
|
216
|
+
Logatron.msg_id = msg.headers[LOGATRAON_MSG_ID_HEADER]
|
195
217
|
msg
|
196
218
|
end
|
197
219
|
|
@@ -295,6 +317,12 @@ class Mercury
|
|
295
317
|
end
|
296
318
|
end
|
297
319
|
|
320
|
+
# @param msg [Mercury::ReceivedMessage]
|
321
|
+
# @return [Hash] the headers with republish count incremented
|
322
|
+
def self.increment_republish_count(msg)
|
323
|
+
msg.headers.merge(REPUBLISH_COUNT_HEADER => msg.republish_count + 1)
|
324
|
+
end
|
325
|
+
|
298
326
|
def guard_public(k, initializing: false)
|
299
327
|
Mercury.guard_public(@amqp.nil?, k, initializing: initializing)
|
300
328
|
end
|
data/lib/mercury/monadic.rb
CHANGED
@@ -1,19 +1,23 @@
|
|
1
1
|
class Mercury
|
2
2
|
class ReceivedMessage
|
3
|
-
attr_reader :content, :metadata, :action_taken
|
3
|
+
attr_reader :content, :metadata, :action_taken, :work_queue_name
|
4
4
|
|
5
|
-
def initialize(content, metadata,
|
5
|
+
def initialize(content, metadata, work_queue_name: nil)
|
6
6
|
@content = content
|
7
7
|
@metadata = metadata
|
8
|
-
@
|
8
|
+
@work_queue_name = work_queue_name
|
9
9
|
end
|
10
10
|
|
11
11
|
def tag
|
12
|
-
metadata.routing_key
|
12
|
+
headers[Mercury::ORIGINAL_TAG_HEADER] || metadata.routing_key
|
13
13
|
end
|
14
14
|
|
15
15
|
def headers
|
16
|
-
metadata.headers || {}
|
16
|
+
(metadata.headers || {}).dup
|
17
|
+
end
|
18
|
+
|
19
|
+
def republish_count
|
20
|
+
(metadata.headers[Mercury::REPUBLISH_COUNT_HEADER] || 0).to_i
|
17
21
|
end
|
18
22
|
|
19
23
|
def ack
|
@@ -33,8 +37,12 @@ class Mercury
|
|
33
37
|
|
34
38
|
private
|
35
39
|
|
40
|
+
def is_ackable
|
41
|
+
@work_queue_name != nil
|
42
|
+
end
|
43
|
+
|
36
44
|
def performing_action(action)
|
37
|
-
|
45
|
+
is_ackable or raise "This message is not #{action}able"
|
38
46
|
if @action_taken
|
39
47
|
raise "This message was already #{@action_taken}ed"
|
40
48
|
end
|
data/lib/mercury/version.rb
CHANGED
data/mercury_amqp.gemspec
CHANGED
@@ -121,6 +121,34 @@ describe Mercury::Monadic do
|
|
121
121
|
end
|
122
122
|
end
|
123
123
|
|
124
|
+
itt 'republishes' do
|
125
|
+
test_with_mercury do |m|
|
126
|
+
msgs = []
|
127
|
+
seql do
|
128
|
+
and_then { m.start_worker(worker, source, &msgs.method(:push)) }
|
129
|
+
and_then { m.publish(source, msg, tag: 'foo', headers: {bar: 123}) }
|
130
|
+
and_then { wait_until { msgs.size == 1 } }
|
131
|
+
and_lift do
|
132
|
+
expect(msgs.last.tag).to eql 'foo'
|
133
|
+
expect(msgs.last.headers['bar']).to eql 123
|
134
|
+
expect(msgs.last.republish_count).to eql 0
|
135
|
+
end
|
136
|
+
and_then { m.republish(msgs.last) }
|
137
|
+
and_then { wait_until { msgs.size == 2 } }
|
138
|
+
and_lift do
|
139
|
+
expect(msgs.last.tag).to eql 'foo' # preserves the tag
|
140
|
+
expect(msgs.last.headers['bar']).to eql 123 # preserves the headers
|
141
|
+
expect(msgs.last.republish_count).to eql 1 # increments the republish count
|
142
|
+
end
|
143
|
+
and_then { m.republish(msgs.last) }
|
144
|
+
and_then { wait_until { msgs.size == 3 } }
|
145
|
+
and_lift do
|
146
|
+
expect(msgs.last.republish_count).to eql 2 # can republish a republished message
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
124
152
|
it 'propagates logatron headers' do
|
125
153
|
real_msg_id = SecureRandom.uuid
|
126
154
|
Logatron.msg_id = real_msg_id
|
@@ -56,11 +56,11 @@ describe Mercury::ReceivedMessage do
|
|
56
56
|
end
|
57
57
|
|
58
58
|
def make_actionable
|
59
|
-
Mercury::ReceivedMessage.new('hello', make_metadata,
|
59
|
+
Mercury::ReceivedMessage.new('hello', make_metadata, work_queue_name: 'foo')
|
60
60
|
end
|
61
61
|
|
62
62
|
def make_non_actionable
|
63
|
-
Mercury::ReceivedMessage.new('hello', make_metadata,
|
63
|
+
Mercury::ReceivedMessage.new('hello', make_metadata, work_queue_name: nil)
|
64
64
|
end
|
65
65
|
|
66
66
|
def make_metadata
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mercury_amqp
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Peter Winton
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-05-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -178,6 +178,20 @@ dependencies:
|
|
178
178
|
- - "~>"
|
179
179
|
- !ruby/object:Gem::Version
|
180
180
|
version: '0'
|
181
|
+
- !ruby/object:Gem::Dependency
|
182
|
+
name: activesupport
|
183
|
+
requirement: !ruby/object:Gem::Requirement
|
184
|
+
requirements:
|
185
|
+
- - "~>"
|
186
|
+
- !ruby/object:Gem::Version
|
187
|
+
version: '4.0'
|
188
|
+
type: :runtime
|
189
|
+
prerelease: false
|
190
|
+
version_requirements: !ruby/object:Gem::Requirement
|
191
|
+
requirements:
|
192
|
+
- - "~>"
|
193
|
+
- !ruby/object:Gem::Version
|
194
|
+
version: '4.0'
|
181
195
|
description: Abstracts common patterns used with AMQP
|
182
196
|
email:
|
183
197
|
- wintonpc@gmail.com
|