carrot_rpc 0.4.1 → 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/CHANGELOG.md +30 -0
- data/README.md +16 -3
- data/carrot_rpc.gemspec +2 -0
- data/lib/carrot_rpc/client_actions.rb +34 -0
- data/lib/carrot_rpc/configuration.rb +6 -3
- data/lib/carrot_rpc/error/code.rb +1 -1
- data/lib/carrot_rpc/exception.rb +5 -0
- data/lib/carrot_rpc/rpc_client.rb +72 -47
- data/lib/carrot_rpc/server_runner/pid.rb +1 -1
- data/lib/carrot_rpc/server_runner/signals.rb +1 -1
- data/lib/carrot_rpc/version.rb +1 -1
- data/lib/carrot_rpc.rb +2 -0
- metadata +18 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7021e60c18d67242d796d0a7989d0b6ba411bd2f
|
4
|
+
data.tar.gz: 2a857193768aafda74326c94339132e71d30ba65
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d244349b6f223b3bc3104075a766084054d7e15aab8d419c7e2a0c12c8cc63ac9b2554366ad56975dff3972463d40867aaa1a931c608a661695e25f6c358168f
|
7
|
+
data.tar.gz: 3f74c94e6af796112817eb92de1401767e837fe06ee4d9356473cffabdecb8ce8e896a16f86c3c74d007cd3f1fab899c8bbcca9a8f0f4f020031a6f35f60f248
|
data/CHANGELOG.md
CHANGED
@@ -34,6 +34,36 @@
|
|
34
34
|
# Changelog
|
35
35
|
All significant changes in the project are documented here.
|
36
36
|
|
37
|
+
## v.0.5.0
|
38
|
+
### Enhancements
|
39
|
+
* [#25](https://github.com/C-S-D/carrot_rpc/pull/25) - [shamil614](https://github.com/shamil614)
|
40
|
+
* Timeout RpcClient requests when response is not received.
|
41
|
+
* Default timeout is 5 seconds.
|
42
|
+
* Timeout is configurable.
|
43
|
+
* [#27](https://github.com/C-S-D/carrot_rpc/pull/27) - [shamil614](https://github.com/shamil614)
|
44
|
+
* Simplify RpcClient usage.
|
45
|
+
* Each request which goes through `RpcClient.remote_request` ultimately needs to use a unique `reply_queue` on eqch request.
|
46
|
+
* By closing the channel and opening a new channel on each request we ensure that cleanup takes place by the deletion of the `reply_queue`.
|
47
|
+
* [#29](https://github.com/C-S-D/carrot_rpc/pull/29) - [shamil614](https://github.com/shamil614)
|
48
|
+
* Implementations of the RpcClient need to be flexible with the key formatter.
|
49
|
+
* Formatting can be set globally via `Configuration`, overridden via passing Configuration object upon initializing client, or redefine `response_key_formatter` `request_key_formatter` methods.
|
50
|
+
|
51
|
+
### Incompatible Changes
|
52
|
+
* [#27](https://github.com/C-S-D/carrot_rpc/pull/27) - [shamil614](https://github.com/shamil614)
|
53
|
+
* Calling `rpc_client.start` and `rpc_client.channel.close` are no longer required when calling `rpc_client.remote_call` or the methods that call it (`index` `create`, etc).
|
54
|
+
* Calling `rpc_client.channel.close` after `rpc_client.remote_call` will cause an Exception to be raised as the channel is already closed.
|
55
|
+
* [#29](https://github.com/C-S-D/carrot_rpc/pull/29) - [shamil614](https://github.com/shamil614)
|
56
|
+
* Replaced hard coded key formatter in place of a configurable option.
|
57
|
+
* Need to set the following in config to maintain previous behavior
|
58
|
+
```ruby
|
59
|
+
CarrotRpc.configure do |config|
|
60
|
+
# RpcServers expect the params to be dashed.
|
61
|
+
config.rpc_client_request_key_format = :dasherize
|
62
|
+
# In most cases the RpcClient instances use JSONAPI::Resource classes and the keys need to be transformed.
|
63
|
+
config.rpc_client_response_key_format = :underscore
|
64
|
+
end
|
65
|
+
```
|
66
|
+
|
37
67
|
## v0.4.1
|
38
68
|
### Bug Fixes
|
39
69
|
* [#23](https://githb.com/C-S-D/carrot_rpc/pull/23) - [shamil614](https://github.com/shamil614)
|
data/README.md
CHANGED
@@ -86,6 +86,12 @@ CarrotRpc.configure do |config|
|
|
86
86
|
config.logger = CarrotRpc::TaggedLog.new(logger: Rails.logger, tags: ["Carrot RPC Client"])
|
87
87
|
# Set a Proc to allow manipulation of the params on the RpcClient before the request is sent.
|
88
88
|
config.before_request = proc { |params| params.merge(foo: "bar") }
|
89
|
+
# Number of seconds to wait before a RPC Client request timesout. Default 5 seconds.
|
90
|
+
config.rpc_client_timeout = 5
|
91
|
+
# Formats hash keys to stringified and replaces "_" with "-". Default is `:none` for no formatting.
|
92
|
+
config.rpc_client_request_key_format = :dasherize
|
93
|
+
# Formats hash keys to stringified and replaces "-" with "_". Default is `:none` for no formatting.
|
94
|
+
config.rpc_client_response_key_format = :underscore
|
89
95
|
|
90
96
|
# Don't use. Server implementation only. The values below are set via CLI:
|
91
97
|
# config.pidfile = nil
|
@@ -160,14 +166,21 @@ class CarsController < ApplicationController
|
|
160
166
|
|
161
167
|
def show
|
162
168
|
car_client = CarClient.new
|
163
|
-
car_client.start
|
164
169
|
result = car_client.show({id: 1})
|
165
|
-
# Good idea to clean up connections when finished.
|
166
|
-
car_client.channel.close
|
167
170
|
end
|
168
171
|
end
|
169
172
|
```
|
170
173
|
|
174
|
+
One way to implement a RpcClient is to override the default configuration.
|
175
|
+
```ruby
|
176
|
+
config = CarrotRPC.configuration.clone
|
177
|
+
# Now only this one object will format keys as dashes
|
178
|
+
config.rpc_client_response_key_format = :dasherize
|
179
|
+
|
180
|
+
car_client = CarClient.new(config)
|
181
|
+
```
|
182
|
+
By duplicating the `Configuration` instance you can override the global configuration and pass a custom configuration to the RpcClient instance.
|
183
|
+
|
171
184
|
### Support for JSONAPI::Resources
|
172
185
|
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.
|
173
186
|
|
data/carrot_rpc.gemspec
CHANGED
@@ -44,6 +44,8 @@ Gem::Specification.new do |spec|
|
|
44
44
|
spec.add_development_dependency "rspec"
|
45
45
|
# Style-checker
|
46
46
|
spec.add_development_dependency "rubocop", "~> 0.36.0"
|
47
|
+
# Documentation
|
48
|
+
spec.add_development_dependency "yard", "~> 0.8"
|
47
49
|
|
48
50
|
spec.required_ruby_version = "~> 2.2"
|
49
51
|
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# Methods similar to rails controller actions for RpcClient
|
2
|
+
module CarrotRpc::ClientActions
|
3
|
+
# Convience method as a resource alias for index action.
|
4
|
+
# To customize, override the method in your class.
|
5
|
+
#
|
6
|
+
# @param params [Hash] the arguments for the method being called.
|
7
|
+
def index(params)
|
8
|
+
remote_call("index", params)
|
9
|
+
end
|
10
|
+
|
11
|
+
# Convience method as a resource alias for show action.
|
12
|
+
# To customize, override the method in your class.
|
13
|
+
#
|
14
|
+
# @param params [Hash] the arguments for the method being called.
|
15
|
+
def show(params)
|
16
|
+
remote_call("show", params)
|
17
|
+
end
|
18
|
+
|
19
|
+
# Convience method as a resource alias for create action.
|
20
|
+
# To customize, override the method in your class.
|
21
|
+
#
|
22
|
+
# @param params [Hash] the arguments for the method being called.
|
23
|
+
def create(params)
|
24
|
+
remote_call("create", params)
|
25
|
+
end
|
26
|
+
|
27
|
+
# Convience method as a resource alias for update action.
|
28
|
+
# To customize, override the method in your class.
|
29
|
+
#
|
30
|
+
# @param params [Hash] the arguments for the method being called.
|
31
|
+
def update(params)
|
32
|
+
remote_call("update", params)
|
33
|
+
end
|
34
|
+
end
|
@@ -1,11 +1,11 @@
|
|
1
1
|
# Global configuration for {CarrotRpc}. Access with {CarrotRpc.configuration}.
|
2
2
|
class CarrotRpc::Configuration
|
3
3
|
attr_accessor :logger, :logfile, :loglevel, :daemonize, :pidfile, :runloop_sleep, :autoload_rails, :bunny,
|
4
|
-
:before_request
|
4
|
+
:before_request, :rpc_client_timeout, :rpc_client_response_key_format, :rpc_client_request_key_format
|
5
5
|
|
6
6
|
# logfile - set logger to a file. overrides rails logger.
|
7
7
|
|
8
|
-
def initialize
|
8
|
+
def initialize # rubocop:disable Metrics/MethodLength
|
9
9
|
@logfile = nil
|
10
10
|
@loglevel = Logger::DEBUG
|
11
11
|
@logger = nil
|
@@ -15,5 +15,8 @@ class CarrotRpc::Configuration
|
|
15
15
|
@autoload_rails = true
|
16
16
|
@bunny = nil
|
17
17
|
@before_request = nil
|
18
|
-
|
18
|
+
@rpc_client_timeout = 5
|
19
|
+
@rpc_client_response_key_format = :none
|
20
|
+
@rpc_client_request_key_format = :none
|
21
|
+
end # rubocop:enable Metrics/MethodLength
|
19
22
|
end
|
@@ -9,6 +9,7 @@ class CarrotRpc::RpcClient
|
|
9
9
|
attr_reader :channel, :server_queue, :logger
|
10
10
|
|
11
11
|
extend CarrotRpc::ClientServer
|
12
|
+
include CarrotRpc::ClientActions
|
12
13
|
|
13
14
|
def self.before_request(*proc)
|
14
15
|
if proc.length == 0
|
@@ -20,12 +21,44 @@ class CarrotRpc::RpcClient
|
|
20
21
|
end
|
21
22
|
end
|
22
23
|
|
23
|
-
#
|
24
|
-
#
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
24
|
+
# Logic to process the renaming of keys in a hash.
|
25
|
+
# @param format [Symbol] :dasherize changes keys that have "_" to "-"
|
26
|
+
# @param format [Symbol] :underscore changes keys that have "-" to "_"
|
27
|
+
# @param format [Symbol] :skip, will not rename the keys
|
28
|
+
# @param data [Hash] data structure to be transformed
|
29
|
+
# @return [Hash] the transformed data
|
30
|
+
def self.format_keys(format, data)
|
31
|
+
case format
|
32
|
+
when :dasherize
|
33
|
+
data.rename_keys("_", "-")
|
34
|
+
when :underscore
|
35
|
+
data.rename_keys("-", "_")
|
36
|
+
when :none
|
37
|
+
data
|
38
|
+
else
|
39
|
+
data
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
# Use defaults for application level connection to RabbitMQ.
|
44
|
+
#
|
45
|
+
# @example pass custom {Configuration} class as an argument to override.
|
46
|
+
# config = CarrotRpc::Configuration.new
|
47
|
+
# config.rpc_client_timeout = 10
|
48
|
+
# CarrotRpc::RpcClient.new(config)
|
49
|
+
def initialize(config = nil)
|
50
|
+
@config = config || CarrotRpc.configuration
|
51
|
+
@logger = @config.logger
|
52
|
+
end
|
53
|
+
|
54
|
+
# Starts the connection to listen for messages.
|
55
|
+
#
|
56
|
+
# All RpcClient requests go to the a single @server_queue
|
57
|
+
# Responses come back over a unique queue name.
|
58
|
+
def start
|
59
|
+
# Create a new channel on each request because the channel should be closed after each request.
|
60
|
+
@channel = @config.bunny.create_channel
|
61
|
+
|
29
62
|
# auto_delete => false keeps the queue around until RabbitMQ restarts or explicitly deleted
|
30
63
|
@server_queue = @channel.queue(self.class.queue_name, auto_delete: false)
|
31
64
|
|
@@ -33,8 +66,7 @@ class CarrotRpc::RpcClient
|
|
33
66
|
@exchange = @channel.default_exchange
|
34
67
|
end
|
35
68
|
|
36
|
-
|
37
|
-
def start
|
69
|
+
def subscribe
|
38
70
|
# Empty queue name ends up creating a randomly named queue by RabbitMQ
|
39
71
|
# Exclusive => queue will be deleted when connection closes. Allows for automatic "cleanup".
|
40
72
|
@reply_queue = @channel.queue("", exclusive: true)
|
@@ -45,9 +77,10 @@ class CarrotRpc::RpcClient
|
|
45
77
|
# setup subscribe block to Service
|
46
78
|
# block => false is a non blocking IO option.
|
47
79
|
@reply_queue.subscribe(block: false) do |_delivery_info, properties, payload|
|
48
|
-
response = JSON.parse(payload).
|
80
|
+
response = JSON.parse(payload).with_indifferent_access
|
49
81
|
|
50
82
|
result = parse_response(response)
|
83
|
+
result = response_key_formatter(result).with_indifferent_access if result.is_a? Hash
|
51
84
|
@results[properties[:correlation_id]].push(result)
|
52
85
|
end
|
53
86
|
end
|
@@ -61,20 +94,44 @@ class CarrotRpc::RpcClient
|
|
61
94
|
# @param params [Hash] the arguments for the method being called.
|
62
95
|
# @return [Object] the result of the method call.
|
63
96
|
def remote_call(remote_method, params)
|
97
|
+
start
|
98
|
+
subscribe
|
64
99
|
correlation_id = SecureRandom.uuid
|
65
100
|
params = self.class.before_request.call(params) if self.class.before_request
|
66
|
-
publish(correlation_id: correlation_id, method: remote_method, params: params
|
101
|
+
publish(correlation_id: correlation_id, method: remote_method, params: request_key_formatter(params))
|
67
102
|
wait_for_result(correlation_id)
|
68
103
|
end
|
69
104
|
|
70
105
|
def wait_for_result(correlation_id)
|
71
|
-
#
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
106
|
+
# Should be good to timeout here because we're blocking in the main thread here.
|
107
|
+
Timeout.timeout(@config.rpc_client_timeout, CarrotRpc::Exception::RpcClientTimeout) do
|
108
|
+
# `pop` is `Queue#pop`, so it is blocking on the receiving thread
|
109
|
+
# and this must happend before the `Hash.delete` or
|
110
|
+
# the receiving thread won't be able to find the correlation_id in @results
|
111
|
+
result = @results[correlation_id].pop
|
112
|
+
@results.delete correlation_id # remove item from hash. prevents memory leak.
|
113
|
+
result
|
114
|
+
end
|
115
|
+
ensure
|
116
|
+
@channel.close
|
117
|
+
end
|
118
|
+
|
119
|
+
# Formats keys in the response data.
|
120
|
+
# @param payload [Hash] response data received from the remote server.
|
121
|
+
# @return [Hash] formatted data structure.
|
122
|
+
def response_key_formatter(payload)
|
123
|
+
self.class.format_keys @config.rpc_client_response_key_format, payload
|
124
|
+
end
|
125
|
+
|
126
|
+
# Formats keys in the request data.
|
127
|
+
# @param payload [Hash] request data to be sent to the remote server.
|
128
|
+
# @return [Hash] formatted data structure.
|
129
|
+
def request_key_formatter(params)
|
130
|
+
self.class.format_keys @config.rpc_client_request_key_format, params
|
76
131
|
end
|
77
132
|
|
133
|
+
# A @reply_queue is deleted when the channel is closed.
|
134
|
+
# Closing the channel accounts for cleanup of the client @reply_queue.
|
78
135
|
def publish(correlation_id:, method:, params:)
|
79
136
|
message = message(
|
80
137
|
correlation_id: correlation_id,
|
@@ -96,38 +153,6 @@ class CarrotRpc::RpcClient
|
|
96
153
|
}
|
97
154
|
end
|
98
155
|
|
99
|
-
# Convience method as a resource alias for index action.
|
100
|
-
# To customize, override the method in your class.
|
101
|
-
#
|
102
|
-
# @param params [Hash] the arguments for the method being called.
|
103
|
-
def index(params)
|
104
|
-
remote_call("index", params)
|
105
|
-
end
|
106
|
-
|
107
|
-
# Convience method as a resource alias for show action.
|
108
|
-
# To customize, override the method in your class.
|
109
|
-
#
|
110
|
-
# @param params [Hash] the arguments for the method being called.
|
111
|
-
def show(params)
|
112
|
-
remote_call("show", params)
|
113
|
-
end
|
114
|
-
|
115
|
-
# Convience method as a resource alias for create action.
|
116
|
-
# To customize, override the method in your class.
|
117
|
-
#
|
118
|
-
# @param params [Hash] the arguments for the method being called.
|
119
|
-
def create(params)
|
120
|
-
remote_call("create", params)
|
121
|
-
end
|
122
|
-
|
123
|
-
# Convience method as a resource alias for update action.
|
124
|
-
# To customize, override the method in your class.
|
125
|
-
#
|
126
|
-
# @param params [Hash] the arguments for the method being called.
|
127
|
-
def update(params)
|
128
|
-
remote_call("update", params)
|
129
|
-
end
|
130
|
-
|
131
156
|
private
|
132
157
|
|
133
158
|
# Logic to find the data from the RPC response.
|
@@ -75,7 +75,7 @@ class CarrotRpc::ServerRunner::Pid
|
|
75
75
|
|
76
76
|
## Instance Methods
|
77
77
|
|
78
|
-
# Exits if
|
78
|
+
# Exits if status indicates server is already running, otherwise deletes {#path}.
|
79
79
|
#
|
80
80
|
# @return [void]
|
81
81
|
def check
|
data/lib/carrot_rpc/version.rb
CHANGED
data/lib/carrot_rpc.rb
CHANGED
@@ -18,9 +18,11 @@ module CarrotRpc
|
|
18
18
|
extend ActiveSupport::Autoload
|
19
19
|
|
20
20
|
autoload :CLI
|
21
|
+
autoload :ClientActions
|
21
22
|
autoload :ClientServer
|
22
23
|
autoload :Configuration
|
23
24
|
autoload :Error
|
25
|
+
autoload :Exception
|
24
26
|
autoload :HashExtensions
|
25
27
|
autoload :RpcClient
|
26
28
|
autoload :RpcServer
|
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.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Scott Hamilton
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2016-
|
12
|
+
date: 2016-05-02 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activesupport
|
@@ -109,6 +109,20 @@ dependencies:
|
|
109
109
|
- - "~>"
|
110
110
|
- !ruby/object:Gem::Version
|
111
111
|
version: 0.36.0
|
112
|
+
- !ruby/object:Gem::Dependency
|
113
|
+
name: yard
|
114
|
+
requirement: !ruby/object:Gem::Requirement
|
115
|
+
requirements:
|
116
|
+
- - "~>"
|
117
|
+
- !ruby/object:Gem::Version
|
118
|
+
version: '0.8'
|
119
|
+
type: :development
|
120
|
+
prerelease: false
|
121
|
+
version_requirements: !ruby/object:Gem::Requirement
|
122
|
+
requirements:
|
123
|
+
- - "~>"
|
124
|
+
- !ruby/object:Gem::Version
|
125
|
+
version: '0.8'
|
112
126
|
description: Streamlined approach to setting up RPC over RabbitMQ.
|
113
127
|
email:
|
114
128
|
- shamil614@gmail.com
|
@@ -138,10 +152,12 @@ files:
|
|
138
152
|
- circle.yml
|
139
153
|
- lib/carrot_rpc.rb
|
140
154
|
- lib/carrot_rpc/cli.rb
|
155
|
+
- lib/carrot_rpc/client_actions.rb
|
141
156
|
- lib/carrot_rpc/client_server.rb
|
142
157
|
- lib/carrot_rpc/configuration.rb
|
143
158
|
- lib/carrot_rpc/error.rb
|
144
159
|
- lib/carrot_rpc/error/code.rb
|
160
|
+
- lib/carrot_rpc/exception.rb
|
145
161
|
- lib/carrot_rpc/hash_extensions.rb
|
146
162
|
- lib/carrot_rpc/rpc_client.rb
|
147
163
|
- lib/carrot_rpc/rpc_server.rb
|