jrpc 0.4.6 → 1.0.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 +4 -4
- data/jrpc.gemspec +1 -1
- data/lib/jrpc/base_client.rb +47 -19
- data/lib/jrpc/tcp_client.rb +39 -23
- data/lib/jrpc/version.rb +1 -1
- metadata +4 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 88f3c2e9907a01e2628d9eb41bb96be8d683ab40
|
4
|
+
data.tar.gz: 8543544144a943094699050800dc5645402aa954
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8b4906aa2277f8e6dae407f222a206071cd8fe2979c869a0808945befe5093e44957f20ea55a8c78248777304198035c2574f08f18924ecd23d673abc3393e39
|
7
|
+
data.tar.gz: 3b43159a29ebf248714acede8b4a20cf83f629f14291b92d557da2c6ef5f846462feb62d1af98ba6436f4a1c0b676e043234a85ca970e8ed2ee19248efc8e912
|
data/jrpc.gemspec
CHANGED
@@ -18,7 +18,7 @@ Gem::Specification.new do |spec|
|
|
18
18
|
spec.require_paths = ['lib']
|
19
19
|
|
20
20
|
spec.add_dependency 'netstring', '~> 0'
|
21
|
-
spec.add_dependency 'net_tcp_client', '~>
|
21
|
+
spec.add_dependency 'net_tcp_client', '~> 2.0'
|
22
22
|
spec.add_dependency 'oj', '~> 2.0'
|
23
23
|
|
24
24
|
spec.add_development_dependency 'bundler', '~> 1.10'
|
data/lib/jrpc/base_client.rb
CHANGED
@@ -7,6 +7,7 @@ module JRPC
|
|
7
7
|
attr_reader :uri, :options
|
8
8
|
|
9
9
|
ID_CHARACTERS = (('a'..'z').to_a + ('0'..'9').to_a + ('A'..'Z').to_a).freeze
|
10
|
+
REQUEST_TYPES = [:request, :notification].freeze
|
10
11
|
|
11
12
|
def initialize(uri, options)
|
12
13
|
@uri = uri
|
@@ -17,31 +18,58 @@ module JRPC
|
|
17
18
|
invoke_request(method, *params)
|
18
19
|
end
|
19
20
|
|
20
|
-
def
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
21
|
+
def perform_request(method, params: nil, type: :request, read_timeout: nil, write_timeout: nil)
|
22
|
+
validate_request(params, type)
|
23
|
+
request = create_message(method.to_s, params)
|
24
|
+
if type == :request
|
25
|
+
id = generate_id
|
26
|
+
request['id'] = id
|
27
|
+
response = send_command serialize_request(request), read_timeout: read_timeout, write_timeout: write_timeout
|
28
|
+
response = deserialize_response(response)
|
29
|
+
|
30
|
+
validate_response(response, id)
|
31
|
+
parse_error(response['error']) if response.has_key?('error')
|
32
|
+
|
33
|
+
response['result']
|
34
|
+
else
|
35
|
+
send_notification serialize_request(request), write_timeout: write_timeout
|
36
|
+
nil
|
37
|
+
end
|
38
|
+
end
|
30
39
|
|
31
|
-
|
40
|
+
def invoke_request(method, *params)
|
41
|
+
warn '[DEPRECATION] `invoke_request` is deprecated. Please use `perform_request` instead.'
|
42
|
+
params = nil if params.empty?
|
43
|
+
perform_request(method, params: params)
|
32
44
|
end
|
33
45
|
|
34
46
|
def invoke_notification(method, *params)
|
35
|
-
|
36
|
-
nil
|
47
|
+
warn '[DEPRECATION] `invoke_request` is deprecated. Please use `perform_request` instead.'
|
48
|
+
params = nil if params.empty?
|
49
|
+
perform_request(method, params: params, type: :notification)
|
37
50
|
end
|
38
51
|
|
39
52
|
private
|
40
53
|
|
54
|
+
def serialize_request(request)
|
55
|
+
Oj.dump(request, mode: :compat)
|
56
|
+
end
|
57
|
+
|
58
|
+
def deserialize_response(response)
|
59
|
+
Oj.load(response)
|
60
|
+
end
|
61
|
+
|
41
62
|
def validate_response(response, id)
|
42
|
-
raise ClientError
|
43
|
-
raise ClientError
|
44
|
-
|
63
|
+
raise ClientError, 'Wrong response structure' unless response.is_a?(Hash)
|
64
|
+
raise ClientError, 'Wrong version' if response['jsonrpc'] != JRPC::JSON_RPC_VERSION
|
65
|
+
if id != response['id']
|
66
|
+
raise ClientError, "ID response mismatch. expected #{id.inspect} got #{response['id'].inspect}"
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def validate_request(params, type)
|
71
|
+
raise ClientError, 'invalid type' unless REQUEST_TYPES.include?(type)
|
72
|
+
raise ClientError, 'invalid params' if !params.nil? && !params.is_a?(Array) && !params.is_a?(Hash)
|
45
73
|
end
|
46
74
|
|
47
75
|
def parse_error(error)
|
@@ -63,11 +91,11 @@ module JRPC
|
|
63
91
|
end
|
64
92
|
end
|
65
93
|
|
66
|
-
def send_command(json)
|
94
|
+
def send_command(json, options={})
|
67
95
|
raise NotImplementedError
|
68
96
|
end
|
69
97
|
|
70
|
-
def send_notification(json)
|
98
|
+
def send_notification(json, options={})
|
71
99
|
raise NotImplementedError
|
72
100
|
end
|
73
101
|
|
@@ -81,7 +109,7 @@ module JRPC
|
|
81
109
|
'jsonrpc' => JSON_RPC_VERSION,
|
82
110
|
'method' => method
|
83
111
|
}
|
84
|
-
message['params'] = params unless params.
|
112
|
+
message['params'] = params unless params.nil?
|
85
113
|
message
|
86
114
|
end
|
87
115
|
end
|
data/lib/jrpc/tcp_client.rb
CHANGED
@@ -14,12 +14,18 @@ module JRPC
|
|
14
14
|
super
|
15
15
|
@logger = @options.delete(:logger) || Logger.new($null)
|
16
16
|
@namespace = @options.delete(:namespace).to_s
|
17
|
-
|
17
|
+
|
18
|
+
timeout = @options.fetch(:timeout, 5)
|
19
|
+
connect_timeout = @options.fetch(:connect_timeout, timeout)
|
20
|
+
read_timeout = @options.fetch(:read_timeout, timeout)
|
21
|
+
write_timeout = @options.fetch(:write_timeout, nil) # default 60
|
22
|
+
connect_retry_count = @options.fetch(:connect_retry_count, nil) # default 10
|
18
23
|
|
19
24
|
@transport = Net::TCPClient.new server: @uri,
|
20
|
-
connect_retry_count:
|
21
|
-
connect_timeout:
|
22
|
-
read_timeout:
|
25
|
+
connect_retry_count: connect_retry_count,
|
26
|
+
connect_timeout: connect_timeout,
|
27
|
+
read_timeout: read_timeout,
|
28
|
+
write_timeout: write_timeout,
|
23
29
|
buffered: false # recommended for RPC
|
24
30
|
rescue ::SocketError
|
25
31
|
raise ConnectionError, "Can't connect to #{@uri}"
|
@@ -27,48 +33,58 @@ module JRPC
|
|
27
33
|
|
28
34
|
private
|
29
35
|
|
30
|
-
def send_command(request)
|
36
|
+
def send_command(request, options={})
|
37
|
+
read_timeout = options.fetch(:read_timeout)
|
38
|
+
write_timeout = options.fetch(:write_timeout)
|
31
39
|
response = nil
|
32
40
|
t = Benchmark.realtime do
|
33
|
-
logger.debug "Request address: #{uri}"
|
34
|
-
logger.debug "Request message: #{Utils.truncate(request, MAX_LOGGED_MESSAGE_LENGTH)}"
|
35
|
-
|
36
|
-
|
41
|
+
logger.debug { "Request address: #{uri}" }
|
42
|
+
logger.debug { "Request message: #{Utils.truncate(request, MAX_LOGGED_MESSAGE_LENGTH)}" }
|
43
|
+
logger.debug { "Request read_timeout: #{read_timeout}" }
|
44
|
+
logger.debug { "Request write_timeout: #{write_timeout}" }
|
45
|
+
send_request(request, write_timeout)
|
46
|
+
response = receive_response(read_timeout)
|
47
|
+
end
|
48
|
+
logger.debug do
|
49
|
+
"(#{'%.2f' % (t * 1000)}ms) Response message: #{Utils.truncate(response, MAX_LOGGED_MESSAGE_LENGTH)}"
|
37
50
|
end
|
38
|
-
logger.debug "(#{'%.2f' % (t * 1000)}ms) Response message: #{Utils.truncate(response, MAX_LOGGED_MESSAGE_LENGTH)}"
|
39
51
|
response
|
40
52
|
end
|
41
53
|
|
42
|
-
def send_notification(request)
|
43
|
-
|
44
|
-
logger.debug "Request
|
45
|
-
|
46
|
-
logger.debug
|
54
|
+
def send_notification(request, options={})
|
55
|
+
write_timeout = options.fetch(:write_timeout)
|
56
|
+
logger.debug { "Request address: #{uri}" }
|
57
|
+
logger.debug { "Request message: #{Utils.truncate(request, MAX_LOGGED_MESSAGE_LENGTH)}" }
|
58
|
+
logger.debug { "Request write_timeout: #{write_timeout}" }
|
59
|
+
send_request(request, write_timeout)
|
60
|
+
logger.debug { 'No response required' }
|
47
61
|
end
|
48
62
|
|
49
63
|
def create_message(method, params)
|
50
64
|
super("#{namespace}#{method}", params)
|
51
65
|
end
|
52
66
|
|
53
|
-
def send_request(request)
|
54
|
-
@transport.
|
67
|
+
def send_request(request, timeout)
|
68
|
+
timeout ||= @transport.write_timeout
|
69
|
+
@transport.write Netstring.dump(request.to_s), timeout
|
55
70
|
rescue ::SocketError
|
56
71
|
raise ConnectionError, "Can't send request to #{uri}"
|
57
72
|
end
|
58
73
|
|
59
|
-
def receive_response
|
60
|
-
|
61
|
-
|
74
|
+
def receive_response(timeout)
|
75
|
+
timeout ||= @transport.read_timeout
|
76
|
+
length = get_msg_length(timeout)
|
77
|
+
response = @transport.read(length+1, nil, timeout)
|
62
78
|
raise ClientError.new('invalid response. missed comma as terminator') if response[-1] != ','
|
63
79
|
response.chomp(',')
|
64
80
|
rescue ::SocketError
|
65
81
|
raise ConnectionError, "Can't receive response from #{uri}"
|
66
82
|
end
|
67
83
|
|
68
|
-
def get_msg_length
|
84
|
+
def get_msg_length(timeout)
|
69
85
|
length = ''
|
70
86
|
while true do
|
71
|
-
character = @transport.read(1)
|
87
|
+
character = @transport.read(1, nil, timeout)
|
72
88
|
break if character == ':'
|
73
89
|
length += character
|
74
90
|
end
|
@@ -77,4 +93,4 @@ module JRPC
|
|
77
93
|
end
|
78
94
|
|
79
95
|
end
|
80
|
-
end
|
96
|
+
end
|
data/lib/jrpc/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: jrpc
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Denis Talakevich
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2017-08-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: netstring
|
@@ -30,20 +30,14 @@ dependencies:
|
|
30
30
|
requirements:
|
31
31
|
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '
|
34
|
-
- - ">="
|
35
|
-
- !ruby/object:Gem::Version
|
36
|
-
version: 1.0.2
|
33
|
+
version: '2.0'
|
37
34
|
type: :runtime
|
38
35
|
prerelease: false
|
39
36
|
version_requirements: !ruby/object:Gem::Requirement
|
40
37
|
requirements:
|
41
38
|
- - "~>"
|
42
39
|
- !ruby/object:Gem::Version
|
43
|
-
version: '
|
44
|
-
- - ">="
|
45
|
-
- !ruby/object:Gem::Version
|
46
|
-
version: 1.0.2
|
40
|
+
version: '2.0'
|
47
41
|
- !ruby/object:Gem::Dependency
|
48
42
|
name: oj
|
49
43
|
requirement: !ruby/object:Gem::Requirement
|