From 54338bd83cb6ca5a12fe31321d246845ed6802ea Mon Sep 17 00:00:00 2001 From: Anthony Martin <github@martin-studio.com> Date: Thu, 19 Jul 2018 12:40:49 -0700 Subject: [PATCH] refactor class level signatures cache to instance access --- lib/steem/api.rb | 38 +++++++++++++++++++++-------------- lib/steem/mixins/retriable.rb | 35 ++++++++++++++++++++------------ test/steem/broadcast_test.rb | 8 ++++++-- test/steem/jsonrpc_test.rb | 1 + 4 files changed, 52 insertions(+), 30 deletions(-) diff --git a/lib/steem/api.rb b/lib/steem/api.rb index ab69f1d..cdf6e80 100644 --- a/lib/steem/api.rb +++ b/lib/steem/api.rb @@ -1,6 +1,6 @@ module Steem # This ruby API works with - # {https://github.com/steemit/steem/releases steemd-0.19.4} and other AppBase + # {https://github.com/steemit/steem/releases steemd-0.19.10} and other AppBase # compatible upstreams. To access different API namespaces, use the # following: # @@ -36,7 +36,7 @@ module Steem # # Also see: {https://developers.steem.io/apidefinitions/ Complete API Definitions} class Api - attr_accessor :chain, :methods + attr_accessor :chain, :methods, :rpc_client # Use this for debugging naive thread handler. # DEFAULT_RPC_CLIENT_CLASS = RPC::HttpClient @@ -57,12 +57,17 @@ module Steem @api_name.to_s.split('_').map(&:capitalize).join end - def self.jsonrpc=(jsonrpc) - @jsonrpc = jsonrpc + def self.jsonrpc=(jsonrpc, url = nil) + @jsonrpc ||= {} + @jsonrpc[url || jsonrpc.rpc_client.uri.to_s] = jsonrpc end - def self.jsonrpc - @jsonrpc + def self.jsonrpc(url = nil) + if @jsonrpc.size < 2 && url.nil? + @jsonrpc.values.first + else + @jsonrpc[url] + end end # Override this if you want to use your own client. @@ -89,7 +94,7 @@ module Steem # have access to instance options until now. Api::jsonrpc = Jsonrpc.new(options) - @methods = Api::jsonrpc.get_api_methods + @methods = Api::jsonrpc(rpc_client.uri.to_s).get_api_methods unless !!@methods[@api_name] raise UnknownApiError, "#{@api_name} (known APIs: #{@methods.keys.join(' ')})" @@ -115,19 +120,22 @@ module Steem end private # @private - def self.args_keys_to_s(rpc_method_name) + def args_keys_to_s(rpc_method_name) args = signature(rpc_method_name).args args_keys = JSON[args.to_json] end # @private - def self.signature(rpc_method_name) + def signature(rpc_method_name) + url = rpc_client.uri.to_s + @@signatures ||= {} - @@signatures[rpc_method_name] ||= jsonrpc.get_signature(method: rpc_method_name).result + @@signatures[url] ||= {} + @@signatures[url][rpc_method_name] ||= Api::jsonrpc(url).get_signature(method: rpc_method_name).result end # @private - def self.raise_error_response(rpc_method_name, rpc_args, response) + def raise_error_response(rpc_method_name, rpc_args, response) raise UnknownError, "#{rpc_method_name}: #{response}" if response.error.nil? error = response.error @@ -153,9 +161,9 @@ module Steem when :condenser_api then args when :jsonrpc then args.first else - expected_args = Api::signature(rpc_method_name).args || [] + expected_args = signature(rpc_method_name).args || [] expected_args_key_string = if expected_args.size > 0 - " (#{Api::args_keys_to_s(rpc_method_name)})" + " (#{args_keys_to_s(rpc_method_name)})" end expected_args_size = expected_args.size @@ -178,11 +186,11 @@ module Steem args end - response = @rpc_client.rpc_execute(@api_name, m, rpc_args) + response = rpc_client.rpc_execute(@api_name, m, rpc_args) if defined?(response.error) && !!response.error if !!response.error.message - Api::raise_error_response rpc_method_name, rpc_args, response + raise_error_response rpc_method_name, rpc_args, response else raise Steem::ArgumentError, response.error.inspect end diff --git a/lib/steem/mixins/retriable.rb b/lib/steem/mixins/retriable.rb index 9f16944..b918488 100644 --- a/lib/steem/mixins/retriable.rb +++ b/lib/steem/mixins/retriable.rb @@ -13,24 +13,12 @@ module Steem IncorrectResponseIdError, RemoteDatabaseLockError ] - # Expontential backoff. - # - # @private - def backoff - @backoff ||= 0.1 - @backoff *= 2 - @backoff = 0.1 if @backoff > MAX_BACKOFF - - sleep @backoff - end - def can_retry?(e = nil) @retry_count ||= 0 - @first_retry_at ||= Time.now.utc return false if @retry_count >= MAX_RETRY_COUNT - @retry_count = if Time.now.utc - @first_retry_at > MAX_RETRY_ELAPSE + @retry_count = if retry_reset? @first_retry_at = nil else @retry_count + 1 @@ -45,5 +33,26 @@ module Steem can_retry end + private + # @private + def first_retry_at + @first_retry_at ||= Time.now.utc + end + + # @private + def retry_reset? + Time.now.utc - first_retry_at > MAX_RETRY_ELAPSE + end + + # Expontential backoff. + # + # @private + def backoff + @backoff ||= 0.1 + @backoff *= 2 + @backoff = 0.1 if @backoff > MAX_BACKOFF + + sleep @backoff + end end end diff --git a/test/steem/broadcast_test.rb b/test/steem/broadcast_test.rb index e88ca43..c8d198b 100644 --- a/test/steem/broadcast_test.rb +++ b/test/steem/broadcast_test.rb @@ -1084,12 +1084,16 @@ module Steem def test_can_retry e = NonCanonicalSignatureError.new("test") - assert Broadcast.send(:can_retry?, e) + + refute_nil Broadcast.send(:first_retry_at) + assert Broadcast.send(:can_retry?, e) unless Broadcast.send :retry_reset? end def test_can_retry_remote_node_error e = IncorrectResponseIdError.new("test: The json-rpc id did not match") - assert Broadcast.send(:can_retry?, e) + + refute_nil Broadcast.send(:first_retry_at) + assert Broadcast.send(:can_retry?, e) unless Broadcast.send :retry_reset? end end end \ No newline at end of file diff --git a/test/steem/jsonrpc_test.rb b/test/steem/jsonrpc_test.rb index d6de60d..78b3968 100644 --- a/test/steem/jsonrpc_test.rb +++ b/test/steem/jsonrpc_test.rb @@ -70,6 +70,7 @@ module Steem assert_raises SocketError, Errno::ECONNREFUSED do jsonrpc = Jsonrpc.new(url: 'https://bad.node') jsonrpc.get_methods + fail 'regression detected, SocketError or Errno::ECONNREFUSED expected' end end end -- GitLab