summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/environment.rb8
-rw-r--r--lib/model.rb4
-rw-r--r--lib/owl.rb13
-rw-r--r--lib/rest_client_wrapper.rb72
-rw-r--r--lib/task.rb63
5 files changed, 90 insertions, 70 deletions
diff --git a/lib/environment.rb b/lib/environment.rb
index c86d2be..b46bf19 100644
--- a/lib/environment.rb
+++ b/lib/environment.rb
@@ -45,9 +45,11 @@ before {$sinatra = self unless $sinatra}
class Sinatra::Base
# overwriting halt to log halts (!= 202)
- def halt(status,msg)
- LOGGER.error "halt "+status.to_s+" "+msg.to_s if (status != 202)
- throw :halt, [status, msg]
+ def halt(*response)
+ LOGGER.error "halt "+response.first.to_s+" "+(response.size>1 ? response[1].to_s : "") if response.first >= 300
+ # orig sinatra code:
+ response = response.first if response.length == 1
+ throw :halt, response
end
end
diff --git a/lib/model.rb b/lib/model.rb
index 236de84..dfd5886 100644
--- a/lib/model.rb
+++ b/lib/model.rb
@@ -14,7 +14,7 @@ module OpenTox
def initialize(owl)
[:date, :creator, :title, :format, :algorithm, :dependentVariables,
:independentVariables, :predictedVariables, :trainingDataset].each do |a|
- self.send("#{a.to_s}=".to_sym, owl.get(a.to_s))
+ self.send("#{a.to_s}=".to_sym, owl.get(a.to_s))
end
@uri = owl.uri
RestClientWrapper.raise_uri_error "invalid model:\n"+
@@ -35,7 +35,7 @@ module OpenTox
LOGGER.debug "Build model, algorithm_uri:"+algorithm_uri.to_s+", algorithm_parms: "+algorithm_params.inspect.to_s
uri = OpenTox::RestClientWrapper.post(algorithm_uri,algorithm_params).to_s
- RestClientWrapper.raise_uri_error("Invalid build model result: "+uri.to_s, algorithm_uri, algorithm_params ) unless Utils.model_uri?(uri)
+ RestClientWrapper.raise_uri_error("Invalid build model result: '"+uri.to_s+"'", algorithm_uri, algorithm_params ) unless Utils.model_uri?(uri)
return PredictionModel.find(uri)
end
diff --git a/lib/owl.rb b/lib/owl.rb
index 17adb15..43d034d 100644
--- a/lib/owl.rb
+++ b/lib/owl.rb
@@ -36,7 +36,7 @@ module OpenTox
end
# loads owl from data
- def self.from_data(data, base_uri, ot_class, no_wrong_class_exception=false )
+ def self.from_data(data, base_uri, ot_class)
owl = OpenTox::Owl.new
parser = Redland::Parser.new
@@ -64,15 +64,8 @@ module OpenTox
unless owl.root_node
types = []
owl.model.find(nil, owl.node("type"), nil){ |s,p,o| types << o.to_s }
- msg = "root node for class '"+ot_class+"' not found (available type nodes: "+types.inspect+")"
- if no_wrong_class_exception
- LOGGER.debug "suppressing error: "+msg
- return nil
- else
- raise msg
- end
+ raise "root node for class '"+ot_class+"' not found (available type nodes: "+types.inspect+")"
end
-
raise "no uri in rdf: '"+owl.uri+"'" unless owl.uri and Utils.is_uri?(owl.uri)
owl.ot_class = ot_class
owl
@@ -98,6 +91,8 @@ module OpenTox
return nil unless val
if val.is_a?(Redland::Literal)
return val.value
+ elsif val.blank?
+ return nil
else
return val.uri.to_s
end
diff --git a/lib/rest_client_wrapper.rb b/lib/rest_client_wrapper.rb
index 7b3e148..f917e35 100644
--- a/lib/rest_client_wrapper.rb
+++ b/lib/rest_client_wrapper.rb
@@ -31,13 +31,13 @@ module OpenTox
end
class WrapperResult < String
- attr_accessor :content_type
+ attr_accessor :content_type, :code
end
class RestClientWrapper
- def self.get(uri, headers=nil)
- execute( "get", uri, headers)
+ def self.get(uri, headers=nil, wait=true)
+ execute( "get", uri, headers, nil, wait)
end
def self.post(uri, headers, payload=nil, wait=true)
@@ -79,35 +79,14 @@ module OpenTox
# result is a string, with the additional filed content_type
res = WrapperResult.new(result.to_s)
res.content_type = result.headers[:content_type]
+ res.code = result.code
- # get result cannot be a task
- return res if rest_call=="get" or !wait
- return res if res.strip.size==0
+ return res if res.code==200 || !wait
- # try to load task from result (maybe task-uri, or task-object)
- task = nil
- case res.content_type
- when /application\/rdf\+xml|text\/x-yaml/
- task = OpenTox::Task.from_data(res, res.content_type, uri, true)
- when /text\//
- return res if res.content_type=~/text\/uri-list/ and
- res.split("\n").size > 1 #if uri list contains more then one uri, its not a task
- task = OpenTox::Task.find(res.to_s) if Utils.task_uri?(res)
- else
- raise "unknown content-type when checking for task: "+res.content_type+" content: "+res[0..200]
- end
-
- # task could be loaded, wait for task to finish
- if task
- LOGGER.debug "result is a task '"+task.uri.to_s+"', wait for completion"
- task.wait_for_completion
- raise task.description unless task.completed?
- do_halt 502,"task resultURI is invalid: '"+task.resultURI.to_s+
- "'",task.uri,nil unless task.resultURI and Utils.is_uri?(task.resultURI)
- res = WrapperResult.new(task.resultURI)
- LOGGER.debug "task resultURI "+res.to_s
- res.content_type = "text/uri-list"
+ while (res.code==201 || res.code==202)
+ res = wait_for_task(res, uri)
end
+ raise "illegal status code: '"+res.code.to_s+"'" unless res.code==200
return res
rescue RestClient::RequestFailed => ex
@@ -128,6 +107,30 @@ module OpenTox
end
end
+ def self.wait_for_task( res, base_uri )
+
+ task = nil
+ case res.content_type
+ when /application\/rdf\+xml|text\/x-yaml/
+ task = OpenTox::Task.from_data(res, res.content_type, res.code, base_uri)
+ when /text\//
+ raise "uri list has more than one entry, should be a task" if res.content_type=~/text\/uri-list/ and
+ res.split("\n").size > 1 #if uri list contains more then one uri, its not a task
+ task = OpenTox::Task.find(res.to_s) if Utils.task_uri?(res)
+ else
+ raise "unknown content-type for task: "+res.content_type+" content: "+res[0..200]
+ end
+
+ LOGGER.debug "result is a task '"+task.uri.to_s+"', wait for completion"
+ task.wait_for_completion
+ raise task.description unless task.completed? # maybe task was cancelled / error
+
+ res = WrapperResult.new task.resultURI
+ res.code = task.http_code
+ res.content_type = "text/uri-list"
+ return res
+ end
+
def self.do_halt( code, body, uri, headers, payload=nil )
#build error
@@ -152,13 +155,14 @@ module OpenTox
# we are either in a task, or in sinatra
# PENDING: always return yaml for now
-
if $self_task #this global var in Task.as_task to mark that the current process is running in a task
raise error.to_yaml # the error is caught, logged, and task state is set to error in Task.as_task
- elsif $sinatra #else halt sinatra
- $sinatra.halt(502,error.to_yaml)
- else
- raise "internal error"
+ #elsif $sinatra #else halt sinatra
+ #$sinatra.halt(502,error.to_yaml)
+ elsif defined?(halt)
+ halt(502,error.to_yaml)
+ else #for testing purposes (if classes used directly)
+ raise error.to_yaml
end
end
end
diff --git a/lib/task.rb b/lib/task.rb
index 03d5330..b686d24 100644
--- a/lib/task.rb
+++ b/lib/task.rb
@@ -1,7 +1,7 @@
LOGGER.progname = File.expand_path(__FILE__)
-DEFAULT_TASK_MAX_DURATION = 120
-EXTERNAL_TASK_MAX_DURATION = 60
+DEFAULT_TASK_MAX_DURATION = 360
+EXTERNAL_TASK_MAX_DURATION = 120
$self_task=nil
@@ -12,7 +12,8 @@ module OpenTox
# due_to_time is only set in local tasks
TASK_ATTRIBS = [ :uri, :date, :title, :creator, :title, :description, :hasStatus, :percentageCompleted, :resultURI, :due_to_time ]
TASK_ATTRIBS.each{ |a| attr_accessor(a) }
-
+ attr_accessor :http_code
+
private
def initialize(uri)
@uri = uri.to_s.strip
@@ -31,24 +32,20 @@ module OpenTox
return task
end
- # test_if_task = true -> error suppressed if data is no task, nil is returned
- def self.from_data(data, content_type, base_uri, test_if_task)
+ def self.from_data(data, content_type, code, base_uri)
task = Task.new(nil)
- task.reload_from_data(data, content_type, base_uri, test_if_task)
- if test_if_task and (!task.uri or task.uri.strip.size==0)
- return nil
- else
- return task
- end
+ task.http_code = code
+ task.reload_from_data(data, content_type, base_uri)
+ return task
end
def reload
- result = RestClientWrapper.get(uri, {:accept => 'application/rdf+xml'})#'text/x-yaml'})
- reload_from_data(result, result.content_type, uri, false)
+ result = RestClientWrapper.get(uri, {:accept => 'application/rdf+xml'}, false)#'text/x-yaml'})
+ @http_code = result.code
+ reload_from_data(result, result.content_type, uri)
end
- # test_if_task = true -> error suppressed if data is no task, empty task is returned
- def reload_from_data( data, content_type, base_uri, test_if_task )
+ def reload_from_data( data, content_type, base_uri )
case content_type
when /text\/x-yaml/
task = YAML.load data
@@ -57,15 +54,13 @@ module OpenTox
send("#{a.to_s}=".to_sym,task[a])
end
when /application\/rdf\+xml/
- owl = OpenTox::Owl.from_data(data,base_uri,"Task",test_if_task)
- if owl
- self.uri = owl.uri
- (TASK_ATTRIBS-[:uri]).each{|a| self.send("#{a.to_s}=".to_sym, owl.get(a.to_s))}
- end
+ owl = OpenTox::Owl.from_data(data,base_uri,"Task")
+ self.uri = owl.uri
+ (TASK_ATTRIBS-[:uri]).each{|a| self.send("#{a.to_s}=".to_sym, owl.get(a.to_s))}
else
raise "content type for tasks not supported: "+content_type.to_s
end
- raise "uri is null after loading" unless @uri and @uri.to_s.strip.size>0 unless test_if_task
+ raise "uri is null after loading" unless @uri and @uri.to_s.strip.size>0
end
def cancel
@@ -104,20 +99,44 @@ module OpenTox
if (@uri.match(@@config[:services]["opentox-task"]))
due_to_time = Time.parse(@due_to_time)
+ running_time = due_to_time - Time.parse(@date)
else
# the date of the external task cannot be trusted, offest to local time might be to big
due_to_time = Time.new + EXTERNAL_TASK_MAX_DURATION
+ running_time = EXTERNAL_TASK_MAX_DURATION
end
LOGGER.debug "start waiting for task "+@uri.to_s+" at: "+Time.new.to_s+", waiting at least until "+due_to_time.to_s
+
while self.running?
sleep dur
reload
+ check_state
if (Time.new > due_to_time)
- raise "max waiting time exceeded, task seems to be stalled, task: '"+@uri.to_s+"'"
+ raise "max wait time exceeded ("+running_time.to_s+"sec), task: '"+@uri.to_s+"'"
end
end
+
+ LOGGER.debug "task no longer running: "+@uri.to_s+", result: "+@resultURI.to_s
end
+ def check_state
+ begin
+ raise "illegal task state, task is completed, resultURI is no URI: '"+@resultURI.to_s+
+ "'" unless @resultURI and Utils.is_uri?(@resultURI) if completed?
+
+ if @http_code == 202
+ raise "illegal task state, code is 202, but hasStatus is not Running: '"+@hasStatus+"'" unless running?
+ elsif @http_code == 201
+ raise "illegal task state, code is 201, but hasStatus is not Completed: '"+@hasStatus+"'" unless completed?
+ raise "illegal task state, code is 201, resultURI is no task-URI: '"+@resultURI.to_s+
+ "'" unless @resultURI and Utils.task_uri?(@resultURI)
+ end
+ rescue => ex
+ RestClientWrapper.raise_uri_error(ex.message, @uri)
+ end
+
+ end
+
# returns the task uri
# catches halts and exceptions, task state is set to error then
def self.as_task(max_duration=DEFAULT_TASK_MAX_DURATION)