summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristoph Helma <helma@in-silico.ch>2012-05-09 16:32:07 +0000
committerChristoph Helma <helma@in-silico.ch>2012-05-09 16:32:07 +0000
commit347fe11fb64384462a7f434d487fca66b55d0e62 (patch)
tree7f3edb090b22f613941a7ecbccaa8f135448e0cb
parent4059b9ca4f768db6a1dece477b7d49be2e68d1dc (diff)
parente80386bf5e362a336c110d54f3838cdb81f4e6c3 (diff)
Merge branch 'feature/opentox-client' into development
-rw-r--r--Gemfile4
-rw-r--r--Rakefile1
-rw-r--r--VERSION1
-rw-r--r--application.rb327
-rw-r--r--config.ru12
-rw-r--r--public/robots.txt2
-rw-r--r--task.gemspec27
7 files changed, 93 insertions, 281 deletions
diff --git a/Gemfile b/Gemfile
new file mode 100644
index 0000000..36f1a90
--- /dev/null
+++ b/Gemfile
@@ -0,0 +1,4 @@
+source :gemcutter
+gemspec
+gem "opentox-server", :path => "~/opentox-server"
+gem "opentox-client", :path => "~/opentox-client"
diff --git a/Rakefile b/Rakefile
new file mode 100644
index 0000000..2995527
--- /dev/null
+++ b/Rakefile
@@ -0,0 +1 @@
+require "bundler/gem_tasks"
diff --git a/VERSION b/VERSION
new file mode 100644
index 0000000..3eefcb9
--- /dev/null
+++ b/VERSION
@@ -0,0 +1 @@
+1.0.0
diff --git a/application.rb b/application.rb
index 8c5b81a..e0a33ab 100644
--- a/application.rb
+++ b/application.rb
@@ -1,282 +1,65 @@
-require 'rubygems'
-gem "opentox-ruby", "~> 3"
-require 'opentox-ruby'
-
-set :lock, true
-
-class Task < Ohm::Model
-
- attribute :uri
- attribute :created_at
-
- attribute :finished_at
- attribute :due_to_time
- attribute :pid
-
- attribute :resultURI
- attribute :percentageCompleted
- attribute :hasStatus
- attribute :title
- attribute :creator
- attribute :description
-
- attribute :waiting_for
-
- attribute :error_report_yaml
-
- # convenience method to store object in redis
- def errorReport
- YAML.load(self.error_report_yaml) if self.error_report_yaml
- end
-
- # convenience method to store object in redis
- def errorReport=(er)
- self.error_report_yaml = er.to_yaml
- end
-
-
- def metadata
- {
- DC.creator => creator,
- DC.title => title,
- DC.date => created_at,
- OT.hasStatus => hasStatus,
- OT.resultURI => resultURI,
- OT.percentageCompleted => percentageCompleted.to_f,
- #text fields are lazy loaded, using member variable can cause description to be nil
- DC.description => description
- #:due_to_time => @due_to_timer
- }
- end
-
-end
-
-#DataMapper.auto_upgrade!
-
-# Get a list of all tasks
-# @return [text/uri-list] List of all tasks
-get '/?' do
- LOGGER.debug "list all tasks "+params.inspect
- if request.env['HTTP_ACCEPT'] =~ /html/
- response['Content-Type'] = 'text/html'
- OpenTox.text_to_html Task.all.sort.collect{|t| t.uri}.join("\n") + "\n"
- else
- response['Content-Type'] = 'text/uri-list'
- Task.all.collect{|t| t.uri}.join("\n") + "\n"
- end
-end
+module OpenTox
+ class Application < Service
+
+ helpers do
+ def status_code uri
+ sparql = "SELECT ?o WHERE { GRAPH <#{uri}> { <#{uri}> <#{RDF::OT.hasStatus}> ?o. } }"
+ status = Backend::FourStore.query(sparql,nil).last.gsub(/"|'/,'').gsub(/\^\^.*$/,'')
+ case status
+ when "Completed"
+ 200
+ when "Running"
+ 202
+ when "Cancelled"
+ 503
+ when "Error"
+ sparql = "SELECT ?code WHERE { GRAPH <#{uri}> { <#{uri}> <#{RDF::OT.error}> ?error. ?error <#{RDF::OT.statusCode}> ?code } }"
+ code = Backend::FourStore.query(sparql,nil).last.to_i
+ code ? code : 500
+ end
+ end
-# Get task representation
-# @param [Header] Accept Mime type of accepted representation, may be one of `application/rdf+xml,application/x-yaml,text/uri-list`
-# @return [application/rdf+xml,application/x-yaml,text/uri-list] Task representation in requested format, Accept:text/uri-list returns URI of the created resource if task status is "Completed"
-get '/:id/?' do
- task = Task[params[:id]]
- raise OpenTox::NotFoundError.new "Task '#{params[:id]}' not found." unless task
-
- # set task http code according to status
- case task.hasStatus
- when "Running"
- code = 202
- when "Cancelled"
- code = 503
- when "Error"
- if task.errorReport
- code = task.errorReport.http_code.to_i
- else
- code = 500
end
- else #Completed
- code = 200
- end
-
- case request.env['HTTP_ACCEPT']
- when /yaml/
- response['Content-Type'] = 'application/x-yaml'
- metadata = task.metadata
- metadata[OT.waitingFor] = task.waiting_for
- metadata[OT.errorReport] = task.errorReport if task.errorReport
- halt code, metadata.to_yaml
- #halt code, task.created_at
- when /html/
- response['Content-Type'] = 'text/html'
- metadata = task.metadata
- description = task.title ? "This task computes '"+task.title+"'" : "This task performs a process that is running on the server."
- if task.hasStatus=="Running"
- description << "\nRefresh your browser (presss F5) to see if the task has finished."
- elsif task.hasStatus=="Completed"
- description << "\nThe task is completed, click on the link below to see your result."
- elsif task.errorReport
- description << "\nUnfortunately, the task has failed."
- end
- related_links = task.hasStatus=="Completed" ? "The task result: "+task.resultURI : nil
- metadata[OT.waitingFor] = task.waiting_for
- metadata[OT.errorReport] = task.errorReport if task.errorReport
- halt code, OpenTox.text_to_html(metadata.to_yaml, @subjectid, related_links, description)
- when /application\/rdf\+xml|\*\/\*/ # matches 'application/x-yaml', '*/*'
- response['Content-Type'] = 'application/rdf+xml'
- t = OpenTox::Task.new task.uri
- t.add_metadata task.metadata
- t.add_error_report task.errorReport if task.errorReport
- halt code, t.to_rdfxml
- when /text\/uri\-list/
- response['Content-Type'] = 'text/uri-list'
- if task.hasStatus=="Completed"
- halt code, task.resultURI
- else
- halt code, task.uri
- end
- else
- raise OpenTox::BadRequestError.new "MIME type '"+request.env['HTTP_ACCEPT'].to_s+"' not supported, valid Accept-Headers are \"application/rdf+xml\" and \"application/x-yaml\"."
- end
-end
-
-
-# Get Task properties. Works for
-# - /task/id
-# - /task/uri
-# - /task/created_at
-# - /task/finished_at
-# - /task/due_to_time
-# - /task/pid
-# - /task/resultURI
-# - /task/percentageCompleted
-# - /task/hasStatus
-# - /task/title
-# - /task/creator
-# - /task/description
-# @return [String] Task property
-get '/:id/:property/?' do
- response['Content-Type'] = 'text/plain'
- task = Task[params[:id]]
- raise OpenTox::NotFoundError.new"Task #{params[:id]} not found." unless task
- begin
- eval("task.#{params[:property]}").to_s
- rescue
- raise OpenTox::NotFoundError.new"Unknown task property #{params[:property]}."
- end
-end
-
-# Create a new task
-# @param [optional,String] max_duration
-# @param [optional,String] pid
-# @param [optional,String] resultURI
-# @param [optional,String] percentageCompleted
-# @param [optional,String] hasStatus
-# @param [optional,String] title
-# @param [optional,String] creator
-# @param [optional,String] description
-# @return [text/uri-list] URI for new task
-post '/?' do
- LOGGER.debug "Creating new task with params "+params.inspect
- max_duration = params.delete(:max_duration.to_s) if params.has_key?(:max_duration.to_s)
- params[:created_at] = Time.now
- params[:hasStatus] = "Running" unless params[:hasStatus]
- task = Task.create params
- task.update :uri => url_for("/#{task.id}", :full)
- #task.due_to_time = DateTime.parse((Time.parse(task.created_at.to_s) + max_duration.to_f).to_s) if max_duration
- #raise "Could not save task #{task.uri}" unless task.save
- response['Content-Type'] = 'text/uri-list'
- task.uri + "\n"
-end
-# Clean tasks. Delete every completed task older than 30 days
-delete '/cleanup' do
- begin
- tasklist = Task.all
- tasklist.each do |task|
- if task.metadata[OT.hasStatus] == 'Completed'
- task.delete if Time.now - Time.parse(task.created_at) > 2592000
- end
+ get '/task/:id/?' do
+ uri = uri("/task/#{params[:id]}")
+ rdf = FourStore.get(uri, request.env['HTTP_ACCEPT'])
+ halt status_code(uri), rdf
end
- rescue
- return false
- end
- return true
-end
-# Change task status. Possible URIs are: `
-# - /task/Cancelled
-# - /task/Completed: requires taskURI argument
-# - /task/Running
-# - /task/Error
-# - /task/pid: requires pid argument
-# IMPORTANT NOTE: Rack does not accept empty PUT requests. Please send an empty parameter (e.g. with -d '' for curl) or you will receive a "411 Length Required" error.
-# @param [optional, String] resultURI URI of created resource, required for /task/Completed
-# @param [optional, String] pid Task PID, required for /task/pid
-# @param [optional, String] description Task description
-# @param [optional, String] percentageCompleted progress value, can only be set while running
-# @return [] nil
-put '/:id/:hasStatus/?' do
-
- task = Task[params[:id]]
- raise OpenTox::NotFoundError.new"Task #{params[:id]} not found." unless task
- task.hasStatus = params[:hasStatus] unless /pid/ =~ params[:hasStatus]
- task.description = params[:description] if params[:description]
- # error report comes as yaml string
- task.error_report_yaml = params[:errorReport] if params[:errorReport]
-
- case params[:hasStatus]
- when "Completed"
- LOGGER.debug "Task " + params[:id].to_s + " completed"
- raise OpenTox::BadRequestError.new"no param resultURI when completing task" unless params[:resultURI]
- task.resultURI = params[:resultURI]
- task.finished_at = DateTime.now
- task.percentageCompleted = 100
- task.pid = nil
- when "pid"
- task.pid = params[:pid]
- when "Running"
- raise OpenTox::BadRequestError.new"Task cannot be set to running after not running anymore" if task.hasStatus!="Running"
- task.waiting_for = params[:waiting_for] if params.has_key?("waiting_for")
- if params.has_key?("percentageCompleted")
- task.percentageCompleted = params[:percentageCompleted].to_f
- #LOGGER.debug "Task " + params[:id].to_s + " set percentage completed to: "+params[:percentageCompleted].to_s
- end
- when /Cancelled|Error/
- if task.waiting_for and task.waiting_for.uri?
- # try cancelling the child task
- begin
- w = OpenTox::Task.find(task.waiting_for)
- w.cancel if w.running?
- rescue
+ put '/task/:id/:status/?' do
+ uri = uri("/task/#{params[:id]}")
+ sparql = []
+ case params[:status]
+ when "Completed"
+ bad_request_error "No resultURI parameter recieved. Cannot complete task '#{uri}' without resultURI." unless params[:resultURI]
+ sparql << "DELETE DATA { GRAPH <#{uri}> {<#{uri}> <#{RDF::OT.hasStatus}> \"Running\"}}"
+ sparql << "INSERT DATA { GRAPH <#{uri}> {<#{uri}> <#{RDF::OT.hasStatus}> \"Completed\"}}"
+ sparql << "INSERT DATA { GRAPH <#{uri}> {<#{uri}> <#{RDF::OT.resultURI}> <#{params[:resultURI]}>}}"
+ sparql << "INSERT DATA { GRAPH <#{uri}> {<#{uri}> <#{RDF::OT.percentageCompleted}> \"100.0\"}}"
+ sparql << "INSERT DATA { GRAPH <#{uri}> {<#{uri}> <#{RDF::OT.finished_at}> \"#{RDF::Literal.new(DateTime.now).to_s}\"}}"
+ when "Running"
+ sparql << "INSERT DATA { GRAPH <#{uri}> {<#{uri}> <#{RDF::OT.percentageCompleted}> \"#{params["percentageCompleted"].to_f}\"^^#{RDF::XSD.float}}" if params["percentageCompleted"]
+ #task.waiting_for = params[:waiting_for] if params.has_key?("waiting_for")
+ when "Cancelled"
+ sparql << "DELETE DATA { GRAPH <#{uri}> {<#{uri}> <#{RDF::OT.hasStatus}> \"Running\"}}"
+ sparql << "INSERT DATA { GRAPH <#{uri}> {<#{uri}> <#{RDF::OT.hasStatus}> \"Cancelled\"}}"
+ sparql << "INSERT DATA { GRAPH <#{uri}> {<#{uri}> <#{RDF::OT.finished_at}> \"#{DateTime.now}\"}}"
+ when "Error"
+ sparql << "DELETE DATA { GRAPH <#{uri}> {<#{uri}> <#{RDF::OT.hasStatus}> \"Running\"}}"
+ sparql << "INSERT DATA { GRAPH <#{uri}> {<#{uri}> <#{RDF::OT.hasStatus}> \"Error\"}}"
+ sparql << "INSERT DATA { GRAPH <#{uri}> {<#{uri}> <#{RDF::OT.finished_at}> \"#{DateTime.now}\"}}"
+ id = params[:errorReport].split("\n").first.sub(/^(_:\w+) .*/,'\1')
+ params[:errorReport] += "\n<#{uri}> <#{RDF::OT.error}> #{id} ."
+ Backend::FourStore.post uri, params[:errorReport], "text/plain" if params[:errorReport]
+ #if task.waiting_for and task.waiting_for.uri?
+ # try cancelling the child task
+ else
+ bad_request_error "Invalid status value: '"+params[:status].to_s+"'"
end
+ sparql.each{|q| Backend::FourStore.update q}
end
- LOGGER.debug("Aborting task '"+task.uri.to_s+"' with pid: '"+task.pid.to_s+"'")
- Process.kill(9,task.pid.to_i) unless task.pid.nil?
- task.pid = nil
- else
- raise OpenTox::BadRequestError.new"Invalid value for hasStatus: '"+params[:hasStatus].to_s+"'"
- end
-
- raise"could not save task" unless task.save
-end
-# Delete a task
-# @return [text/plain] Status message
-delete '/:id/?' do
- task = Task[params[:id]]
- raise OpenTox::NotFoundError.new "Task #{params[:id]} not found." unless task
- begin
- Process.kill(9,task.pid) unless task.pid.nil?
- task.delete
- response['Content-Type'] = 'text/plain'
- "Task #{params[:id]} deleted."
- rescue
- raise"Cannot kill task with pid #{task.pid}"
- end
+ end
end
-# Delete all tasks
-# @return [text/plain] Status message
-delete '/?' do
- Task.all.each do |task|
- begin
- Process.kill(9,task.pid.to_i) unless task.pid.nil?
- task.delete
- response['Content-Type'] = 'text/plain'
- "All tasks deleted."
- rescue
- "Cannot kill task with pid #{task.pid}"
- end
- end
-end
diff --git a/config.ru b/config.ru
index 8603270..72224f6 100644
--- a/config.ru
+++ b/config.ru
@@ -1,7 +1,5 @@
-require 'rubygems'
-require 'opentox-ruby'
-require 'config/config_ru'
-run Sinatra::Application
-set :raise_errors, false
-set :show_exceptions, false
-
+SERVICE = "task"
+require 'bundler'
+Bundler.require
+require './application.rb'
+run OpenTox::Application
diff --git a/public/robots.txt b/public/robots.txt
deleted file mode 100644
index 1f53798..0000000
--- a/public/robots.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-User-agent: *
-Disallow: /
diff --git a/task.gemspec b/task.gemspec
new file mode 100644
index 0000000..d1ac00d
--- /dev/null
+++ b/task.gemspec
@@ -0,0 +1,27 @@
+# -*- encoding: utf-8 -*-
+$:.push File.expand_path("../lib", __FILE__)
+
+Gem::Specification.new do |s|
+ s.name = "task"
+ s.version = File.read("./VERSION")
+ s.authors = ["Christoph Helma","Denis Gebele","Micha Rautenberg"]
+ s.email = ["helma@in-silico.ch","gebele@in-silico.ch","rautenenberg@in-silico.ch"]
+ s.homepage = "http://github.com/OpenTox/task"
+ s.summary = %q{Toxbank task service}
+ s.description = %q{Toxbank task service}
+ s.license = 'GPL-3'
+ #s.platform = Gem::Platform::CURRENT
+
+ s.rubyforge_project = "task"
+
+ s.files = `git ls-files`.split("\n")
+ #s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
+ #s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
+ #s.require_paths = ["lib"]
+ s.required_ruby_version = '>= 1.9.2'
+
+ # specify any dependencies here; for example:
+ s.add_runtime_dependency "opentox-server"
+ s.post_install_message = "Please configure your service in ~/.opentox/config/task.rb"
+end
+