songkick_queue 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a6dc1bf4e0b25fb8f6ed6bb49a7423a4c52649ad
4
- data.tar.gz: 93d50d6793741d2f61c1a0be13408b116bdbcc22
3
+ metadata.gz: 1a1aac7777298d72bae853264f21dc552edc3dad
4
+ data.tar.gz: 90d45ace00562b8b6d5db8d0d33ec1c2cfca509d
5
5
  SHA512:
6
- metadata.gz: e174cceaeee589c2ddaa3e9573dea75f0f7a971ad2f3d47365795e7123a832ebfbe5bba8d1e2ab14640c07b2dbb7052d0ce9ca88115ef5425ce06fc9b3d137f3
7
- data.tar.gz: c3f9ff40394a52f35f91d1dee21e7ba89b33d98edb1d6da8ccc29fc08d5e9f6e77954a26cbed5fd51ec527d47155fc011087a0ca6e3a3249cdb14abab32453e5
6
+ metadata.gz: 1abc17c28cf1d98fad5900a7d76c5a5644f436d2257b8a895e2f8243ac816368dbad85cbacf14dc3c1d257ab5b4cc2f7b8e67af2ada6299d14ee9365cb4ee33f
7
+ data.tar.gz: 460e390e2dd5f4cf78c067ee7b22a647c884f0b8f3927e10fee635016bd39195092863308eaeef3bfc08822c650298c9b06c3371ac40009fc4637a49cde30625
data/CHANGELOG.md ADDED
@@ -0,0 +1,10 @@
1
+ # Changelog
2
+
3
+ ## 0.2.0
4
+ ### Added
5
+ - Configuration option: `queue_namespace` to namespace queue names when
6
+ producing and consuming messages
7
+
8
+ ## 0.1.0
9
+ ### Added
10
+ - Initial project release
@@ -1,4 +1,5 @@
1
1
  require 'json'
2
+ require 'securerandom'
2
3
  require 'bunny'
3
4
 
4
5
  require 'songkick_queue/version'
@@ -28,10 +29,9 @@ module SongkickQueue
28
29
 
29
30
  # Publishes the given message to the given queue
30
31
  #
31
- # @param queue_name [String] to publish to
32
- # @param message [#to_json] to serialize and enqueue
33
- def self.publish(queue_name, message)
34
- producer.publish(queue_name, message)
32
+ # @see SongkickQueue::Producer#publish for argument documentation
33
+ def self.publish(queue_name, message, options = {})
34
+ producer.publish(queue_name, message, options = {})
35
35
  end
36
36
 
37
37
  private
@@ -9,16 +9,27 @@ module SongkickQueue
9
9
  #
10
10
  # @param queue_name [String] to publish to
11
11
  # @param message [#to_json] to serialize and enqueue
12
- def publish(queue_name, message)
13
- payload = JSON.generate(message)
12
+ # @option options [String] :message_id to pass through to the consumer (will be logged)
13
+ # @option options [String] :produced_at time when the message was created, ISO8601 formatted
14
+ def publish(queue_name, payload, options = {})
15
+ message_id = options.fetch(:message_id) { SecureRandom.hex(6) }
16
+ produced_at = options.fetch(:produced_at) { Time.now.utc.iso8601 }
17
+
18
+ message = {
19
+ message_id: message_id,
20
+ produced_at: produced_at,
21
+ payload: payload
22
+ }
23
+
24
+ message = JSON.generate(message)
14
25
 
15
26
  routing_key = [config.queue_namespace, queue_name].compact.join('.')
16
27
 
17
28
  client
18
29
  .default_exchange
19
- .publish(payload, routing_key: routing_key)
30
+ .publish(message, routing_key: routing_key)
20
31
 
21
- logger.info "Published message to #{routing_key}"
32
+ logger.info "Published message #{message_id} to '#{routing_key}' at #{produced_at}"
22
33
  end
23
34
 
24
35
  private
@@ -1,3 +1,3 @@
1
1
  module SongkickQueue
2
- VERSION = "0.2.0"
2
+ VERSION = "0.3.0"
3
3
  end
@@ -67,8 +67,8 @@ module SongkickQueue
67
67
  queue = channel.queue(consumer_class.queue_name, durable: true,
68
68
  arguments: { 'x-ha-policy' => 'all' })
69
69
 
70
- queue.subscribe(manual_ack: true) do |delivery_info, properties, payload|
71
- process_message(consumer_class, delivery_info, properties, payload)
70
+ queue.subscribe(manual_ack: true) do |delivery_info, properties, message|
71
+ process_message(consumer_class, delivery_info, properties, message)
72
72
  end
73
73
 
74
74
  logger.info "Subscribed #{consumer_class} to #{consumer_class.queue_name}"
@@ -79,16 +79,19 @@ module SongkickQueue
79
79
  # @param consumer_class [Class] that was subscribed to
80
80
  # @param delivery_info [Bunny::DeliveryInfo]
81
81
  # @param properties [Bunny::MessageProperties]
82
- # @param payload [String] to deserialize
83
- def process_message(consumer_class, delivery_info, properties, payload)
84
- logger.info "Processing message via #{consumer_class}..."
82
+ # @param message [String] to deserialize
83
+ def process_message(consumer_class, delivery_info, properties, message)
84
+ message = JSON.parse(message, symbolize_names: true)
85
85
 
86
- set_process_name(consumer_class)
86
+ # Handle both old and new format of messages
87
+ # TODO: Tidy this up once messages always have a payload
88
+ payload = message.fetch(:payload, message)
87
89
 
88
- message = JSON.parse(payload, symbolize_names: true)
90
+ logger.info "Processing message via #{consumer_class}..."
91
+ set_process_name(consumer_class)
89
92
 
90
93
  consumer = consumer_class.new(delivery_info, logger)
91
- consumer.process(message)
94
+ consumer.process(payload)
92
95
  rescue Object => exception
93
96
  logger.error(exception)
94
97
  ensure
@@ -115,14 +118,13 @@ module SongkickQueue
115
118
  #
116
119
  # @example idle
117
120
  # set_process_name #=> "songkick_queue[idle]"
118
- # @example consumer running
119
- # set_process_name(TweetConsumer) #=> "songkick_queue[tweet_consumer]"
121
+ # @example consumer running, namespace is removed
122
+ # set_process_name(Foo::TweetConsumer) #=> "songkick_queue[TweetConsumer]"
120
123
  # @param status [String] of the program
121
124
  def set_process_name(status = 'idle')
122
125
  formatted_status = String(status)
123
- .gsub('::', '')
124
- .gsub(/([A-Z]+)/) { "_#{$1.downcase}" }
125
- .sub(/^_(\w)/) { $1 }
126
+ .split('::')
127
+ .last
126
128
 
127
129
  $PROGRAM_NAME = "#{process_name}[#{formatted_status}]"
128
130
  end
@@ -14,11 +14,14 @@ module SongkickQueue
14
14
  allow(producer).to receive(:logger) { logger }
15
15
 
16
16
  expect(exchange).to receive(:publish)
17
- .with('{"example":"message","value":true}', routing_key: 'queue_name')
17
+ .with('{"message_id":"92c583bdc248","produced_at":"2015-03-30T15:41:55Z",' +
18
+ '"payload":{"example":"message","value":true}}', routing_key: 'queue_name')
18
19
 
19
- expect(logger).to receive(:info).with('Published message to queue_name')
20
+ expect(logger).to receive(:info)
21
+ .with("Published message 92c583bdc248 to 'queue_name' at 2015-03-30T15:41:55Z")
20
22
 
21
- producer.publish(:queue_name, { example: 'message', value: true })
23
+ producer.publish(:queue_name, { example: 'message', value: true },
24
+ message_id: '92c583bdc248', produced_at: '2015-03-30T15:41:55Z')
22
25
  end
23
26
 
24
27
  it "should publish with a routing key using the configured queue namespace" do
@@ -32,13 +35,16 @@ module SongkickQueue
32
35
  allow(producer).to receive(:logger) { logger }
33
36
 
34
37
  expect(exchange).to receive(:publish)
35
- .with('{"example":"message","value":true}', routing_key: 'test-env.queue_name')
38
+ .with('{"message_id":"92c583bdc248","produced_at":"2015-03-30T15:41:55Z",' +
39
+ '"payload":{"example":"message","value":true}}', routing_key: 'test-env.queue_name')
36
40
 
37
- expect(logger).to receive(:info).with('Published message to test-env.queue_name')
41
+ expect(logger).to receive(:info)
42
+ .with("Published message 92c583bdc248 to 'test-env.queue_name' at 2015-03-30T15:41:55Z")
38
43
 
39
44
  allow(producer).to receive(:config) { double(queue_namespace: 'test-env') }
40
45
 
41
- producer.publish(:queue_name, { example: 'message', value: true })
46
+ producer.publish(:queue_name, { example: 'message', value: true },
47
+ message_id: '92c583bdc248', produced_at: '2015-03-30T15:41:55Z')
42
48
  end
43
49
  end
44
50
  end
@@ -93,6 +93,36 @@ module SongkickQueue
93
93
 
94
94
  expect(channel).to have_received(:ack).with('tag', false)
95
95
  end
96
+
97
+ it "should handle new message format with nested payload" do
98
+ ::BarConsumer = Class.new
99
+ worker = Worker.new(:process_name, BarConsumer)
100
+
101
+ logger = double(:logger, info: :null)
102
+ allow(worker).to receive(:logger) { logger }
103
+
104
+ channel = double(:channel, ack: :null)
105
+ allow(worker).to receive(:channel) { channel }
106
+
107
+ delivery_info = double(:delivery_info, delivery_tag: 'tag')
108
+
109
+ consumer = double(BarConsumer, process: :null)
110
+
111
+ expect(BarConsumer).to receive(:new)
112
+ .with(delivery_info, logger) { consumer }
113
+
114
+ expect(consumer).to receive(:process)
115
+ .with({ example: 'message', value: true})
116
+
117
+ worker.send(:process_message, BarConsumer, delivery_info, :properties,
118
+ '{"message_id":"92c583bdc248","produced_at":"2015-03-30T15:41:55Z",' +
119
+ '"payload":{"example":"message","value":true}}')
120
+
121
+ expect(logger).to have_received(:info)
122
+ .with('Processing message via BarConsumer...')
123
+
124
+ expect(channel).to have_received(:ack).with('tag', false)
125
+ end
96
126
  end
97
127
  end
98
128
  end
@@ -14,7 +14,7 @@ RSpec.describe SongkickQueue do
14
14
  producer = instance_double(SongkickQueue::Producer)
15
15
  allow(SongkickQueue).to receive(:producer) { producer }
16
16
 
17
- expect(producer).to receive(:publish).with(:queue_name, :message)
17
+ expect(producer).to receive(:publish).with(:queue_name, :message, {})
18
18
 
19
19
  SongkickQueue.publish(:queue_name, :message)
20
20
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: songkick_queue
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dan Lucraft
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2015-03-27 00:00:00.000000000 Z
12
+ date: 2015-03-31 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rake
@@ -94,6 +94,7 @@ files:
94
94
  - .rspec
95
95
  - .travis.yml
96
96
  - .yardopts
97
+ - CHANGELOG.md
97
98
  - Gemfile
98
99
  - LICENSE.txt
99
100
  - README.md