51 lines
1.2 KiB
Ruby
51 lines
1.2 KiB
Ruby
|
|
# rpc_client.rb
|
||
|
|
require 'ffi-rzmq'
|
||
|
|
require 'json'
|
||
|
|
require 'securerandom'
|
||
|
|
require 'timeout'
|
||
|
|
|
||
|
|
ENDPOINT = "ipc:///tmp/zmq-rpc-demo"
|
||
|
|
|
||
|
|
class RpcClient
|
||
|
|
def initialize(endpoint, timeout_ms: 2000)
|
||
|
|
@ctx = ZMQ::Context.new
|
||
|
|
@req = @ctx.socket(ZMQ::REQ)
|
||
|
|
|
||
|
|
@req.setsockopt(ZMQ::LINGER, 0)
|
||
|
|
|
||
|
|
rc = @req.connect(endpoint)
|
||
|
|
raise "connect failed: #{ZMQ::Util.error_string}" unless rc == 0
|
||
|
|
@poller = ZMQ::Poller.new
|
||
|
|
@poller.register_readable(@req)
|
||
|
|
@timeout = timeout_ms
|
||
|
|
end
|
||
|
|
|
||
|
|
def call(method, params=nil)
|
||
|
|
id = SecureRandom.uuid
|
||
|
|
payload = { jsonrpc: "2.0", id: id, method: method, params: params }.to_json
|
||
|
|
@req.send_string(payload)
|
||
|
|
|
||
|
|
# Wait for reply with timeout
|
||
|
|
rc = @poller.poll(@timeout)
|
||
|
|
raise Timeout::Error, "RPC timeout after #{@timeout}ms" if rc == 0
|
||
|
|
|
||
|
|
raw = ''
|
||
|
|
@req.recv_string(raw)
|
||
|
|
res = JSON.parse(raw)
|
||
|
|
|
||
|
|
if res["error"]
|
||
|
|
code = res["error"]["code"]
|
||
|
|
msg = res["error"]["message"]
|
||
|
|
data = res["error"]["data"]
|
||
|
|
raise StandardError, "RPC error (#{code}): #{msg}#{data ? " | #{data}" : ""}"
|
||
|
|
end
|
||
|
|
|
||
|
|
raise "Mismatched id" if res["id"] != id
|
||
|
|
res["result"]
|
||
|
|
end
|
||
|
|
|
||
|
|
def close
|
||
|
|
@req.close
|
||
|
|
@ctx.terminate
|
||
|
|
end
|
||
|
|
end
|