summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authormguetlein <martin.guetlein@gmail.com>2011-01-24 17:19:56 +0100
committermguetlein <martin.guetlein@gmail.com>2011-01-24 17:19:56 +0100
commit59dba52a30de35da0122cd6c25777573faa5ffc3 (patch)
tree3ffe5534fb3f4ca4a801b45124a9966fe0f6d3dc /lib
parent0e759bee80e2668e1fec7b741a4ea18015f98b84 (diff)
fix error handling
Diffstat (limited to 'lib')
-rw-r--r--lib/error.rb67
-rw-r--r--lib/overwrite.rb18
-rw-r--r--lib/rest_client_wrapper.rb72
-rw-r--r--lib/task.rb36
4 files changed, 102 insertions, 91 deletions
diff --git a/lib/error.rb b/lib/error.rb
index e47ad62..8a57bd0 100644
--- a/lib/error.rb
+++ b/lib/error.rb
@@ -1,69 +1,52 @@
# adding additional fields to Exception class to format errors according to OT-API
class Exception
- attr_accessor :creator, :errorCause, :id, :http_code
+ attr_accessor :errorCause
def http_code; 500; end
end
module OpenTox
- class BadRequestError < Exception
+ class BadRequestError < RuntimeError
def http_code; 400; end
end
- class NotAuthorizedError < Exception
+ class NotAuthorizedError < RuntimeError
def http_code; 401; end
end
- class NotFoundError < Exception
+ class NotFoundError < RuntimeError
def http_code; 404; end
end
- class RestCallError < Exception
- attr_accessor :rest_code, :rest_body, :rest_uri, :rest_payload, :rest_headers
+ class RestCallError < RuntimeError
+ attr_accessor :rest_params
def http_code; 502; end
end
class ErrorReport
- # formats error according to accept-header, yaml is default
- # ( sets content-type in response accordingly )
- # @param [Exception] error
- # @param |Sinatra::Request, optional] request
- # @param [Sinatra::Response, optiona,] response, optional to set content-type
- # @return [String] formated error
- def self.format(error, request=nil, response=nil)
- # sets current uri
- error.creator = "#{request.env['rack.url_scheme']}://#{request.env['HTTP_HOST']}#{request.env['REQUEST_URI']}" if request
- # bit of a hack: set instance attribute in order to add it for the to_yaml conversion
- error.http_code = error.http_code
-
- accept = request.env['HTTP_ACCEPT'].to_s if request
- case accept
- # when /rdf/
- # TODO add error to rdf
- when /html/
- response['Content-Type'] = 'text/html' if response
- OpenTox.text_to_html error.to_yaml
- else
- response['Content-Type'] = 'application/x-yaml' if response
- error.to_yaml
- end
+ # TODO replace params with URIs (errorCause -> OT.errorCause)
+ attr_reader :message, :actor, :errorCause, :http_code, :errorDetails, :errorType
+
+ # creates a error report object, from an ruby-exception object
+ # @param [Exception] error
+ # @param [String] actor, URI of the call that cause the error
+ def initialize( error, actor )
+ @http_code = error.http_code
+ @errorType = error.class.to_s
+ @message = error.message
+ @actor = actor
+ @errorCause = error.errorCause if error.errorCause
+ @rest_params = error.rest_params if error.is_a?(OpenTox::RestCallError) and error.rest_params
+ end
+
+ def self.from_rdf(rdf)
+ raise "not yet implemented"
end
- # trys to parse error from text
- # @return [Exception] Exception if parsing sucessfull, nil otherwise
- def self.parse( body )
- begin
- err = YAML.load(body)
- if err and err.is_a?(Exception)
- return err
- else
- return nil
- end
- rescue
- return nil
- end
+ def self.to_rdf
+ raise "not yet implemented"
end
end
end \ No newline at end of file
diff --git a/lib/overwrite.rb b/lib/overwrite.rb
index 83d8099..4fa0829 100644
--- a/lib/overwrite.rb
+++ b/lib/overwrite.rb
@@ -19,8 +19,22 @@ error Exception do
# log error to logfile
LOGGER.error error.class.to_s+": "+error.message
# log backtrace only if code is 500 -> unwanted (Runtime)Exceptions and internal errors (see error.rb)
- LOGGER.error error.backtrace.join("\n") if error.http_code==500
- halt error.http_code,OpenTox::ErrorReport.format(error,request,response)
+ LOGGER.error ":\n"+error.backtrace.join("\n") if error.http_code==500
+
+ actor = "#{request.env['rack.url_scheme']}://#{request.env['HTTP_HOST']}#{request.env['REQUEST_URI']}"
+ rep = OpenTox::ErrorReport.new(error, actor)
+
+ case request.env['HTTP_ACCEPT']
+ when /rdf/
+ content_type 'application/rdf+xml'
+ halt error.http_code,rep.to_xml
+ when /html/
+ content_type 'text/html'
+ halt error.http_code,(OpenTox.text_to_html rep.to_yaml)
+ else
+ content_type 'application/x-yaml'
+ halt error.http_code,rep.to_yaml
+ end
end
class String
diff --git a/lib/rest_client_wrapper.rb b/lib/rest_client_wrapper.rb
index 3d7b72e..7c2d719 100644
--- a/lib/rest_client_wrapper.rb
+++ b/lib/rest_client_wrapper.rb
@@ -50,16 +50,6 @@ module OpenTox
execute( "delete", uri, headers, nil)
end
- # raises an Error message (rescued in overwrite.rb -> halt 502)
- # usage: if the return value of a call is invalid
- # @param [String] error_msg the error message
- # @param [String] uri destination URI that is responsible for the error
- # @param [optional,Hash] headers sent to the URI
- # @param [optional,String] payload data sent to the URI
- def self.raise_uri_error(error_msg, uri, headers=nil, payload=nil)
- raise_ot_error( nil, error_msg, nil, uri, headers, payload )
- end
-
private
def self.execute( rest_call, uri, headers, payload=nil, waiting_task=nil, wait=true )
@@ -70,7 +60,7 @@ module OpenTox
headers.each{ |k,v| headers.delete(k) if v==nil } if headers #remove keys with empty values, as this can cause problems
begin
- #LOGGER.debug "RestCall: "+rest_call.to_s+" "+uri.to_s+" "+headers.inspect
+ #LOGGER.debug "RestCall: "+rest_call.to_s+" "+uri.to_s+" "+headers.inspect+" "+payload.inspect
resource = RestClient::Resource.new(uri,{:timeout => 60})
if payload
result = resource.send(rest_call, payload, headers)
@@ -86,6 +76,7 @@ module OpenTox
raise "content-type not set" unless res.content_type
res.code = result.code
+ #LOGGER.debug "RestCall result: "+res.to_s+" "+res.code.to_s+" "+res.content_type.to_s
# TODO: Ambit returns task representation with 200 instead of result URI
return res if res.code==200 || !wait
@@ -96,11 +87,16 @@ module OpenTox
return res
rescue RestClient::RequestTimeout => ex
- raise_ot_error 408,ex.message,nil,ex.uri,headers,payload
+ received_error ex.message, 408, nil, {:rest_uri => uri, :headers => headers}
rescue RestClient::ExceptionWithResponse => ex
- raise_ot_error ex.http_code,ex.message,ex.http_body,uri,headers,payload
+ # error comming from a different webservice,
+ received_error ex.http_body, ex.http_code, ex.response.net_http_res.content_type, {:rest_uri => uri, :headers => headers}
+ rescue OpenTox::RestCallError => ex
+ # already a rest-error, probably comes from wait_for_task, just pass through
+ raise ex
rescue => ex
- raise_ot_error 500,ex.message,nil,uri,headers,payload
+ # some internal error occuring in rest_client_wrapper, just pass through
+ raise ex
end
end
@@ -121,27 +117,49 @@ module OpenTox
LOGGER.debug "result is a task '"+task.uri.to_s+"', wait for completion"
task.wait_for_completion waiting_task
- raise task.description unless task.completed? # maybe task was cancelled / error
-
+ unless task.completed? # maybe task was cancelled / error
+ if task.errorReport
+ received_error task.errorReport, task.http_code, nil, {:rest_uri => task.uri, :rest_code => task.http_code}
+ else
+ raise "task status: '"+task.status.to_s+"' but errorReport nil"
+ end
+ end
+
res = WrapperResult.new task.result_uri
res.code = task.http_code
res.content_type = "text/uri-list"
return res
end
- def self.raise_ot_error( code, message, body, uri, headers, payload=nil )
- error = OpenTox::RestCallError.new("REST call returned error: '"+message.to_s+"'")
- error.rest_code = code
- error.rest_uri = uri
- error.rest_headers = headers
- error.rest_payload = payload
- parsed = OpenTox::ErrorReport.parse(body) if body
- if parsed
- error.errorCause = parsed
+ def self.received_error( body, code, content_type=nil, params=nil )
+
+ # try to parse body
+ report = nil
+ if body.is_a?(OpenTox::ErrorReport)
+ report = body
+ else
+ case content_type
+ when /yaml/
+ report = YAML.load(body)
+ when /rdf/
+ report = OpenTox::ErrorReport.from_rdf(body)
+ end
+ end
+
+ unless report
+ # parsing was not successfull
+ # raise 'plain' RestCallError
+ err = OpenTox::RestCallError.new("REST call returned error: '"+body.to_s+"'")
+ err.rest_params = params
+ raise err
else
- error.rest_body = body
+ # parsing sucessfull
+ # raise RestCallError with parsed report as error cause
+ err = OpenTox::RestCallError.new("REST call subsequent error")
+ err.errorCause = report
+ err.rest_params = params
+ raise err
end
- raise error
end
end
end
diff --git a/lib/task.rb b/lib/task.rb
index d701c82..06d290f 100644
--- a/lib/task.rb
+++ b/lib/task.rb
@@ -56,26 +56,17 @@ module OpenTox
#raise "Server too busy to start a new task"
end
-
task_pid = Spork.spork(:logger => LOGGER) do
LOGGER.debug "Task #{task.uri} started #{Time.now}"
-
begin
- result = catch(:halt) do
- yield task
- end
- # catching halt, set task state to error
- if result && result.is_a?(Array) && result.size==2 && result[0]>202
- LOGGER.error "task was halted: "+result.inspect
- task.error(result[1])
- return
- end
+ result = yield task
LOGGER.debug "Task #{task.uri} done #{Time.now} -> "+result.to_s
task.completed(result)
- rescue => ex
- LOGGER.error "task failed: "+ex.message
- LOGGER.error ": "+ex.backtrace.join("\n")
- task.error(ex.message)
+ rescue => error
+ LOGGER.error "task failed: "+error.class.to_s+": "+error.message
+ # log backtrace only if code is 500 -> unwanted (Runtime)Exceptions and internal errors (see error.rb)
+ LOGGER.error ":\n"+error.backtrace.join("\n") if error.http_code==500
+ task.error(OpenTox::ErrorReport.new(error, creator))
end
end
task.pid = task_pid
@@ -127,6 +118,10 @@ module OpenTox
@metadata[DC.description]
end
+ def errorReport
+ @metadata[OT.errorReport]
+ end
+
def cancel
RestClientWrapper.put(File.join(@uri,'Cancelled'))
load_metadata
@@ -137,8 +132,9 @@ module OpenTox
load_metadata
end
- def error(description)
- RestClientWrapper.put(File.join(@uri,'Error'),{:description => description.to_s[0..2000]})
+ def error(error_report)
+ raise "no error report" unless error_report.is_a?(OpenTox::ErrorReport)
+ RestClientWrapper.put(File.join(@uri,'Error'),{:errorReport => error_report.to_yaml})
load_metadata
end
@@ -236,7 +232,7 @@ module OpenTox
end
end
- LOGGER.debug "Task '"+@metadata[OT.hasStatus]+"': "+@uri.to_s+", Result: "+@metadata[OT.resultURI].to_s
+ LOGGER.debug "Task '"+@metadata[OT.hasStatus].to_s+"': "+@uri.to_s+", Result: "+@metadata[OT.resultURI].to_s
end
# updates percentageCompleted value (can only be increased)
@@ -250,7 +246,7 @@ module OpenTox
load_metadata
end
end
-
+
private
def check_state
begin
@@ -265,7 +261,7 @@ module OpenTox
"'" unless @metadata[OT.resultURI] and @metadata[OT.resultURI].to_s.uri?
end
rescue => ex
- RestClientWrapper.raise_uri_error(ex.message, @uri)
+ raise OpenTox::BadRequestError.new ex.message+" (task-uri:"+@uri+")"
end
end