carrot_rpc 0.8.0 → 1.0.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: 97329124a088c7a7628e5613ce2059874097a8db
4
- data.tar.gz: 216bf02e2bf6e657c1a3938329069af10f6380c2
3
+ metadata.gz: 4ba255fb6d2e277988ef84326c30193fe9dc0ca7
4
+ data.tar.gz: 7c8a26c482a1041887f7ac73eb5bd9396966a3fe
5
5
  SHA512:
6
- metadata.gz: 8f6171315d5e230225a1062be1e46d97fe102f942407c0725c8331734137be6428598d675021ff808a2428009397c2beee07031632dbc0745bcb1c5fd7b70864
7
- data.tar.gz: 4abfd002d0ea5d4b5c5704dac547c0076143c2dcfbbc3c46a7cf030b6105d275977ec95c649778ea08269aaae5b310b73cf00948257e8ac7a48951af76cb0aa3
6
+ metadata.gz: ca9b37d0788166fe678d7281cfeac3846f662370b6a5ac6de02fc3567df59ddce010999f61555603ba7c0170f338ee5f32a9d70e7e7f71f2bc86e0cac7bf358b
7
+ data.tar.gz: 71d2becd5fa8dab667c8b82c3e98e194c29cd46ab95d1997304597aa929741cb2a7287fdb936d46d991c160e06642fde18b504953c868e628329a71fb8d9ad7e
data/.rubocop.yml CHANGED
@@ -2,6 +2,9 @@ AllCops:
2
2
  DisplayCopNames: true
3
3
  TargetRubyVersion: 2.2
4
4
 
5
+ Metrics/ClassLength:
6
+ Max: 120
7
+
5
8
  Metrics/LineLength:
6
9
  Max: 120
7
10
 
data/.travis.yml CHANGED
@@ -1,3 +1,5 @@
1
1
  language: ruby
2
2
  rvm:
3
- - 2.2.1
3
+ - 2.2.6
4
+ - 2.3.3
5
+ - 2.4.0
data/CHANGELOG.md CHANGED
@@ -3,52 +3,69 @@
3
3
  **Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)*
4
4
 
5
5
  - [Changelog](#changelog)
6
+ - [v1.0.0](#v100)
7
+ - [Incompatible Changes](#incompatible-changes)
8
+ - [v0.8.1](#v081)
9
+ - [Enhancements](#enhancements)
10
+ - [v0.8.0](#v080)
11
+ - [Enhancements](#enhancements-1)
6
12
  - [v0.7.1](#v071)
7
13
  - [Bug Fixes](#bug-fixes)
8
14
  - [v0.7.0](#v070)
9
15
  - [Bug Fixes](#bug-fixes-1)
10
- - [Incompatible Changes](#incompatible-changes)
16
+ - [Incompatible Changes](#incompatible-changes-1)
11
17
  - [v0.6.0](#v060)
12
- - [Enhancements](#enhancements)
18
+ - [Enhancements](#enhancements-2)
13
19
  - [v0.5.1](#v051)
14
20
  - [Bug Fixes](#bug-fixes-2)
15
21
  - [v0.5.0](#v050)
16
- - [Enhancements](#enhancements-1)
17
- - [Incompatible Changes](#incompatible-changes-1)
22
+ - [Enhancements](#enhancements-3)
23
+ - [Incompatible Changes](#incompatible-changes-2)
18
24
  - [v0.4.1](#v041)
19
25
  - [Bug Fixes](#bug-fixes-3)
20
26
  - [v0.4.0](#v040)
21
- - [Enhancements](#enhancements-2)
27
+ - [Enhancements](#enhancements-4)
22
28
  - [Bug Fixes](#bug-fixes-4)
23
- - [Incompatible Changes](#incompatible-changes-2)
29
+ - [Incompatible Changes](#incompatible-changes-3)
24
30
  - [v0.3.0](#v030)
25
- - [Enhancements](#enhancements-3)
31
+ - [Enhancements](#enhancements-5)
26
32
  - [Bug Fixes](#bug-fixes-5)
27
33
  - [v0.2.3](#v023)
28
- - [Enhancements](#enhancements-4)
34
+ - [Enhancements](#enhancements-6)
29
35
  - [Bug Fixes](#bug-fixes-6)
30
36
  - [Upgrading](#upgrading)
31
37
  - [v0.2.1](#v021)
32
38
  - [Bug Fixes](#bug-fixes-7)
33
39
  - [v0.2.0](#v020)
34
- - [Enhancements](#enhancements-5)
40
+ - [Enhancements](#enhancements-7)
35
41
  - [Bug Fixes](#bug-fixes-8)
36
- - [Incompatible Changes](#incompatible-changes-3)
42
+ - [Incompatible Changes](#incompatible-changes-4)
37
43
  - [v0.1.2](#v012)
38
- - [Enhancements](#enhancements-6)
44
+ - [Enhancements](#enhancements-8)
39
45
  - [Bug Fixes](#bug-fixes-9)
40
46
  - [v0.1.1](#v011)
41
- - [Enhancements](#enhancements-7)
47
+ - [Enhancements](#enhancements-9)
42
48
  - [Bug Fixes](#bug-fixes-10)
43
- - [Incompatible Changes](#incompatible-changes-4)
49
+ - [Incompatible Changes](#incompatible-changes-5)
44
50
 
45
51
  <!-- END doctoc generated TOC please keep comment here to allow auto update -->
46
52
 
47
53
  # Changelog
48
54
  All significant changes in the project are documented here.
49
55
 
56
+ ## v1.0.0
57
+ ### Incompatible Changes
58
+ * [#48](https://github.com/C-S-D/carrot_rpc/pull/48) - Remove queue for correlation_id when RpcClient#wait_for_result raises an exception. -[@nward](https://github.com/nward)
59
+ * [#50](https://github.com/C-S-D/carrot_rpc/pull/50) - Raise an exception for error responses to let consuming application handle response. -[@nward](https://github.com/nward)
60
+ * [#52](https://github.com/C-S-D/carrot_rpc/pull/52) - Allow custom queue options to be set -[@nward](https://github.com/nward)
61
+ * [#53](https://github.com/C-S-D/carrot_rpc/pull/53) - Rename keys for any hashes inside arrays. Fixes issue [#35](https://github.com/C-S-D/carrot_rpc/issues/35) -[@thewalkingtoast](https://github.com/thewalkingtoast)
62
+
63
+ ## v0.8.1
64
+ ### Enhancements
65
+ * Update to Ruby 2.2.6 and have tests run for Ruby 2.3 and 2.4.
66
+
50
67
  ## v0.8.0
51
- ### Enchancements
68
+ ### Enhancements
52
69
  * Don't assume that Bunny already has a connection to RabbitMQ.
53
70
  * Attempt to start Bunny for the servers
54
71
  * This allows the implementing application to decide when to start the connection when using a forking web server
data/CODE_OF_CONDUCT.md CHANGED
@@ -1,3 +1,11 @@
1
+ <!-- START doctoc generated TOC please keep comment here to allow auto update -->
2
+ <!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
3
+ **Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)*
4
+
5
+ - [Contributor Code of Conduct](#contributor-code-of-conduct)
6
+
7
+ <!-- END doctoc generated TOC please keep comment here to allow auto update -->
8
+
1
9
 
2
10
  # Contributor Code of Conduct
3
11
 
data/Gemfile CHANGED
@@ -1,6 +1,5 @@
1
1
  source "https://rubygems.org"
2
2
 
3
- ruby "2.2.5"
4
3
  # Specify your gem's dependencies in carrot_rpc.gemspec
5
4
  gemspec
6
5
 
data/README.md CHANGED
@@ -11,6 +11,8 @@
11
11
  - [Writing Servers](#writing-servers)
12
12
  - [Writing Clients](#writing-clients)
13
13
  - [Using request threading in clients](#using-request-threading-in-clients)
14
+ - [Custom Queue Options](#custom-queue-options)
15
+ - [Errors](#errors)
14
16
  - [Support for JSONAPI::Resources](#support-for-jsonapiresources)
15
17
  - [Development](#development)
16
18
  - [Contributing](#contributing)
@@ -249,6 +251,21 @@ class ProfileClient < CarrotRpc::RpcClient
249
251
  end
250
252
  ```
251
253
 
254
+ ### Custom Queue Options
255
+ By default, client queues are defined with `auto_delete: false`, and server queues are defined with no parameters, so use the Bunny/RabbitMQ defaults. These can be customised by calling the `queue_options` class method to add to or override these options on either a RpcClient or RpcServer subclass. This method takes any queue parameter accepted by Bunny.
256
+ Care should be taken when setting these options, as CarrotRPC does not attempt to fix mistakes here. The defaults are typically what you want.
257
+
258
+ The following overrides the default CarrotRpc auto_delete option, and sets durable to true:
259
+ ```ruby
260
+ class CarClient < CarrotRpc::RpcClient
261
+ queue_name "car_queue"
262
+ queue_options auto_delete: true, durable: true
263
+ end
264
+ ```
265
+
266
+ #### Errors
267
+ If a JSON-RPC error is returned, a CarrotRpc::Error exception is raised with the appropriate attributes set. If a malformed JSON-RPC error is returned (i.e. code or message are missing), an CarrotRpc::Exception::InvalidResponse exception is raised.
268
+
252
269
  ### Support for JSONAPI::Resources
253
270
  In the case that you're writing an application that uses the `jsonapi-resources` gem and you want the `RpcServer` to have the same functionality, then we got you covered. All you need to do is import a few modules. See [jsonapi-resources](https://github.com/cerebris/jsonapi-resources) for details on how to implement resources for your models.
254
271
 
@@ -257,25 +274,25 @@ Example Server with JSONAPI functionality:
257
274
  class CarServer < CarrotRpc::RpcServer
258
275
  extend CarrotRpc::RpcServer::JSONAPIResources::Actions
259
276
  include CarrotRpc::RpcServer::JSONAPIResources
260
-
277
+
261
278
  # declare the actions to enable
262
279
  actions: :create, :destroy, :index, :show, :update
263
-
280
+
264
281
  # Context so it can build urls
265
282
  def base_url
266
283
  "http://foo.com"
267
284
  end
268
-
285
+
269
286
  # Context to find the resource and create links.
270
287
  def controller
271
288
  "api/cars"
272
289
  end
273
-
290
+
274
291
  # JSONAPI::Resource example: `app/resources/car_resource.rb`
275
292
  def resource_klass
276
293
  CarResource
277
294
  end
278
-
295
+
279
296
  queue_name "car_queue"
280
297
 
281
298
  def show(params)
data/carrot_rpc.gemspec CHANGED
@@ -28,7 +28,7 @@ Gem::Specification.new do |spec|
28
28
  # Production requirements
29
29
 
30
30
  # Common extensions from Rails
31
- spec.add_dependency "activesupport", "~> 4.2"
31
+ spec.add_dependency "activesupport", ">= 4.2", "< 6.x"
32
32
  # The RabbitMQ library
33
33
  spec.add_dependency "bunny", "~> 2.2"
34
34
 
data/circle.yml CHANGED
@@ -1,8 +1,15 @@
1
1
  machine:
2
2
  services:
3
3
  - rabbitmq-server
4
+ dependencies:
5
+ override:
6
+ - 'rvm-exec 2.2.6 bundle install'
7
+ - 'rvm-exec 2.3.3 bundle install'
8
+ - 'rvm-exec 2.4.0 bundle install'
4
9
  test:
5
10
  override:
6
- - RAILS_ENV=test bundle exec rspec -r rspec_junit_formatter --format RspecJunitFormatter -o $CIRCLE_TEST_REPORTS/rspec/junit.xml
11
+ - 'RAILS_ENV=test rvm-exec 2.2.6 bundle exec rspec -r rspec_junit_formatter --format RspecJunitFormatter -o $CIRCLE_TEST_REPORTS/rspec/junit.xml'
12
+ - 'RAILS_ENV=test rvm-exec 2.3.3 bundle exec rspec -r rspec_junit_formatter --format RspecJunitFormatter -o $CIRCLE_TEST_REPORTS/rspec/junit.xml'
13
+ - 'RAILS_ENV=test rvm-exec 2.4.0 bundle exec rspec -r rspec_junit_formatter --format RspecJunitFormatter -o $CIRCLE_TEST_REPORTS/rspec/junit.xml'
7
14
  post:
8
- - bundle exec rubocop
15
+ - 'rvm-exec 2.2.6 bundle exec rubocop'
@@ -19,7 +19,30 @@ module CarrotRpc::ClientServer
19
19
  @queue_name = args[0]
20
20
  else
21
21
  fail ArgumentError,
22
- "queue_name(new_name) :: new_name or queue_name() :: current_name are the only ways to call queue_name"
22
+ "queue_name(new_name) :: new_name or queue_name() :: " \
23
+ "current_name are the only ways to call queue_name"
24
+ end
25
+ end
26
+
27
+ # @overload queue_options(options)
28
+ #
29
+ # Allows for custom queue options, such as durable.
30
+ #
31
+ # @options params [Hash] a hash of options to pass to bunny.
32
+ #
33
+ # @overload queue_options
34
+ # The current queue options previously set with `#queue_options(options)`.
35
+ #
36
+ # @return [Hash]
37
+ def queue_options(*args)
38
+ if args.length == 0
39
+ @queue_options || {}
40
+ elsif args.length == 1
41
+ @queue_options = args[0]
42
+ else
43
+ fail ArgumentError,
44
+ "queue_options(options) :: options or queue_options() :: " \
45
+ "current_options are the only ways to call queue_options"
23
46
  end
24
47
  end
25
48
 
@@ -3,4 +3,5 @@ module CarrotRpc::Exception
3
3
  # Exception to be raised when the client timesout waiting for a response.
4
4
  class RpcClientTimeout < StandardError; end
5
5
  class InvalidQueueName < StandardError; end
6
+ class InvalidResponse < StandardError; end
6
7
  end
@@ -5,11 +5,13 @@ module CarrotRpc::HashExtensions
5
5
  # @param [String] find the text to look for in a keys
6
6
  # @param [String] replace the text to replace the found text
7
7
  # @return [Hash] a new hash
8
- def rename_keys(find, replace, new_hash = {})
8
+ def rename_keys(find, replace, new_hash = {}) # rubocop:disable Metrics/MethodLength
9
9
  each do |k, v|
10
10
  new_key = k.to_s.gsub(find, replace)
11
11
 
12
- new_hash[new_key] = if v.is_a? Hash
12
+ new_hash[new_key] = if v.is_a? Array
13
+ v.map { |t| t.rename_keys(find, replace) }
14
+ elsif v.is_a? Hash
13
15
  v.rename_keys(find, replace)
14
16
  else
15
17
  v
@@ -17,6 +19,6 @@ module CarrotRpc::HashExtensions
17
19
  end
18
20
 
19
21
  new_hash
20
- end
22
+ end # rubocop:enable Metrics/MethodLength
21
23
  end
22
24
  end
@@ -40,7 +40,8 @@ class CarrotRpc::RpcClient
40
40
 
41
41
  queue_name = self.class.test_queue_name(self.class.queue_name, @config.client_test_mode)
42
42
  # auto_delete => false keeps the queue around until RabbitMQ restarts or explicitly deleted
43
- @server_queue = @channel.queue(queue_name, auto_delete: false)
43
+ options = { auto_delete: false }.merge(self.class.queue_options)
44
+ @server_queue = @channel.queue(queue_name, options)
44
45
 
45
46
  # Setup a direct exchange.
46
47
  @exchange = @channel.default_exchange
@@ -87,10 +88,16 @@ class CarrotRpc::RpcClient
87
88
  # and this must happend before the `Hash.delete` or
88
89
  # the receiving thread won't be able to find the correlation_id in @results
89
90
  result = @results[correlation_id].pop
90
- @results.delete correlation_id # remove item from hash. prevents memory leak.
91
+
92
+ # If we get an exception, raise it in this thread, so the application can deal with it.
93
+ if result.is_a? Exception
94
+ fail result
95
+ end
96
+
91
97
  result
92
98
  end
93
99
  ensure
100
+ @results.delete correlation_id # remove item from hash. prevents memory leak.
94
101
  @channel.close
95
102
  end
96
103
 
@@ -151,12 +158,30 @@ class CarrotRpc::RpcClient
151
158
  response[:result]
152
159
  # data is the key holding the error information
153
160
  elsif response.key?(:error)
154
- response[:error][:data]
161
+ parse_error_result(response)
155
162
  else
156
163
  response
157
164
  end
158
165
  end
159
166
 
167
+ # Build an CarrotRpc::Error based on an error response or throw CarrotRpc::Exception::InvalidResponse if
168
+ # the response error itself is invalid.
169
+ # @param [Hash] response from rpc call
170
+ # @return [CarrotRpc::Error, CarrotRpc::Exception::InvalidResponse]
171
+ def parse_error_result(response)
172
+ # If we don't have a code, throw an exception.
173
+ unless response[:error].key?(:code) &&
174
+ response[:error].key?(:message)
175
+ return CarrotRpc::Exception::InvalidResponse.new
176
+ end
177
+
178
+ CarrotRpc::Error.new(
179
+ code: response[:error][:code],
180
+ data: response[:error].key?(:data) ? response[:error][:data] : nil,
181
+ message: response[:error][:message]
182
+ )
183
+ end
184
+
160
185
  def publish_payload(payload, correlation_id:)
161
186
  # Reply To => make sure the service knows where to send it's response.
162
187
  # Correlation ID => identify the results that belong to the unique call made
@@ -18,8 +18,7 @@ class CarrotRpc::RpcServer
18
18
  @channel = config.bunny.create_channel
19
19
  @logger = config.logger
20
20
  @block = block
21
- queue_name = self.class.test_queue_name(self.class.queue_name, config.server_test_mode)
22
- @server_queue = @channel.queue(queue_name)
21
+ setup_queue(config)
23
22
  @exchange = @channel.default_exchange
24
23
  end
25
24
 
@@ -92,6 +91,11 @@ class CarrotRpc::RpcServer
92
91
  end
93
92
  end
94
93
 
94
+ def setup_queue(config)
95
+ queue_name = self.class.test_queue_name(self.class.queue_name, config.server_test_mode)
96
+ @server_queue = @channel.queue(queue_name, self.class.queue_options)
97
+ end
98
+
95
99
  def thread_request(request_message:)
96
100
  logger.debug "Threading request (#{request_message.inspect}) " \
97
101
  "in Thread.current.thread_variable_get(#{thread_request_variable.inspect})"
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module CarrotRpc
2
- VERSION = "0.8.0".freeze
3
+ VERSION = "1.0.0".freeze
3
4
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: carrot_rpc
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.0
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Scott Hamilton
@@ -9,22 +9,28 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2016-10-27 00:00:00.000000000 Z
12
+ date: 2017-05-16 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activesupport
16
16
  requirement: !ruby/object:Gem::Requirement
17
17
  requirements:
18
- - - "~>"
18
+ - - ">="
19
19
  - !ruby/object:Gem::Version
20
20
  version: '4.2'
21
+ - - "<"
22
+ - !ruby/object:Gem::Version
23
+ version: 6.x
21
24
  type: :runtime
22
25
  prerelease: false
23
26
  version_requirements: !ruby/object:Gem::Requirement
24
27
  requirements:
25
- - - "~>"
28
+ - - ">="
26
29
  - !ruby/object:Gem::Version
27
30
  version: '4.2'
31
+ - - "<"
32
+ - !ruby/object:Gem::Version
33
+ version: 6.x
28
34
  - !ruby/object:Gem::Dependency
29
35
  name: bunny
30
36
  requirement: !ruby/object:Gem::Requirement