Permalink
Browse files

Added session verification, also better retry handling of underlying …

…connection issues
  • Loading branch information...
1 parent e69c6a6 commit af0fa4bb4948c31145bb89076717e413181bcda2 @chicks chicks committed Aug 26, 2011
Showing with 76 additions and 21 deletions.
  1. +75 −21 lib/sugarcrm/connection/connection.rb
  2. +1 −0 lib/sugarcrm/exceptions.rb
@@ -65,41 +65,53 @@ def connect!
end
@connection.start
end
+ alias :reconnect! :connect!
# Send a request to the Sugar Instance
def send!(method, json)
nb_failed_attempts = 0 # how many times we have failed to send
@request = SugarCRM::Request.new(@url, method, json, @options[:debug])
+ # Send Ze Request
begin
if @request.length > 3900
@response = @connection.post(@url.path, @request)
else
@response = @connection.get(@url.path.dup + "?" + @request.to_s)
end
- rescue Timeout::Error, Errno::ECONNABORTED
+ return handle_response
+ # Timeouts are usually a server side issue
+ rescue Timeout::Error
nb_failed_attempts += 1
unless nb_failed_attempts >= 3
retry
else
raise
end
- rescue Errno::ECONNRESET, EOFError
+ # Lower level errors requiring a reconnect
+ rescue Errno::ECONNRESET, Errno::ECONNABORTED, Errno::EPIPE, EOFError
nb_failed_attempts += 1
unless nb_failed_attempts >= 3
retry!(method, json)
else
raise
end
+ # Handle invalid sessions
+ rescue SugarCRM::InvalidSession
+ nb_failed_attempts += 1
+ unless nb_failed_attempts >= 3
+ login!
+ retry
+ else
+ raise
+ end
end
- handle_response
end
# Sometimes our connection just disappears but we still have a session.
# This method forces a reconnect and relogin to update the session and resend
# the request.
def retry!(method, json)
- connect!
- login!
+ reconnect!
send!(method,json)
end
@@ -132,31 +144,73 @@ def handle_response
end
def process_response
- # Complain if our body is empty.
+ empty_body?
+ if response_contains_json?
+ return parse_response
+ else
+ return @response.body
+ end
+ end
+
+ def resolve_url
+ # Appends the rest.php path onto the end of the URL if it's not included
+ if @url.path !~ /rest.php$/
+ @url.path += URL
+ end
+ end
+
+ # Complain if our body is empty.
+ def empty_body?
raise SugarCRM::EmptyResponse unless @response.body
- # Some methods are dumb and don't return a JSON Response
- return @response.body if RESPONSE_IS_NOT_JSON.include? @request.method
+ end
+
+ # Some methods are dumb and don't return a JSON Response
+ def response_contains_json?
+ if RESPONSE_IS_NOT_JSON.include? @request.method
+ return false
+ end
+ true
+ end
+
+ def parse_response
begin
# Push it through the old meat grinder.
- response_json = JSON.parse(@response.body)
+ json = JSON.parse(@response.body)
rescue StandardError => e
+ # Complain if we can't parse
raise UnhandledResponse, @response.body
end
- # Empty result. Is this wise?
- return nil if response_json["result_count"] == 0
- # Filter debugging on REALLY BIG responses
- if @options[:debug] && !(DONT_SHOW_DEBUG_FOR.include? @request.method)
- puts "#{@request.method}: JSON Response:"
- pp response_json
- puts "\n"
+ # Check for an invalid session
+ invalid_session? json
+ # Check for an empty result set
+ if zero_results? json
+ return nil
+ end
+ nice_debugging_for json
+ json
+ end
+
+ # Check if we got an invalid session error back
+ # something like:
+ # {"name"=>"Invalid Session ID",
+ # "number"=>11,
+ # "description"=>"The session ID is invalid"}
+ def invalid_session?(json)
+ if json["name"]
+ raise SugarCRM::InvalidSession if json["name"] == "Invalid Session ID"
end
- return response_json
end
- def resolve_url
- # Appends the rest.php path onto the end of the URL if it's not included
- if @url.path !~ /rest.php$/
- @url.path += URL
+ def zero_results?(json)
+ json["result_count"] == 0
+ end
+
+ # Filter debugging on REALLY BIG responses
+ def nice_debugging_for(json)
+ if @options[:debug] && !(DONT_SHOW_DEBUG_FOR.include? @request.method)
+ puts "#{@request.method}: JSON Response:"
+ pp json
+ puts "\n"
end
end
@@ -1,6 +1,7 @@
module SugarCRM
class NoActiveSession < RuntimeError; end
class MultipleSessions < RuntimeError; end
+ class InvalidSession < RuntimeError; end
class LoginError < RuntimeError; end
class MissingCredentials < RuntimeError; end
class ConnectionTimeoutError < RuntimeError; end

0 comments on commit af0fa4b

Please sign in to comment.