diff options
author | Martin Gütlein <martin.guetlein@gmail.com> | 2010-04-19 14:03:29 +0200 |
---|---|---|
committer | Martin Gütlein <martin.guetlein@gmail.com> | 2010-04-19 14:03:29 +0200 |
commit | f4234893c238d298c09e921208c5431287899f8e (patch) | |
tree | 97565177fadc6ead370986c6377d49b46a48c215 /lib | |
parent | 7386c1b50448ad338b84628e1d585cefb05006f1 (diff) |
improved error handling
Diffstat (limited to 'lib')
-rw-r--r-- | lib/opentox-ruby-api-wrapper.rb | 2 | ||||
-rw-r--r-- | lib/owl.rb | 19 | ||||
-rw-r--r-- | lib/rest_client_wrapper.rb | 155 | ||||
-rw-r--r-- | lib/task.rb | 43 | ||||
-rw-r--r-- | lib/utils.rb | 52 |
5 files changed, 195 insertions, 76 deletions
diff --git a/lib/opentox-ruby-api-wrapper.rb b/lib/opentox-ruby-api-wrapper.rb index c795ca8..16c23fe 100644 --- a/lib/opentox-ruby-api-wrapper.rb +++ b/lib/opentox-ruby-api-wrapper.rb @@ -8,6 +8,6 @@ rescue LoadError puts "Please install Openbabel with 'rake openbabel:install' in the compound component" end -['owl', 'compound','dataset','algorithm','model','task','validation','utils','authorization','features'].each do |lib| +['owl', 'compound','dataset','algorithm','model','task','validation','utils','authorization','features', 'rest_client_wrapper'].each do |lib| require lib end @@ -62,16 +62,25 @@ module OpenTox @model.add @uri, DC[name], args.first else # getter #HACK for reading Panteli's models - if @uri.to_s =~ /ntua.*model|tu-muenchen.*model/ and !["title", "source", "identifier"].include?(name.to_s) - me = @model.subject(RDF['type'],OT['Model']) - #puts "going for "+name.to_s - return @model.object(me, OT[name.to_s]).uri.to_s + if @uri.to_s =~ /194.141.0.136.*model|ambit2.*model|ntua.*model|tu-muenchen.*model/ and !["title", "source", "identifier"].include?(name.to_s) + begin + me = @model.subject(RDF['type'],OT['Model']) + return @model.object(me, OT[name.to_s]).uri.to_s + rescue + LOGGER.warn "cannot get "+name.to_s+" from model" + return nil + end elsif @uri.to_s =~ /ambit.*task/ and ["hasStatus", "percentageCompleted"].include?(name.to_s) me = @model.subject(RDF['type'],OT['Task']) return @model.object(me, OT[name.to_s]).literal.value.to_s end #raise "stop there "+name.to_s - @model.object(@uri, DC[name.to_s]).to_s + val = @model.object(@uri, DC[name.to_s]) + if val.is_a?(Redland::Literal) + return val.value + else + return val.to_s + end end else raise "Method '#{name.to_s}' not found." diff --git a/lib/rest_client_wrapper.rb b/lib/rest_client_wrapper.rb new file mode 100644 index 0000000..1532a79 --- /dev/null +++ b/lib/rest_client_wrapper.rb @@ -0,0 +1,155 @@ +module OpenTox + + #PENDING: implement ot error api, move to own file + class Error + + attr_accessor :code, :body, :uri, :payload, :headers + + def initialize(code, body, uri, payload, headers) + self.code = code + self.body = body + self.uri = uri + self.payload = payload + self.headers = headers + end + + def self.parse(error_array_string) + begin + err = YAML.load(error_array_string) + if err.is_a?(Array) and err.size>0 and err[0].is_a?(Error) + return err + else + return nil + end + rescue + return nil + end + end + + end + + module RestClientWrapper + + # PENDING: remove as soon as redirect tasks are remove from partner webservices + def self.redirect_task( uri ) + raise "no redirect task uri: "+uri.to_s unless uri.to_s =~ /194.141.0.136|ambit.*task|tu-muenchen.*task/ + + while (uri.to_s =~ /194.141.0.136|ambit.*task|tu-muenchen.*task/) + #HACK handle redirect + LOGGER.debug "REDIRECT TASK: "+uri.to_s + redirect = "" + while (redirect.size == 0) + IO.popen("bin/redirect.sh "+uri.to_s) do |f| + while line = f.gets + redirect += line.chomp + end + end + raise "TASK ERROR" if $?!=0 + sleep 0.3 + end + uri = redirect + LOGGER.debug "REDIRECT TO: "+uri.to_s + end + return uri + end + + def self.get(uri, headers=nil, wait_for_task=false, curl_hack=false) + execute( "get", uri, nil, headers, wait_for_task, curl_hack ) + end + + def self.post(uri, payload=nil, headers=nil, wait_for_task=false, curl_hack=false) + execute( "post", uri, payload, headers, wait_for_task, curl_hack ) + end + + def self.delete(uri, headers=nil, wait_for_task=false, curl_hack=false) + execute( "delete", uri, nil, headers, wait_for_task, curl_hack ) + end + + private + def self.execute( rest_call, uri, payload, headers, wait_for_task=false, curl_hack=false ) + + do_halt 400,"uri is null",uri,payload,headers unless uri + begin + + payload.each{ |k,v| payload.delete(k) if v==nil } if payload #remove keys with empty values, as this can cause problems + unless curl_hack + if payload + result = RestClient.send(rest_call, uri, payload, headers) + else + result = RestClient.send(rest_call, uri, headers) + end + else + result = "" + cmd = " curl -v -X "+rest_call.upcase+" "+payload.collect{|k,v| "-d "+k.to_s+"='"+v.to_s+"' "}.join("")+" "+uri.to_s + LOGGER.debug "CURL HACK: "+cmd + IO.popen(cmd+" 2> /dev/null") do |f| + while line = f.gets + result += line + end + end + result.chomp!("\n") + LOGGER.debug "CURL -> "+result.to_s + raise "curl call failed "+result if $?!=0 + #raise "STOP "+result + end + + if wait_for_task + if result.to_s =~ /ambit.*task|tu-muenchen.*task/ + result = redirect_task(result) + elsif Utils.task_uri?(result) + task = OpenTox::Task.find(result) + task.wait_for_completion + raise task.description if task.failed? + result = task.resource + end + end + return result + + rescue RestClient::RequestFailed => ex + do_halt ex.http_code,ex.http_body,uri,payload,headers + rescue RestClient::RequestTimeout => ex + do_halt 408,ex.message,uri,payload,headers + rescue => ex + begin + code = ex.http_code + msg = ex.http_body + rescue + code = 500 + msg = ex.to_s + end + do_halt code,msg,uri,payload,headers + end + end + + def self.do_halt( code, body, uri, payload, headers ) + + #build error + causing_errors = Error.parse(body) + if causing_errors + error = causing_errors + [Error.new(code, "subsequent error", uri, payload, headers)] + else + error = [Error.new(code, body, uri, payload, headers)] + end + +# debug utility: write error to file +# error_dir = "/tmp/ot_errors" +# FileUtils.mkdir(error_dir) unless File.exist?(error_dir) +# raise "could not create error dir" unless File.exist?(error_dir) and File.directory?(error_dir) +# file_name = "error" +# time=Time.now.strftime("%m.%d.%Y-%H:%M:%S") +# count = 1 +# count+=1 while File.exist?(File.join(error_dir,file_name+"_"+time+"_"+count.to_s)) +# File.new(File.join(error_dir,file_name+"_"+time+"_"+count.to_s),"w").puts(body) + + # return error (by halting, halts should be logged) + # PENDING always return yaml for now + if defined?(halt) + halt(502,error.to_yaml) + elsif defined?($sinatra) + $sinatra.halt(502,error.to_yaml) + else + raise error.to_yaml + end + end + end +end diff --git a/lib/task.rb b/lib/task.rb index 75cc2d2..8b1ab5d 100644 --- a/lib/task.rb +++ b/lib/task.rb @@ -35,8 +35,12 @@ module OpenTox def finished_at RestClient.get File.join(@uri, 'finished_at') - end - + end + + def description + RestClient.get File.join(@uri, 'description') + end + def status RestClient.get File.join(@uri, 'status') end @@ -61,9 +65,10 @@ module OpenTox resource.put :resource => uri end - def failed + def failed(description) resource = RestClient::Resource.new(File.join(@uri,'failed'), :user => @@users[:users].keys[0], :password => @@users[:users].values[0]) - resource.put({}) + resource.put :description => description + #resource.put({}) end def parent=(task) @@ -92,19 +97,30 @@ module OpenTox end end - def self.as_task + def self.as_task(parent_task=nil) + #return yield + task = OpenTox::Task.create + task.parent = parent_task if parent_task LOGGER.debug "Starting task" pid = Spork.spork(:logger => LOGGER) do task.started LOGGER.debug "Task #{task.uri} started #{Time.now}" begin - result = yield + result = catch(:halt) do + yield task + end + if result && result.is_a?(Array) && result.size==2 && result[0]>202 + # halted while executing task + LOGGER.error "task was halted: "+result.inspect + task.failed(result[1]) + throw :halt,result + end task.completed(result) rescue => ex - raise ex - LOGGER.error ex.message - task.failed + #raise ex + LOGGER.error "task failed: "+ex.message + task.failed(ex.message) end raise "Invalid task state" unless task.completed? || task.failed? end @@ -113,15 +129,6 @@ module OpenTox task.uri end - def wait_for_resource - wait_for_completion - if failed? - LOGGER.error "task failed: "+uri.to_s - return nil - end - return resource - end - end end diff --git a/lib/utils.rb b/lib/utils.rb index a31e405..fa61a28 100644 --- a/lib/utils.rb +++ b/lib/utils.rb @@ -21,57 +21,5 @@ module OpenTox false end end - -end - - - module RestClientWrapper - - def self.get(uri, headers=nil) - execute( "get", uri, nil, headers ) - end - - def self.post(uri, payload=nil, headers=nil) - execute( "post", uri, payload, headers ) - end - - def self.delete(uri, headers=nil) - execute( "delete", uri, nil, headers ) - end - - private - def self.execute( rest_call, uri, payload, headers ) - - do_halt 400,"uri is null",uri,payload,headers unless uri - begin - if payload - RestClient.send(rest_call, uri, payload, headers) - else - RestClient.send(rest_call, uri, headers) - end - rescue RestClient::RequestFailed, RestClient::RequestTimeout => ex - do_halt 502,ex.message,uri,payload,headers - rescue SocketError, RestClient::ResourceNotFound => ex - do_halt 400,ex.message,uri,payload,headers - rescue Exception => ex - do_halt 500,"add error '"+ex.class.to_s+"'' to rescue in OpenTox::RestClientWrapper::execute(), msg: '"+ex.message.to_s+"'",uri,payload,headers - end - end - - def self.do_halt(status, msg, uri, payload, headers) - - message = msg+"" - message += ", uri: '"+uri.to_s+"'" if uri - message += ", payload: '"+payload.inspect+"'" if payload - message += ", headers: '"+headers.inspect+"'" if headers - - if defined?(halt) - halt(status,message) - elsif defined?($sinatra) - $sinatra.halt(status,message) - else - raise "halt '"+status.to_s+"' '"+message+"'" - end - end end end |