pipe_rpc 0.3.2 → 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/lib/pipe_rpc/client.rb +4 -13
- data/lib/pipe_rpc/client_request.rb +24 -0
- data/lib/pipe_rpc/client_request_error_response.rb +53 -0
- data/lib/pipe_rpc/client_request_response.rb +26 -0
- data/lib/pipe_rpc/client_request_result.rb +25 -0
- data/lib/pipe_rpc/client_request_result_response.rb +14 -0
- data/lib/pipe_rpc/error.rb +9 -2
- data/lib/pipe_rpc/error_response.rb +1 -46
- data/lib/pipe_rpc/gateway.rb +39 -0
- data/lib/pipe_rpc/hub.rb +5 -101
- data/lib/pipe_rpc/hub_clients.rb +12 -0
- data/lib/pipe_rpc/hub_message.rb +48 -0
- data/lib/pipe_rpc/hub_message_error_response.rb +22 -0
- data/lib/pipe_rpc/hub_request.rb +34 -0
- data/lib/pipe_rpc/{hub/responder/request/error.rb → hub_request_error.rb} +2 -3
- data/lib/pipe_rpc/{hub/responder/request/error_result.rb → hub_request_error_result.rb} +1 -5
- data/lib/pipe_rpc/{hub/responder/request/result.rb → hub_request_result.rb} +2 -6
- data/lib/pipe_rpc/hub_requests.rb +35 -0
- data/lib/pipe_rpc/hub_servers.rb +19 -0
- data/lib/pipe_rpc/hub_socket.rb +40 -0
- data/lib/pipe_rpc/hub_socket_incoming.rb +20 -0
- data/lib/pipe_rpc/hub_socket_outgoing.rb +21 -0
- data/lib/pipe_rpc/result_response.rb +0 -4
- data/lib/pipe_rpc/version.rb +1 -1
- metadata +20 -10
- data/lib/pipe_rpc/hub/message.rb +0 -57
- data/lib/pipe_rpc/hub/requester.rb +0 -31
- data/lib/pipe_rpc/hub/responder/request.rb +0 -35
- data/lib/pipe_rpc/hub/responder.rb +0 -39
- data/lib/pipe_rpc/socket.rb +0 -50
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: db3929008eaf1ac0b4d3d3d2f54ca17ea82ffa9c
|
4
|
+
data.tar.gz: 7737ad82b6cc89bb348179659b64617f28a5b1a1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5a70e27fe8b73c7630c1101f4234d78d991254965c598839622763bd5f37197294bbef0dbdaad93f0f3b35c5659f36f88157fbba6a9d8f5b0a809b8b96f0f70d
|
7
|
+
data.tar.gz: a4ebe6276e87fb6d8613c4f8f721c59c001e6f8635a029848ef0c3be912aaafe44c5f6015c7691af1400557c2d275b0fc2af09d1d7615f0f90c0c317947ff545
|
data/lib/pipe_rpc/client.rb
CHANGED
@@ -1,22 +1,13 @@
|
|
1
1
|
module PipeRpc
|
2
2
|
class Client < BasicObject
|
3
|
-
def initialize(
|
3
|
+
def initialize(server = :default, hub)
|
4
|
+
@server = server.to_sym
|
4
5
|
@hub = hub
|
5
|
-
@server = args.fetch(:server, :default).to_sym
|
6
6
|
end
|
7
7
|
|
8
8
|
def method_missing(method, *args)
|
9
|
-
|
10
|
-
|
11
|
-
@hub.request(server: @server, method: method, arguments: args) do |result|
|
12
|
-
if result.is_a? ::StandardError
|
13
|
-
result.set_backtrace(result.backtrace.to_a + backtrace.to_a) if result.respond_to? :set_backtrace
|
14
|
-
::Kernel.raise result
|
15
|
-
else
|
16
|
-
result
|
17
|
-
end
|
18
|
-
end
|
19
|
-
# Method won't return until we got a result because @hub.request starts a loop and blocks!
|
9
|
+
request = Client::Request.new(server: @server, method: method, arguments: args)
|
10
|
+
@hub.requests.evaluate(request)
|
20
11
|
end
|
21
12
|
|
22
13
|
def to_s
|
@@ -0,0 +1,24 @@
|
|
1
|
+
class PipeRpc::Request; end
|
2
|
+
|
3
|
+
module PipeRpc
|
4
|
+
class Client::Request < Request
|
5
|
+
def initialize(*args)
|
6
|
+
super
|
7
|
+
# discard first three entries mentioning Client::Request#initialize,
|
8
|
+
# Client::Request.new and Client#method_missing in stacktrace
|
9
|
+
@stacktrace = Kernel.respond_to?(:caller) ? Kernel.caller(3).to_a : []
|
10
|
+
@result = Result.new(self)
|
11
|
+
end
|
12
|
+
|
13
|
+
attr_reader :stacktrace, :result
|
14
|
+
|
15
|
+
def id=(id)
|
16
|
+
raise 'id already set' if @id
|
17
|
+
@id = id
|
18
|
+
end
|
19
|
+
|
20
|
+
def id
|
21
|
+
@id or raise 'id not set'
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
class PipeRpc::ErrorResponse; end
|
2
|
+
|
3
|
+
module PipeRpc
|
4
|
+
class Client::Request::ErrorResponse < ErrorResponse
|
5
|
+
def initialize(request, body)
|
6
|
+
@request = request
|
7
|
+
super body
|
8
|
+
end
|
9
|
+
|
10
|
+
def to_result
|
11
|
+
case @code
|
12
|
+
when -32601 then no_method_error
|
13
|
+
when -32602 then argument_error
|
14
|
+
when -32603 then internal_error
|
15
|
+
when -32604 then no_server_error
|
16
|
+
when -32605 then reflected_error
|
17
|
+
else unknown_error
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def no_method_error
|
24
|
+
method = @data.fetch(:method)
|
25
|
+
args = @data.fetch(:args)
|
26
|
+
NoMethodError.new("undefined method `#{method}' for <Client:#{@request.server}>", method, args)
|
27
|
+
end
|
28
|
+
|
29
|
+
def argument_error
|
30
|
+
ArgumentError.new(@data.fetch(:message))
|
31
|
+
end
|
32
|
+
|
33
|
+
def no_server_error
|
34
|
+
NoServerError.new("undefined server `#{@request.server}'")
|
35
|
+
end
|
36
|
+
|
37
|
+
def internal_error
|
38
|
+
InternalError.new(@data[:message]).tap do |error|
|
39
|
+
error.set_backtrace(@data[:backtrace]) if error.respond_to? :set_backtrace
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def reflected_error
|
44
|
+
ReflectedError.new(@data[:message]).tap do |error|
|
45
|
+
error.set_backtrace(@data[:backtrace]) if error.respond_to? :set_backtrace
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def unknown_error
|
50
|
+
UnknownError.new(@data[:message])
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module PipeRpc
|
2
|
+
class Client::Request
|
3
|
+
class Response
|
4
|
+
def initialize(hub, body)
|
5
|
+
@hub = hub
|
6
|
+
@body = body
|
7
|
+
end
|
8
|
+
|
9
|
+
attr_reader :body
|
10
|
+
|
11
|
+
def result?
|
12
|
+
@body.has_key? :result
|
13
|
+
end
|
14
|
+
|
15
|
+
def error?
|
16
|
+
@body.has_key? :error
|
17
|
+
end
|
18
|
+
|
19
|
+
def handle
|
20
|
+
type = result? ? ResultResponse : ErrorResponse
|
21
|
+
result = type.new(@hub.requests[@body[:id]], @body).to_result
|
22
|
+
@hub.requests.inject_result_for(@body[:id], result)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module PipeRpc
|
2
|
+
class Client::Request::Result
|
3
|
+
def initialize(request)
|
4
|
+
@request = request
|
5
|
+
end
|
6
|
+
|
7
|
+
def value=(result)
|
8
|
+
@received = true
|
9
|
+
@value = result
|
10
|
+
end
|
11
|
+
|
12
|
+
def received?
|
13
|
+
@received
|
14
|
+
end
|
15
|
+
|
16
|
+
def value
|
17
|
+
if @value.is_a? Exception
|
18
|
+
@value.set_backtrace(@value.backtrace.to_a + @request.stacktrace) if @value.respond_to? :set_backtrace
|
19
|
+
raise @value
|
20
|
+
else
|
21
|
+
@value
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
data/lib/pipe_rpc/error.rb
CHANGED
@@ -1,7 +1,14 @@
|
|
1
1
|
module PipeRpc
|
2
2
|
class Error < RuntimeError; end
|
3
|
-
class
|
3
|
+
class ClosedError < Error; end
|
4
|
+
class UnknownError < Error; end
|
5
|
+
|
6
|
+
class MessageError < Error; end
|
7
|
+
class MessageParseError < MessageError; end
|
8
|
+
class InvalidMessageError < MessageError; end
|
9
|
+
|
10
|
+
class NoRequestForResponseError < Error; end
|
4
11
|
class NoServerError < Error; end
|
12
|
+
class InternalError < Error; end
|
5
13
|
class ReflectedError < Error; end
|
6
|
-
class CanceledError < Error; end
|
7
14
|
end
|
@@ -5,7 +5,7 @@ module PipeRpc
|
|
5
5
|
error = args.fetch(:error)
|
6
6
|
@code = error.fetch(:code)
|
7
7
|
@message = msg_for(@code) || error.fetch(:message, 'Unknown error')
|
8
|
-
@data = error.fetch(:data,
|
8
|
+
@data = error.fetch(:data, {})
|
9
9
|
end
|
10
10
|
|
11
11
|
attr_reader :id, :code, :message, :data
|
@@ -14,15 +14,6 @@ module PipeRpc
|
|
14
14
|
{ id: id, error: { code: code, message: message, data: data } }
|
15
15
|
end
|
16
16
|
|
17
|
-
def native_error(request = nil)
|
18
|
-
@request = request
|
19
|
-
error_for(@code)
|
20
|
-
end
|
21
|
-
|
22
|
-
def result_for(*args)
|
23
|
-
native_error(*args)
|
24
|
-
end
|
25
|
-
|
26
17
|
private
|
27
18
|
|
28
19
|
def msg_for(code)
|
@@ -37,41 +28,5 @@ module PipeRpc
|
|
37
28
|
else nil
|
38
29
|
end
|
39
30
|
end
|
40
|
-
|
41
|
-
def error_for(code)
|
42
|
-
case code
|
43
|
-
when -32601 then no_method_error
|
44
|
-
when -32602 then argument_error
|
45
|
-
when -32604 then no_server_error
|
46
|
-
when -32605 then reflected_error
|
47
|
-
else internal_error
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
def no_method_error
|
52
|
-
method = @data.fetch(:method)
|
53
|
-
args = @data.fetch(:args)
|
54
|
-
NoMethodError.new("undefined method `#{method}' for <Client:#{@request.server}>", method, args)
|
55
|
-
end
|
56
|
-
|
57
|
-
def argument_error
|
58
|
-
ArgumentError.new(@data.fetch(:message))
|
59
|
-
end
|
60
|
-
|
61
|
-
def no_server_error
|
62
|
-
NoServerError.new("undefined server `#{@request.server}'")
|
63
|
-
end
|
64
|
-
|
65
|
-
def internal_error
|
66
|
-
InternalError.new(@data[:message]).tap do |error|
|
67
|
-
error.set_backtrace(@data[:backtrace]) if error.respond_to? :set_backtrace
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
|
-
def reflected_error
|
72
|
-
ReflectedError.new("#{@data[:message]}").tap do |error|
|
73
|
-
error.set_backtrace(@data[:backtrace]) if error.respond_to? :set_backtrace
|
74
|
-
end
|
75
|
-
end
|
76
31
|
end
|
77
32
|
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module PipeRpc
|
2
|
+
class Gateway
|
3
|
+
def initialize(args)
|
4
|
+
@hub = Hub.new(args)
|
5
|
+
end
|
6
|
+
|
7
|
+
def channel
|
8
|
+
@hub.channel
|
9
|
+
end
|
10
|
+
|
11
|
+
def servers
|
12
|
+
@hub.servers
|
13
|
+
end
|
14
|
+
|
15
|
+
def clients
|
16
|
+
@hub.clients
|
17
|
+
end
|
18
|
+
|
19
|
+
def loop_iteration=(iteration)
|
20
|
+
@hub.requests.wait_for_results_through(iteration)
|
21
|
+
end
|
22
|
+
|
23
|
+
def on_sent(&on_sent)
|
24
|
+
@hub.socket.on_sent(&on_sent)
|
25
|
+
end
|
26
|
+
|
27
|
+
def on_received(&on_received)
|
28
|
+
@hub.socket.on_received(&on_received)
|
29
|
+
end
|
30
|
+
|
31
|
+
def close
|
32
|
+
@hub.socket.close
|
33
|
+
end
|
34
|
+
|
35
|
+
def handle_message
|
36
|
+
@hub.handle_message
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
data/lib/pipe_rpc/hub.rb
CHANGED
@@ -3,111 +3,15 @@ module PipeRpc
|
|
3
3
|
def initialize(args)
|
4
4
|
@channel = args[:input]
|
5
5
|
@socket = Socket.new(self, args)
|
6
|
-
@
|
7
|
-
@
|
8
|
-
@clients =
|
9
|
-
self.loop_iteration = nil
|
6
|
+
@requests = Requests.new(self)
|
7
|
+
@servers = Servers.new
|
8
|
+
@clients = Clients.new(self)
|
10
9
|
end
|
11
10
|
|
12
|
-
attr_reader :channel
|
13
|
-
attr_accessor :logger
|
14
|
-
|
15
|
-
def log(msg)
|
16
|
-
if logger == :reflect
|
17
|
-
notify(server: :reflect_logger, method: :log, arguments: [msg])
|
18
|
-
elsif logger.respond_to? :debug
|
19
|
-
logger.debug msg
|
20
|
-
elsif logger
|
21
|
-
logger.call msg
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
def add_server(servers)
|
26
|
-
@responder.add_server(servers)
|
27
|
-
end
|
28
|
-
|
29
|
-
def rmv_server(server_name)
|
30
|
-
@responder.rmv_server(server_name)
|
31
|
-
end
|
32
|
-
|
33
|
-
def on_incoming_request(&on_request)
|
34
|
-
@responder.on_request(&on_request)
|
35
|
-
end
|
36
|
-
|
37
|
-
def client_for(server_name)
|
38
|
-
@clients[server_name] ||= Client.new(self, server: server_name)
|
39
|
-
end
|
40
|
-
|
41
|
-
def loop_iteration=(proc)
|
42
|
-
@loop_iteration = proc
|
43
|
-
end
|
44
|
-
|
45
|
-
def on_sent(&on_sent)
|
46
|
-
@socket.on_write(&on_sent)
|
47
|
-
end
|
48
|
-
|
49
|
-
def on_received(&on_received)
|
50
|
-
@socket.on_read(&on_received)
|
51
|
-
end
|
52
|
-
|
53
|
-
def notify(signature)
|
54
|
-
@socket.write @requester.notification(signature)
|
55
|
-
end
|
56
|
-
|
57
|
-
def cancel
|
58
|
-
@socket.close
|
59
|
-
@canceled = true
|
60
|
-
end
|
61
|
-
|
62
|
-
def request(signature, &on_result)
|
63
|
-
raise CanceledError.new if @canceled
|
64
|
-
|
65
|
-
result = nil
|
66
|
-
result_ready = false
|
67
|
-
|
68
|
-
request = @requester.request(signature) do |*response|
|
69
|
-
result = on_result.call(*response)
|
70
|
-
result_ready = true
|
71
|
-
end
|
72
|
-
@socket.write request
|
73
|
-
|
74
|
-
loop do
|
75
|
-
raise CanceledError.new if @canceled
|
76
|
-
return result if result_ready
|
77
|
-
@loop_iteration ? @loop_iteration.call : handle_message
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
|
-
def send_response(response)
|
82
|
-
@socket.write response
|
83
|
-
end
|
11
|
+
attr_reader :channel, :servers, :clients, :requests, :socket
|
84
12
|
|
85
13
|
def handle_message
|
86
|
-
|
87
|
-
|
88
|
-
return unless message
|
89
|
-
|
90
|
-
if message.notification?
|
91
|
-
@responder.handle_notification(message.handler)
|
92
|
-
elsif message.request?
|
93
|
-
@responder.handle_request(message.handler)
|
94
|
-
elsif message.response?
|
95
|
-
@requester.handle_response(message.handler)
|
96
|
-
elsif message.error?
|
97
|
-
raise message.handler.native_error
|
98
|
-
else
|
99
|
-
send_response ErrorResponse.new(id: nil, error: { code: -32600,
|
100
|
-
data: { message: 'no request, result or error' } })
|
101
|
-
end
|
102
|
-
end
|
103
|
-
|
104
|
-
private
|
105
|
-
|
106
|
-
def next_message
|
107
|
-
Message.new(self, @socket.read) # blocks
|
108
|
-
rescue => e
|
109
|
-
send_response ErrorResponse.new(id: nil, error: { code: -32700, data: { message: e.message } })
|
110
|
-
nil
|
14
|
+
Message.new(self, @socket.read).handle
|
111
15
|
end
|
112
16
|
end
|
113
17
|
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module PipeRpc
|
2
|
+
class Hub
|
3
|
+
class Message
|
4
|
+
def initialize(hub, body)
|
5
|
+
@hub = hub
|
6
|
+
@body = body
|
7
|
+
end
|
8
|
+
|
9
|
+
def request?
|
10
|
+
@body.has_key? :method
|
11
|
+
end
|
12
|
+
|
13
|
+
def response?
|
14
|
+
(@body.has_key? :error or @body.has_key? :result) and !!@body[:id]
|
15
|
+
end
|
16
|
+
|
17
|
+
def error?
|
18
|
+
@body.has_key? :error and @body[:id].nil?
|
19
|
+
end
|
20
|
+
|
21
|
+
def handler_type
|
22
|
+
if request?
|
23
|
+
Hub::Request
|
24
|
+
elsif response?
|
25
|
+
Client::Request::Response
|
26
|
+
elsif error?
|
27
|
+
Message::ErrorResponse
|
28
|
+
else
|
29
|
+
raise 'no request, result or error'
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def handler
|
34
|
+
handler_type.new(@hub, @body)
|
35
|
+
rescue => e
|
36
|
+
@hub.socket.write ErrorResponse.new(id: @body[:id], error: { code: -32600,
|
37
|
+
data: { message: e.message } })
|
38
|
+
nil
|
39
|
+
end
|
40
|
+
|
41
|
+
def handle
|
42
|
+
handler.tap do |handler|
|
43
|
+
handler.handle if handler
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
class PipeRpc::ErrorResponse; end
|
2
|
+
|
3
|
+
module PipeRpc
|
4
|
+
class Hub::Message::ErrorResponse < ErrorResponse
|
5
|
+
def initialize(hub, body)
|
6
|
+
@hub = hub
|
7
|
+
super body
|
8
|
+
end
|
9
|
+
|
10
|
+
def to_error
|
11
|
+
case @code
|
12
|
+
when -32700 then MessageParseError.new(@data.fetch(:message))
|
13
|
+
when -32600 then InvalidMessageError.new(@data.fetch(:message))
|
14
|
+
else UnknownError.new(@data[:message])
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def handle
|
19
|
+
raise to_error
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
class PipeRpc::Request; end
|
2
|
+
|
3
|
+
module PipeRpc
|
4
|
+
class Hub::Request < Request
|
5
|
+
def initialize(hub, body)
|
6
|
+
@hub = hub
|
7
|
+
super body
|
8
|
+
end
|
9
|
+
|
10
|
+
CALL_FILE, CALL_LINENO = __FILE__, __LINE__+4
|
11
|
+
def handle
|
12
|
+
evaluate_result do
|
13
|
+
# the block is passed for asynchronous evaluation
|
14
|
+
@hub.servers[server].__send__(method, *arguments, &evaluate_result_proc)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def evaluate_result(result = nil, &block)
|
19
|
+
result = Result.new(self, block_given? ? yield : result)
|
20
|
+
rescue Exception => e
|
21
|
+
result = ErrorResult.new(self, e)
|
22
|
+
ensure
|
23
|
+
asynchronous = result.value == evaluate_result_proc
|
24
|
+
@hub.socket.write(result.to_response) unless asynchronous
|
25
|
+
return result.value
|
26
|
+
end
|
27
|
+
|
28
|
+
def evaluate_result_proc
|
29
|
+
@evaluate_result_proc ||= proc do |result = nil, &block|
|
30
|
+
evaluate_result(result, &block)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
module PipeRpc
|
2
|
-
class Hub::
|
2
|
+
class Hub::Request
|
3
3
|
class Error
|
4
4
|
def initialize(error)
|
5
5
|
@error = error
|
@@ -13,8 +13,7 @@ module PipeRpc
|
|
13
13
|
when method_call_error? && NoMethodError then -32601
|
14
14
|
when method_call_error? && ArgumentError then -32602
|
15
15
|
when InternalError then -32605
|
16
|
-
|
17
|
-
else nil
|
16
|
+
else -32603
|
18
17
|
end
|
19
18
|
end
|
20
19
|
|
@@ -1,5 +1,5 @@
|
|
1
1
|
module PipeRpc
|
2
|
-
class Hub::
|
2
|
+
class Hub::Request
|
3
3
|
class ErrorResult
|
4
4
|
def initialize(request, error)
|
5
5
|
@request, @error = request, Error.new(error)
|
@@ -9,10 +9,6 @@ module PipeRpc
|
|
9
9
|
@error.error
|
10
10
|
end
|
11
11
|
|
12
|
-
def asynchronous?
|
13
|
-
false
|
14
|
-
end
|
15
|
-
|
16
12
|
def to_response
|
17
13
|
ErrorResponse.new(id: @request.id, error: { code: @error.code, data: { message: @error.message,
|
18
14
|
backtrace: @error.backtrace, method: @request.method, args: @request.arguments } })
|
@@ -1,17 +1,13 @@
|
|
1
1
|
module PipeRpc
|
2
|
-
class Hub::
|
2
|
+
class Hub::Request::Result
|
3
3
|
def initialize(request, result)
|
4
|
-
@request, @result = request, result
|
4
|
+
@request, @result, @async_responder = request, result
|
5
5
|
end
|
6
6
|
|
7
7
|
def value
|
8
8
|
@result
|
9
9
|
end
|
10
10
|
|
11
|
-
def asynchronous?
|
12
|
-
@result == @request.evaluate_result_proc
|
13
|
-
end
|
14
|
-
|
15
11
|
def to_response
|
16
12
|
ResultResponse.new(id: @request.id, result: @result)
|
17
13
|
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module PipeRpc
|
2
|
+
class Hub::Requests
|
3
|
+
def initialize(hub)
|
4
|
+
@hub = hub
|
5
|
+
@requests ={}
|
6
|
+
@uid = 0
|
7
|
+
wait_for_results_through nil
|
8
|
+
end
|
9
|
+
|
10
|
+
attr_reader :requests
|
11
|
+
|
12
|
+
def evaluate(request)
|
13
|
+
@uid += 1
|
14
|
+
request.id = @uid
|
15
|
+
@requests[@uid] = request
|
16
|
+
@hub.socket.write request
|
17
|
+
@wait.call until request.result.received?
|
18
|
+
request.result.value
|
19
|
+
end
|
20
|
+
|
21
|
+
def [](id)
|
22
|
+
@requests[id]
|
23
|
+
end
|
24
|
+
|
25
|
+
def inject_result_for(id, result)
|
26
|
+
request = @requests.delete(id)
|
27
|
+
raise NoRequestForResponseError.new("no request with id '#{id.inspect}'") unless request
|
28
|
+
request.result.value = result
|
29
|
+
end
|
30
|
+
|
31
|
+
def wait_for_results_through(iteration)
|
32
|
+
@wait = iteration.respond_to?(:call) ? iteration : proc{ @hub.handle_message }
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module PipeRpc
|
2
|
+
class Hub::Servers
|
3
|
+
def initialize
|
4
|
+
@servers = Hash.new{ |hash, key| raise NoServerError.new("no server #{key}") }
|
5
|
+
end
|
6
|
+
|
7
|
+
def add(servers)
|
8
|
+
servers.each{ |name, server| @servers[name.to_sym] = server }
|
9
|
+
end
|
10
|
+
|
11
|
+
def [](name)
|
12
|
+
@servers[name.to_sym]
|
13
|
+
end
|
14
|
+
|
15
|
+
def remove(name)
|
16
|
+
@servers.delete(name.to_sym)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module PipeRpc
|
2
|
+
class Hub::Socket
|
3
|
+
def initialize(hub, args = {})
|
4
|
+
@hub = hub
|
5
|
+
@input = args.fetch(:input)
|
6
|
+
@output = args.fetch(:output)
|
7
|
+
@on_sent = []
|
8
|
+
@on_received = []
|
9
|
+
end
|
10
|
+
|
11
|
+
def read
|
12
|
+
raise ClosedError if @input.closed?
|
13
|
+
incoming = Incoming.new(@input.gets) # blocks
|
14
|
+
incoming.trigger(@on_received)
|
15
|
+
incoming.to_h
|
16
|
+
rescue JSON::JSONError => e
|
17
|
+
write ErrorResponse.new(id: nil, error: { code: -32700, data: { message: e.message } })
|
18
|
+
end
|
19
|
+
|
20
|
+
def write(obj)
|
21
|
+
raise ClosedError if @output.closed?
|
22
|
+
outgoing = Outgoing.new(obj)
|
23
|
+
outgoing.trigger(@on_sent)
|
24
|
+
@output.puts outgoing.to_payload
|
25
|
+
end
|
26
|
+
|
27
|
+
def on_sent(&on_sent)
|
28
|
+
@on_sent << on_sent
|
29
|
+
end
|
30
|
+
|
31
|
+
def on_received(&on_received)
|
32
|
+
@on_received << on_received
|
33
|
+
end
|
34
|
+
|
35
|
+
def close
|
36
|
+
@input.close
|
37
|
+
@output.close
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module PipeRpc
|
2
|
+
class Hub::Socket
|
3
|
+
class Incoming
|
4
|
+
def initialize(payload)
|
5
|
+
@payload = payload
|
6
|
+
end
|
7
|
+
|
8
|
+
def to_h
|
9
|
+
@hash ||= JSON.load(@payload).symbolize_keys.tap do |hash|
|
10
|
+
hash[:error] = hash[:error].symbolize_keys if hash[:error]
|
11
|
+
hash[:error][:data] = hash[:error][:data].symbolize_keys if hash[:error] and hash[:error][:data]
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def trigger(callbacks)
|
16
|
+
callbacks.each{ |callback| callback.call(to_h) }
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module PipeRpc
|
2
|
+
class Hub::Socket
|
3
|
+
class Outgoing
|
4
|
+
def initialize(object)
|
5
|
+
@object = object
|
6
|
+
end
|
7
|
+
|
8
|
+
def to_h
|
9
|
+
@hash ||= @object.to_h
|
10
|
+
end
|
11
|
+
|
12
|
+
def to_payload
|
13
|
+
@payload ||= JSON.dump(to_h)
|
14
|
+
end
|
15
|
+
|
16
|
+
def trigger(callbacks)
|
17
|
+
callbacks.each{ |callback| callback.call(to_h) }
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
data/lib/pipe_rpc/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pipe_rpc
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Christopher Aue
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-04-
|
11
|
+
date: 2016-04-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: json
|
@@ -99,19 +99,29 @@ files:
|
|
99
99
|
- lib/hash.rb
|
100
100
|
- lib/pipe_rpc.rb
|
101
101
|
- lib/pipe_rpc/client.rb
|
102
|
+
- lib/pipe_rpc/client_request.rb
|
103
|
+
- lib/pipe_rpc/client_request_error_response.rb
|
104
|
+
- lib/pipe_rpc/client_request_response.rb
|
105
|
+
- lib/pipe_rpc/client_request_result.rb
|
106
|
+
- lib/pipe_rpc/client_request_result_response.rb
|
102
107
|
- lib/pipe_rpc/error.rb
|
103
108
|
- lib/pipe_rpc/error_response.rb
|
109
|
+
- lib/pipe_rpc/gateway.rb
|
104
110
|
- lib/pipe_rpc/hub.rb
|
105
|
-
- lib/pipe_rpc/
|
106
|
-
- lib/pipe_rpc/
|
107
|
-
- lib/pipe_rpc/
|
108
|
-
- lib/pipe_rpc/
|
109
|
-
- lib/pipe_rpc/
|
110
|
-
- lib/pipe_rpc/
|
111
|
-
- lib/pipe_rpc/
|
111
|
+
- lib/pipe_rpc/hub_clients.rb
|
112
|
+
- lib/pipe_rpc/hub_message.rb
|
113
|
+
- lib/pipe_rpc/hub_message_error_response.rb
|
114
|
+
- lib/pipe_rpc/hub_request.rb
|
115
|
+
- lib/pipe_rpc/hub_request_error.rb
|
116
|
+
- lib/pipe_rpc/hub_request_error_result.rb
|
117
|
+
- lib/pipe_rpc/hub_request_result.rb
|
118
|
+
- lib/pipe_rpc/hub_requests.rb
|
119
|
+
- lib/pipe_rpc/hub_servers.rb
|
120
|
+
- lib/pipe_rpc/hub_socket.rb
|
121
|
+
- lib/pipe_rpc/hub_socket_incoming.rb
|
122
|
+
- lib/pipe_rpc/hub_socket_outgoing.rb
|
112
123
|
- lib/pipe_rpc/request.rb
|
113
124
|
- lib/pipe_rpc/result_response.rb
|
114
|
-
- lib/pipe_rpc/socket.rb
|
115
125
|
- lib/pipe_rpc/version.rb
|
116
126
|
- pipe_rpc.gemspec
|
117
127
|
homepage: https://github.com/christopheraue/ruby-pipe_rpc
|
data/lib/pipe_rpc/hub/message.rb
DELETED
@@ -1,57 +0,0 @@
|
|
1
|
-
module PipeRpc
|
2
|
-
class Hub
|
3
|
-
class Message
|
4
|
-
def initialize(hub, message)
|
5
|
-
@hub = hub
|
6
|
-
@message = message
|
7
|
-
end
|
8
|
-
|
9
|
-
def notification?
|
10
|
-
@message.has_key? :method and not id?
|
11
|
-
end
|
12
|
-
|
13
|
-
def request?
|
14
|
-
@message.has_key? :method and id?
|
15
|
-
end
|
16
|
-
|
17
|
-
def response?
|
18
|
-
(result? or error_message?) and id?
|
19
|
-
end
|
20
|
-
|
21
|
-
def error?
|
22
|
-
error_message? and not id?
|
23
|
-
end
|
24
|
-
|
25
|
-
def handler
|
26
|
-
@handler ||= type.new(@message)
|
27
|
-
rescue => e
|
28
|
-
@hub.send_response ErrorResponse.new(id: nil, error: { code: -32600, data: { message: e.message } })
|
29
|
-
nil
|
30
|
-
end
|
31
|
-
|
32
|
-
private
|
33
|
-
|
34
|
-
def result?
|
35
|
-
@message.has_key? :result
|
36
|
-
end
|
37
|
-
|
38
|
-
def error_message?
|
39
|
-
@message.has_key? :error
|
40
|
-
end
|
41
|
-
|
42
|
-
def type
|
43
|
-
if error_message?
|
44
|
-
ErrorResponse
|
45
|
-
elsif result?
|
46
|
-
ResultResponse
|
47
|
-
else
|
48
|
-
Request
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
def id?
|
53
|
-
not @message[:id].nil?
|
54
|
-
end
|
55
|
-
end
|
56
|
-
end
|
57
|
-
end
|
@@ -1,31 +0,0 @@
|
|
1
|
-
module PipeRpc
|
2
|
-
class Hub
|
3
|
-
class Requester
|
4
|
-
def initialize(hub)
|
5
|
-
@hub = hub
|
6
|
-
@requests = {}
|
7
|
-
@uid = 0
|
8
|
-
end
|
9
|
-
|
10
|
-
def next_uid
|
11
|
-
@uid += 1
|
12
|
-
end
|
13
|
-
|
14
|
-
def notification(signature)
|
15
|
-
Request.new(signature)
|
16
|
-
end
|
17
|
-
|
18
|
-
def request(signature, &on_response)
|
19
|
-
request = Request.new(signature.merge(id: next_uid))
|
20
|
-
@requests[request.id] = { request: request, on_response: on_response }
|
21
|
-
request
|
22
|
-
end
|
23
|
-
|
24
|
-
def handle_response(response)
|
25
|
-
request = @requests.delete(response.id)
|
26
|
-
raise InternalError.new("no request for response(id: #{response.id})") unless request
|
27
|
-
request[:on_response].call response.result_for(request[:request])
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
@@ -1,35 +0,0 @@
|
|
1
|
-
module PipeRpc
|
2
|
-
class Hub::Responder
|
3
|
-
class Request
|
4
|
-
def initialize(responder, request)
|
5
|
-
@responder, @request = responder, request
|
6
|
-
end
|
7
|
-
|
8
|
-
def id
|
9
|
-
@request.id
|
10
|
-
end
|
11
|
-
|
12
|
-
CALL_FILE, CALL_LINENO = __FILE__, __LINE__+3
|
13
|
-
def handle
|
14
|
-
evaluate_result do
|
15
|
-
@responder.servers[@request.server].__send__(@request.method, *@request.arguments, &evaluate_result_proc)
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
def evaluate_result(result = nil, &block)
|
20
|
-
result = Result.new(self, block_given? ? yield : result)
|
21
|
-
rescue Exception => e
|
22
|
-
result = ErrorResult.new(@request, e)
|
23
|
-
ensure
|
24
|
-
@responder.send_response(result.to_response) unless result.asynchronous?
|
25
|
-
return result.value
|
26
|
-
end
|
27
|
-
|
28
|
-
def evaluate_result_proc
|
29
|
-
@evaluate_result_proc ||= proc do |result = nil, &block|
|
30
|
-
evaluate_result(result, &block)
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
@@ -1,39 +0,0 @@
|
|
1
|
-
module PipeRpc
|
2
|
-
class Hub
|
3
|
-
class Responder
|
4
|
-
def initialize(hub)
|
5
|
-
@hub = hub
|
6
|
-
@servers = Hash.new{ |hash, key| ::Kernel.raise NoServerError.new("no server #{key}") }
|
7
|
-
end
|
8
|
-
|
9
|
-
def servers
|
10
|
-
@servers.dup
|
11
|
-
end
|
12
|
-
|
13
|
-
def add_server(servers)
|
14
|
-
servers.each{ |name, server| @servers[name.to_sym] = server }
|
15
|
-
end
|
16
|
-
|
17
|
-
def rmv_server(server_name)
|
18
|
-
@servers.delete(server_name.to_sym)
|
19
|
-
end
|
20
|
-
|
21
|
-
def on_request(&on_request)
|
22
|
-
@on_request = on_request
|
23
|
-
end
|
24
|
-
|
25
|
-
def handle_notification(notification)
|
26
|
-
handle_request(notification)
|
27
|
-
end
|
28
|
-
|
29
|
-
def handle_request(request)
|
30
|
-
@on_request.call(request.server, request.method, request.arguments) if @on_request
|
31
|
-
Request.new(self, request).handle
|
32
|
-
end
|
33
|
-
|
34
|
-
def send_response(response)
|
35
|
-
@hub.send_response response
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
data/lib/pipe_rpc/socket.rb
DELETED
@@ -1,50 +0,0 @@
|
|
1
|
-
module PipeRpc
|
2
|
-
class Socket
|
3
|
-
def initialize(hub, args = {})
|
4
|
-
@hub = hub
|
5
|
-
@input = args.fetch(:input)
|
6
|
-
@output = args.fetch(:output)
|
7
|
-
on_write{}
|
8
|
-
on_read{}
|
9
|
-
end
|
10
|
-
|
11
|
-
def read
|
12
|
-
symbolize_message_keys(JSON.load(@input.gets)).tap do |message|
|
13
|
-
next if message[:server] == 'reflect_logger'
|
14
|
-
@hub.log "received: #{message.inspect}"
|
15
|
-
@on_read.call(message)
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
def write(obj)
|
20
|
-
raise InternalError.new('Output pipe broke') if @output.closed?
|
21
|
-
@output.puts(JSON.dump(obj.to_h.tap do |message|
|
22
|
-
next if @hub.logger == :reflect
|
23
|
-
@hub.log "sent: #{message.inspect}"
|
24
|
-
@on_write.call(message)
|
25
|
-
end))
|
26
|
-
end
|
27
|
-
|
28
|
-
def on_write(&on_write)
|
29
|
-
@on_write = on_write || proc{}
|
30
|
-
end
|
31
|
-
|
32
|
-
def on_read(&on_read)
|
33
|
-
@on_read = on_read || proc{}
|
34
|
-
end
|
35
|
-
|
36
|
-
def close
|
37
|
-
@input.close
|
38
|
-
@output.close
|
39
|
-
end
|
40
|
-
|
41
|
-
private
|
42
|
-
|
43
|
-
def symbolize_message_keys(message)
|
44
|
-
hash = message.symbolize_keys
|
45
|
-
hash[:error] = hash[:error].symbolize_keys if hash[:error]
|
46
|
-
hash[:error][:data] = hash[:error][:data].symbolize_keys if hash[:error] and hash[:error][:data]
|
47
|
-
hash
|
48
|
-
end
|
49
|
-
end
|
50
|
-
end
|