sequenceserver 1.1.0.beta3 → 1.1.0.beta4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/sequenceserver/api_errors.rb +2 -0
- data/lib/sequenceserver/blast/formatter.rb +8 -11
- data/lib/sequenceserver/blast/job.rb +10 -2
- data/lib/sequenceserver/blast/report.rb +3 -22
- data/lib/sequenceserver/job.rb +23 -17
- data/lib/sequenceserver/job_remover.rb +1 -1
- data/lib/sequenceserver/routes.rb +26 -7
- data/lib/sequenceserver/version.rb +1 -1
- data/public/css/sequenceserver.css +2 -1
- data/public/css/sequenceserver.min.css +3 -3
- data/public/js/errormodal.js +22 -10
- data/public/js/search.js +7 -5
- data/public/sequenceserver-report.min.js +1 -1
- data/public/sequenceserver-search.min.js +2 -2
- data/views/layout.erb +3 -5
- data/views/report.erb +1 -1
- data/views/search.erb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a526ad89575f0b9118bf986359b9750a2a1ef894
|
4
|
+
data.tar.gz: 3fa16082e5bb2b99c16be95413ba0fbdf722baf4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2b95e0a703717cd2af830462624dcea36c10b103cffaa3fb4f80e811abe54625a070d94caefe8c05f26fc59fa41ebaa06c80091b8a0b88b0286f8597d5cea2fd
|
7
|
+
data.tar.gz: 5a4e459777fe4ecf68e1f80c0aee8aadb8b231e2dd11bbee79b51ef16f1907c2b6ff69751552daa7bca3c927b38d5f92b9b9123ae537862a016e7b368011c8f2
|
@@ -11,20 +11,20 @@ module SequenceServer
|
|
11
11
|
extend Forwardable
|
12
12
|
def_delegators SequenceServer, :config, :logger, :sys
|
13
13
|
|
14
|
-
def initialize(
|
15
|
-
@
|
14
|
+
def initialize(job, type)
|
15
|
+
@job = job
|
16
16
|
@format, @mime, @specifiers = OUTFMT[type]
|
17
17
|
@type = type
|
18
18
|
|
19
19
|
validate && run
|
20
20
|
end
|
21
21
|
|
22
|
-
attr_reader :
|
22
|
+
attr_reader :job, :type
|
23
23
|
|
24
24
|
attr_reader :format, :mime, :specifiers
|
25
25
|
|
26
26
|
def file
|
27
|
-
@file ||= File.join(
|
27
|
+
@file ||= File.join(job.dir, filename)
|
28
28
|
end
|
29
29
|
|
30
30
|
def filename
|
@@ -37,7 +37,7 @@ module SequenceServer
|
|
37
37
|
def run
|
38
38
|
return if File.exist?(file)
|
39
39
|
command =
|
40
|
-
"blast_formatter -archive '#{
|
40
|
+
"blast_formatter -archive '#{job.stdout}'" \
|
41
41
|
" -outfmt '#{format} #{specifiers}'" \
|
42
42
|
" -out '#{file}'"
|
43
43
|
sys(command, path: config[:bin], dir: DOTDIR)
|
@@ -46,12 +46,9 @@ module SequenceServer
|
|
46
46
|
end
|
47
47
|
|
48
48
|
def validate
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
Incorrect request parameters. Please ensure that requested file name is
|
53
|
-
correct and the file type is either xml or tsv.
|
54
|
-
MSG
|
49
|
+
fail SystemError if !File.exist?(job.stdout) ||
|
50
|
+
File.zero?(job.stdout)
|
51
|
+
true
|
55
52
|
end
|
56
53
|
end
|
57
54
|
end
|
@@ -33,8 +33,16 @@ module SequenceServer
|
|
33
33
|
|
34
34
|
# BLAST's exit status is not definitive of success or error, so we
|
35
35
|
# override success? to define custom criteria. :TODO:
|
36
|
-
def
|
37
|
-
|
36
|
+
def raise!
|
37
|
+
return true if exitstatus == 0
|
38
|
+
|
39
|
+
stderr = File.readlines(this.stderr)
|
40
|
+
if exitstatus == 1 # error in query sequence or options; see [1]
|
41
|
+
error = stderr.grep(ERROR_LINE)
|
42
|
+
error = stderr if error.empty?
|
43
|
+
fail InputError, error.join
|
44
|
+
end
|
45
|
+
fail SystemError, stderr.join
|
38
46
|
end
|
39
47
|
|
40
48
|
private
|
@@ -43,27 +43,15 @@ module SequenceServer
|
|
43
43
|
|
44
44
|
# Generate report.
|
45
45
|
def generate
|
46
|
-
|
47
|
-
xml_ir = parse_xml File.read(Formatter.run(job
|
48
|
-
tsv_ir = parse_tsv File.read(Formatter.run(job
|
46
|
+
job.raise!
|
47
|
+
xml_ir = parse_xml File.read(Formatter.run(job, 'xml').file)
|
48
|
+
tsv_ir = parse_tsv File.read(Formatter.run(job, 'custom_tsv').file)
|
49
49
|
extract_program_info xml_ir
|
50
50
|
extract_params xml_ir
|
51
51
|
extract_stats xml_ir
|
52
52
|
extract_queries xml_ir, tsv_ir
|
53
53
|
end
|
54
54
|
|
55
|
-
def assert_job_completed_successfully
|
56
|
-
return true if job.success?
|
57
|
-
|
58
|
-
stderr = File.readlines(job.stderr)
|
59
|
-
if job.exitstatus == 1 # error in query sequence or options; see [1]
|
60
|
-
error = stderr.grep(ERROR_LINE)
|
61
|
-
error = stderr if error.empty?
|
62
|
-
fail InputError, error.join
|
63
|
-
end
|
64
|
-
fail SystemError, stderr.join
|
65
|
-
end
|
66
|
-
|
67
55
|
# Make program name and program name + version available via `program`
|
68
56
|
# and `program_version` attributes.
|
69
57
|
def extract_program_info(ir)
|
@@ -107,10 +95,6 @@ module SequenceServer
|
|
107
95
|
xml_ir[8].each do |n|
|
108
96
|
query = Query.new(self, n[0], n[2], n[3], [])
|
109
97
|
extract_hits(n[4], tsv_ir[query.id], query)
|
110
|
-
query.hits = query.hits.sort_by do |h|
|
111
|
-
first_hsp = h.hsps.first # most significant hsp
|
112
|
-
[first_hsp.evalue, first_hsp.score]
|
113
|
-
end
|
114
98
|
queries << query
|
115
99
|
end
|
116
100
|
end
|
@@ -131,9 +115,6 @@ module SequenceServer
|
|
131
115
|
hit = Hit.new(query, n[0], n[1], n[3], n[2], n[4],
|
132
116
|
tsv_ir[n[1]][0], tsv_ir[n[1]][1],[])
|
133
117
|
extract_hsps(n[5], tsv_ir[n[1]][2], hit)
|
134
|
-
hit.hsps = hit.hsps.sort_by do |h|
|
135
|
-
[h.evalue, h.score]
|
136
|
-
end
|
137
118
|
query.hits << hit
|
138
119
|
end
|
139
120
|
end
|
data/lib/sequenceserver/job.rb
CHANGED
@@ -63,6 +63,10 @@ module SequenceServer
|
|
63
63
|
mkdir_p dir
|
64
64
|
yield if block_given?
|
65
65
|
save
|
66
|
+
rescue Errno::ENOSPC
|
67
|
+
raise SystemError
|
68
|
+
rescue Errno::EACCES
|
69
|
+
raise SystemError
|
66
70
|
rescue => e
|
67
71
|
rm_rf dir
|
68
72
|
raise e
|
@@ -70,6 +74,12 @@ module SequenceServer
|
|
70
74
|
|
71
75
|
attr_reader :id, :completed_at, :exitstatus
|
72
76
|
|
77
|
+
# Returns shell command that will be executed. Subclass needs to provide a
|
78
|
+
# concrete implementation.
|
79
|
+
def command
|
80
|
+
raise "Not implemented."
|
81
|
+
end
|
82
|
+
|
73
83
|
# Shell out and execute the job.
|
74
84
|
#
|
75
85
|
# NOTE: This method is called asynchronously by thread pool.
|
@@ -80,10 +90,16 @@ module SequenceServer
|
|
80
90
|
done! e.exitstatus
|
81
91
|
end
|
82
92
|
|
83
|
-
#
|
84
|
-
|
85
|
-
|
86
|
-
|
93
|
+
# Is exitstatus of the job available? If yes, it means the job is done.
|
94
|
+
def done?
|
95
|
+
!!@exitstatus
|
96
|
+
end
|
97
|
+
|
98
|
+
# Raise RuntimeError if job finished with non-zero exit status. This method
|
99
|
+
# should be called on a completed job before attempting to use the results.
|
100
|
+
# Subclasses should provide their own implementation.
|
101
|
+
def raise!
|
102
|
+
raise if done? && exitstatus != 0
|
87
103
|
end
|
88
104
|
|
89
105
|
# Where will the stdout be written to during execution and read from later.
|
@@ -96,14 +112,9 @@ module SequenceServer
|
|
96
112
|
File.join(dir, 'stderr')
|
97
113
|
end
|
98
114
|
|
99
|
-
#
|
100
|
-
def
|
101
|
-
|
102
|
-
end
|
103
|
-
|
104
|
-
# Is the job done? Yes if exitstatus of the job is available. No otherwise.
|
105
|
-
def done?
|
106
|
-
!!@exitstatus
|
115
|
+
# Where to save all kind of data for this job.
|
116
|
+
def dir
|
117
|
+
File.join(DOTDIR, id)
|
107
118
|
end
|
108
119
|
|
109
120
|
private
|
@@ -144,11 +155,6 @@ module SequenceServer
|
|
144
155
|
save
|
145
156
|
end
|
146
157
|
|
147
|
-
# Where to save all kind of data for this job.
|
148
|
-
def dir
|
149
|
-
File.join(DOTDIR, id)
|
150
|
-
end
|
151
|
-
|
152
158
|
# Where to write serialised job object.
|
153
159
|
def yfile
|
154
160
|
File.join(dir, 'job.yaml')
|
@@ -8,7 +8,7 @@ module SequenceServer
|
|
8
8
|
# be deleted as soon as they are done, or it can be Infinity in which case
|
9
9
|
# jobs will never be deleted. Default is to delete finished jobs after 7 days.
|
10
10
|
class JobRemover
|
11
|
-
DEFAULT_JOB_LIFETIME =
|
11
|
+
DEFAULT_JOB_LIFETIME = 43200 # minutes (i.e., 30 days)
|
12
12
|
|
13
13
|
def initialize(job_lifetime)
|
14
14
|
@job_lifetime = job_lifetime || DEFAULT_JOB_LIFETIME
|
@@ -122,19 +122,38 @@ module SequenceServer
|
|
122
122
|
# Download BLAST report in various formats.
|
123
123
|
get '/download/:jid.:type' do |jid, type|
|
124
124
|
job = Job.fetch(jid)
|
125
|
-
out = BLAST::Formatter.new(job
|
125
|
+
out = BLAST::Formatter.new(job, type)
|
126
126
|
send_file out.file, :filename => out.filename, :type => out.mime
|
127
127
|
end
|
128
128
|
|
129
|
-
# Catches any exception raised within the app and returns
|
130
|
-
#
|
131
|
-
#
|
132
|
-
#
|
129
|
+
# Catches any exception raised within the app and returns JSON
|
130
|
+
# representation of the error:
|
131
|
+
# {
|
132
|
+
# title: ..., // plain text
|
133
|
+
# message: ..., // plain or HTML text
|
134
|
+
# more_info: ..., // pre-formatted text
|
135
|
+
# }
|
136
|
+
#
|
137
|
+
# If the error class defines `http_status` instance method, its return
|
138
|
+
# value will be used to set HTTP status. HTTP status is set to 500
|
139
|
+
# otherwise.
|
140
|
+
#
|
141
|
+
# If the error class defines `title` instance method, its return value
|
142
|
+
# will be used as title. Otherwise name of the error class is used as
|
143
|
+
# title.
|
144
|
+
#
|
145
|
+
# If the error class defines `more_info` instance method, its return
|
146
|
+
# value will be used as more_info, otherwise `backtrace.join("\n")`
|
147
|
+
# is used as more_info. If an error class does not want to include
|
148
|
+
# more_info (like for NotFound), the error class must undefine
|
149
|
+
# `backtrace` method.
|
150
|
+
#
|
151
|
+
# All error classes should define `message` instance method.
|
133
152
|
error 400..500 do
|
134
153
|
error = env['sinatra.error']
|
135
154
|
|
136
155
|
# All errors will have a message.
|
137
|
-
error_data = {message: error.message}
|
156
|
+
error_data = { message: error.message }
|
138
157
|
|
139
158
|
# If error object has a title method, use that, or use error class for
|
140
159
|
# title.
|
@@ -149,7 +168,7 @@ module SequenceServer
|
|
149
168
|
# more_info.
|
150
169
|
if error.respond_to? :more_info
|
151
170
|
error_data[:more_info] = error.more_info
|
152
|
-
|
171
|
+
elsif error.respond_to? :backtrace
|
153
172
|
error_data[:more_info] = error.backtrace.join("\n")
|
154
173
|
end
|
155
174
|
|