mercury_amqp 0.4.0 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|