songkick_queue 0.2.0 → 0.3.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 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