hutch 0.18.0 → 0.19.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: ae290b72e28ca5ca72f8014fe5688e35b4c31716
4
- data.tar.gz: 2a817eece4ab761d6558255395e123d5cea19ea0
3
+ metadata.gz: c5b96423188a88e607bf694005618e1c13bc6ce1
4
+ data.tar.gz: 97955f0060eea500cbd6cc49c3c393adccfaf8a6
5
5
  SHA512:
6
- metadata.gz: b929abefa84452c0b5a74fc2dcfc5f2918fb752d80f97b77e97cf4d0fbfad99e119cd09f3251f17edf1450ee7ccc063a76efaa9e31d318526aabf5a147779b84
7
- data.tar.gz: c5c04b649c3ea2333ff86273d7d17a1d843a02e782bd981d19ef2ea4025286761b4b96fd8200026ce2f503108d588c0aa61f204997632f02ac467ac5fa4633c3
6
+ metadata.gz: d161d2cf60136e26356a18f7a6f552fd11361bce6258132ce9dc807d219290f1fa67fda7f801fb58cacd542c224a93b4941c473aaa4c5ee3b43446632ab03c96
7
+ data.tar.gz: 7d2c9d3f0524a9583e76c853823a1527a9d516d7a2cf368aa061412442930e09d5a2b7855c915d4ab3e1ca8c39b2a82f0a864a6e51d558a420e1a9efd3d96cc1
@@ -1,4 +1,29 @@
1
- ## 0.18.0 — (unreleased)
1
+ ## 0.19.0 — (unreleased)
2
+
3
+ ### Pluggable Serialisers
4
+
5
+ Hutch now supports pluggable serialisers: see `Hutch::Serializer::JSON` for
6
+ an example. Serialiser is configured via Hutch config as a Ruby
7
+ class.
8
+
9
+ Contributed by Dmitry Galinsky.
10
+
11
+
12
+ ### multi_json Update
13
+
14
+ Hutch now depends on multi_json `1.11.x`.
15
+
16
+ ### Bunny Update
17
+
18
+ Bunny is updated to [2.2.0](http://blog.rubyrabbitmq.info/blog/2015/09/06/bunny-2-dot-2-0-is-released/).
19
+
20
+ ### More Bunny SSL Options
21
+
22
+ `:mq_tls_ca_certificates` and `:mq_verify_peer` options will now be passed on to Bunny as `:tls_ca_certificates` and `:verify_peer` respectively.
23
+
24
+ Contributed by Kennon Ballou.
25
+
26
+ ## 0.18.0 — August 16th, 2015
2
27
 
3
28
  ### JRuby Support (Using March Hare)
4
29
 
data/README.md CHANGED
@@ -289,6 +289,8 @@ Known configuration parameters are:
289
289
  * `mq_tls`: should TLS be used? (default: `false`)
290
290
  * `mq_tls_cert`: path to client TLS certificate (public key)
291
291
  * `mq_tls_key`: path to client TLS private key
292
+ * `mq_tls_ca_certificates`: array of paths to CA keys (if not specified to Hutch, will default to Bunny defaults which are system-dependent)
293
+ * `mq_verify_peer`: should SSL certificate be verified? (default: `true`)
292
294
  * `require_paths`: array of paths to require
293
295
  * `autoload_rails`: should Hutch command line runner try to automatically load Rails environment files?
294
296
  * `daemonise`: should Hutch runner process daemonise?
@@ -6,10 +6,10 @@ Gem::Specification.new do |gem|
6
6
  gem.add_runtime_dependency 'march_hare', '>= 2.11.0'
7
7
  else
8
8
  gem.platform = Gem::Platform::RUBY
9
- gem.add_runtime_dependency 'bunny', '>= 1.7.0'
9
+ gem.add_runtime_dependency 'bunny', '>= 2.2.0'
10
10
  end
11
11
  gem.add_runtime_dependency 'carrot-top', '~> 0.0.7'
12
- gem.add_runtime_dependency 'multi_json', '~> 1.5'
12
+ gem.add_runtime_dependency 'multi_json', '~> 1.11.2'
13
13
  gem.add_runtime_dependency 'activesupport', '>= 3.0'
14
14
  gem.add_development_dependency 'rspec', '~> 3.0'
15
15
  gem.add_development_dependency 'simplecov', '~> 0.7.1'
@@ -3,6 +3,8 @@ require 'hutch/consumer'
3
3
  require 'hutch/worker'
4
4
  require 'hutch/broker'
5
5
  require 'hutch/logging'
6
+ require 'hutch/serializers/identity'
7
+ require 'hutch/serializers/json'
6
8
  require 'hutch/config'
7
9
  require 'hutch/message'
8
10
  require 'hutch/cli'
@@ -195,19 +195,30 @@ module Hutch
195
195
  @channel.nack(delivery_tag, false, false)
196
196
  end
197
197
 
198
- def publish(routing_key, message, properties = {})
198
+ def publish(routing_key, message, properties = {}, options = {})
199
199
  ensure_connection!(routing_key, message)
200
200
 
201
+ serializer = options[:serializer] || @config[:serializer]
202
+
201
203
  non_overridable_properties = {
202
- routing_key: routing_key,
203
- timestamp: @connection.current_timestamp,
204
- content_type: 'application/json'
204
+ routing_key: routing_key,
205
+ timestamp: @connection.current_timestamp,
206
+ content_type: serializer.content_type,
207
+ }
208
+ properties[:message_id] ||= generate_id
209
+
210
+ payload = serializer.encode(message)
211
+ logger.info {
212
+ spec =
213
+ if serializer.binary?
214
+ "#{payload.bytesize} bytes message"
215
+ else
216
+ "message '#{payload}'"
217
+ end
218
+ "publishing #{spec} to #{routing_key}"
205
219
  }
206
- properties[:message_id] ||= generate_id
207
220
 
208
- json = JSON.dump(message)
209
- logger.info("publishing message '#{json}' to #{routing_key}")
210
- response = @exchange.publish(json, {persistent: true}.
221
+ response = @exchange.publish(payload, {persistent: true}.
211
222
  merge(properties).
212
223
  merge(global_properties).
213
224
  merge(non_overridable_properties))
@@ -269,6 +280,10 @@ module Hutch
269
280
  params[:tls] = @config[:mq_tls]
270
281
  params[:tls_key] = @config[:mq_tls_key]
271
282
  params[:tls_cert] = @config[:mq_tls_cert]
283
+ params[:verify_peer] = @config[:mq_verify_peer]
284
+ if @config[:mq_tls_ca_certificates]
285
+ params[:tls_ca_certificates] = @config[:mq_tls_ca_certificates]
286
+ end
272
287
  params[:heartbeat] = @config[:heartbeat]
273
288
  params[:connection_timeout] = @config[:connection_timeout]
274
289
  params[:read_timeout] = @config[:read_timeout]
@@ -354,5 +369,6 @@ module Hutch
354
369
  def global_properties
355
370
  Hutch.global_properties.respond_to?(:call) ? Hutch.global_properties.call : Hutch.global_properties
356
371
  end
372
+
357
373
  end
358
374
  end
@@ -17,6 +17,8 @@ module Hutch
17
17
  mq_tls: false,
18
18
  mq_tls_cert: nil,
19
19
  mq_tls_key: nil,
20
+ mq_tls_ca_certificates: nil,
21
+ mq_verify_peer: true,
20
22
  mq_username: 'guest',
21
23
  mq_password: 'guest',
22
24
  mq_api_host: 'localhost',
@@ -53,6 +55,8 @@ module Hutch
53
55
  client_logger: nil,
54
56
 
55
57
  consumer_pool_size: 1,
58
+
59
+ serializer: Hutch::Serializers::JSON,
56
60
  }.merge(params)
57
61
  end
58
62
 
@@ -19,7 +19,7 @@ module Hutch
19
19
  def requeue!
20
20
  broker.requeue(delivery_info.delivery_tag)
21
21
  end
22
-
22
+
23
23
  def logger
24
24
  Hutch::Logging.logger
25
25
  end
@@ -41,6 +41,11 @@ module Hutch
41
41
  @arguments = arguments
42
42
  end
43
43
 
44
+ # Set custom serializer class, override global value
45
+ def serializer(name)
46
+ @serializer = name
47
+ end
48
+
44
49
  # The RabbitMQ queue name for the consumer. This is derived from the
45
50
  # fully-qualified class name. Module separators are replaced with single
46
51
  # colons, camelcased class names are converted to snake case.
@@ -60,6 +65,10 @@ module Hutch
60
65
  def routing_keys
61
66
  @routing_keys ||= Set.new
62
67
  end
68
+
69
+ def get_serializer
70
+ @serializer
71
+ end
63
72
  end
64
73
  end
65
74
  end
@@ -1,6 +1,4 @@
1
- require 'multi_json'
2
1
  require 'forwardable'
3
- require 'active_support/core_ext/hash/indifferent_access'
4
2
 
5
3
  module Hutch
6
4
  class Message
@@ -8,11 +6,11 @@ module Hutch
8
6
 
9
7
  attr_reader :delivery_info, :properties, :payload
10
8
 
11
- def initialize(delivery_info, properties, payload)
9
+ def initialize(delivery_info, properties, payload, serializer)
12
10
  @delivery_info = delivery_info
13
11
  @properties = properties
14
12
  @payload = payload
15
- @body = MultiJson.load(payload).with_indifferent_access
13
+ @body = serializer.decode(payload)
16
14
  end
17
15
 
18
16
  def_delegator :@body, :[]
@@ -0,0 +1,19 @@
1
+ module Hutch
2
+ module Serializers
3
+ class Identity
4
+
5
+ def self.encode(payload)
6
+ payload
7
+ end
8
+
9
+ def self.decode(payload)
10
+ payload
11
+ end
12
+
13
+ def self.binary? ; false ; end
14
+
15
+ def self.content_type ; nil ; end
16
+
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,22 @@
1
+ require 'multi_json'
2
+ require 'active_support/core_ext/hash/indifferent_access'
3
+
4
+ module Hutch
5
+ module Serializers
6
+ class JSON
7
+
8
+ def self.encode(payload)
9
+ ::JSON.dump(payload)
10
+ end
11
+
12
+ def self.decode(payload)
13
+ ::MultiJson.load(payload).with_indifferent_access
14
+ end
15
+
16
+ def self.binary? ; false ; end
17
+
18
+ def self.content_type ; 'application/json' ; end
19
+
20
+ end
21
+ end
22
+ end
@@ -1,4 +1,4 @@
1
1
  module Hutch
2
- VERSION = '0.18.0'.freeze
2
+ VERSION = '0.19.0'.freeze
3
3
  end
4
4
 
@@ -102,14 +102,18 @@ module Hutch
102
102
  # Called internally when a new messages comes in from RabbitMQ. Responsible
103
103
  # for wrapping up the message and passing it to the consumer.
104
104
  def handle_message(consumer, delivery_info, properties, payload)
105
- logger.info("message(#{properties.message_id || '-'}): " +
106
- "routing key: #{delivery_info.routing_key}, " +
107
- "consumer: #{consumer}, " +
108
- "payload: #{payload}")
109
-
110
105
  broker = @broker
111
106
  begin
112
- message = Message.new(delivery_info, properties, payload)
107
+ serializer = consumer.get_serializer || Hutch::Config[:serializer]
108
+ logger.info {
109
+ spec = serializer.binary? ? "#{payload.bytesize} bytes" : "#{payload}"
110
+ "message(#{properties.message_id || '-'}): " +
111
+ "routing key: #{delivery_info.routing_key}, " +
112
+ "consumer: #{consumer}, " +
113
+ "payload: #{spec}"
114
+ }
115
+
116
+ message = Message.new(delivery_info, properties, payload, serializer)
113
117
  consumer_instance = consumer.new.tap { |c| c.broker, c.delivery_info = @broker, delivery_info }
114
118
  with_tracing(consumer_instance).handle(message)
115
119
  broker.ack(delivery_info.delivery_tag)
@@ -2,10 +2,10 @@ require 'hutch/message'
2
2
 
3
3
  describe Hutch::Message do
4
4
  let(:delivery_info) { double('Delivery Info') }
5
- let(:props) { double('Properties') }
5
+ let(:props) { double('Properties', content_type: "application/json") }
6
6
  let(:body) {{ foo: 'bar' }.with_indifferent_access}
7
7
  let(:json_body) { MultiJson.dump(body) }
8
- subject(:message) { Hutch::Message.new(delivery_info, props, json_body) }
8
+ subject(:message) { Hutch::Message.new(delivery_info, props, json_body, Hutch::Config[:serializer]) }
9
9
 
10
10
  describe '#body' do
11
11
  subject { super().body }
@@ -0,0 +1,17 @@
1
+ require 'spec_helper'
2
+
3
+ describe Hutch::Serializers::JSON do
4
+ let(:subject) { described_class }
5
+
6
+ it "encode/decode" do
7
+ payload = { a: 1, b: 2 }
8
+ encoded = subject.encode(payload)
9
+ decoded = subject.decode(encoded)
10
+
11
+ expect(encoded).to eq "{\"a\":1,\"b\":2}"
12
+ expect(decoded).to eq("a" => 1, "b" => 2)
13
+ expect(decoded[:a]).to eq 1
14
+ expect(decoded[:b]).to eq 2
15
+ end
16
+
17
+ end
@@ -3,7 +3,8 @@ require 'hutch/worker'
3
3
 
4
4
  describe Hutch::Worker do
5
5
  let(:consumer) { double('Consumer', routing_keys: %w( a b c ),
6
- get_queue_name: 'consumer', get_arguments: {}) }
6
+ get_queue_name: 'consumer', get_arguments: {},
7
+ get_serializer: nil) }
7
8
  let(:consumers) { [consumer, double('Consumer')] }
8
9
  let(:broker) { Hutch::Broker.new }
9
10
  subject(:worker) { Hutch::Worker.new(broker, consumers) }
@@ -43,7 +44,7 @@ describe Hutch::Worker do
43
44
  let(:consumer_instance) { double('Consumer instance') }
44
45
  let(:delivery_info) { double('Delivery Info', routing_key: '',
45
46
  delivery_tag: 'dt') }
46
- let(:properties) { double('Properties', message_id: nil) }
47
+ let(:properties) { double('Properties', message_id: nil, content_type: "application/json") }
47
48
  before { allow(consumer).to receive_messages(new: consumer_instance) }
48
49
  before { allow(broker).to receive(:ack) }
49
50
  before { allow(broker).to receive(:nack) }
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hutch
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.18.0
4
+ version: 0.19.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Harry Marr
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-08-16 00:00:00.000000000 Z
11
+ date: 2015-09-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bunny
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: 1.7.0
19
+ version: 2.2.0
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: 1.7.0
26
+ version: 2.2.0
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: carrot-top
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -44,14 +44,14 @@ dependencies:
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: '1.5'
47
+ version: 1.11.2
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: '1.5'
54
+ version: 1.11.2
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: activesupport
57
57
  requirement: !ruby/object:Gem::Requirement
@@ -132,6 +132,8 @@ files:
132
132
  - lib/hutch/exceptions.rb
133
133
  - lib/hutch/logging.rb
134
134
  - lib/hutch/message.rb
135
+ - lib/hutch/serializers/identity.rb
136
+ - lib/hutch/serializers/json.rb
135
137
  - lib/hutch/tracers.rb
136
138
  - lib/hutch/tracers/newrelic.rb
137
139
  - lib/hutch/tracers/null_tracer.rb
@@ -147,6 +149,7 @@ files:
147
149
  - spec/hutch/error_handlers/sentry_spec.rb
148
150
  - spec/hutch/logger_spec.rb
149
151
  - spec/hutch/message_spec.rb
152
+ - spec/hutch/serializers/json_spec.rb
150
153
  - spec/hutch/worker_spec.rb
151
154
  - spec/hutch_spec.rb
152
155
  - spec/spec_helper.rb
@@ -185,6 +188,7 @@ test_files:
185
188
  - spec/hutch/error_handlers/sentry_spec.rb
186
189
  - spec/hutch/logger_spec.rb
187
190
  - spec/hutch/message_spec.rb
191
+ - spec/hutch/serializers/json_spec.rb
188
192
  - spec/hutch/worker_spec.rb
189
193
  - spec/hutch_spec.rb
190
194
  - spec/spec_helper.rb