summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorMartin Gütlein <martin.guetlein@gmail.com>2010-04-19 14:03:29 +0200
committerMartin Gütlein <martin.guetlein@gmail.com>2010-04-19 14:03:29 +0200
commitf4234893c238d298c09e921208c5431287899f8e (patch)
tree97565177fadc6ead370986c6377d49b46a48c215 /lib
parent7386c1b50448ad338b84628e1d585cefb05006f1 (diff)
improved error handling
Diffstat (limited to 'lib')
-rw-r--r--lib/opentox-ruby-api-wrapper.rb2
-rw-r--r--lib/owl.rb19
-rw-r--r--lib/rest_client_wrapper.rb155
-rw-r--r--lib/task.rb43
-rw-r--r--lib/utils.rb52
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
diff --git a/lib/owl.rb b/lib/owl.rb
index c410f76..ec8c699 100644
--- a/lib/owl.rb
+++ b/lib/owl.rb
@@ -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