Module: SequenceServer
- Defined in:
- lib/sequenceserver.rb,
lib/sequenceserver/job.rb,
lib/sequenceserver/sys.rb,
lib/sequenceserver/links.rb,
lib/sequenceserver/config.rb,
lib/sequenceserver/doctor.rb,
lib/sequenceserver/logger.rb,
lib/sequenceserver/report.rb,
lib/sequenceserver/routes.rb,
lib/sequenceserver/server.rb,
lib/sequenceserver/version.rb,
lib/sequenceserver/database.rb,
lib/sequenceserver/sequence.rb,
lib/sequenceserver/blast/hit.rb,
lib/sequenceserver/blast/hsp.rb,
lib/sequenceserver/blast/job.rb,
lib/sequenceserver/api_errors.rb,
lib/sequenceserver/exceptions.rb,
lib/sequenceserver/blast/error.rb,
lib/sequenceserver/blast/query.rb,
lib/sequenceserver/job_remover.rb,
lib/sequenceserver/makeblastdb.rb,
lib/sequenceserver/blast/report.rb,
lib/sequenceserver/blast/constants.rb,
lib/sequenceserver/blast/formatter.rb
Overview
Define constants used by SequenceServer module
Defined Under Namespace
Modules: BLAST, Links Classes: BLAST_DATABASE_ERROR, BLAST_NOT_COMPATIBLE, BLAST_NOT_INSTALLED_OR_NOT_EXECUTABLE, CONFIG_FILE_ERROR, CommandFailed, Config, DATABASE_DIR_NOT_SET, Database, DatabaseUnreachableError, Doctor, ENOENT, INCOMPATIBLE_BLAST_DATABASES, InputError, Job, JobRemover, Logger, MAKEBLASTDB, NO_BLAST_DATABASE_FOUND, NUM_THREADS_INCORRECT, NotFound, Report, Routes, Sequence, Server, SystemError
Constant Summary collapse
- BLAST_VERSION =
The default version of BLAST that will be downloaded and configured for use.
'2.12.0+'.freeze
- DEFAULT_CONFIG_FILE =
Default location of configuration file.
'~/.sequenceserver.conf'.freeze
- DOTDIR =
Constant for denoting the path ~/.sequenceserver
File.('~/.sequenceserver').freeze
- VERSION =
'3.0.1'.freeze
- Error =
Class.new(Sinatra::Error)
- APIError =
API errors have an http status, title, message, and additional information like stacktrace or information from program output.
Class.new(Error)
Class Attribute Summary collapse
-
.config ⇒ Object
readonly
Holds SequenceServer configuration object for this process.
Class Method Summary collapse
-
.call(env) ⇒ Object
Rack-interface.
-
.development? ⇒ Boolean
(also: verbose?)
Returns true if RACK_ENV is set to ‘development’.
-
.environment ⇒ Object
Returns ENV.
-
.init(config = {}) ⇒ Object
SequenceServer initialisation routine.
-
.irb ⇒ Object
This method is invoked by the -i switch to start an IRB shell with SequenceServer loaded.
-
.logger ⇒ Object
Logger object used in the initialisation routine and throughout the application.
-
.makeblastdb ⇒ Object
MAKEBLASTDB service object.
-
.on_start ⇒ Object
This method is called after WEBrick has bound to the host and port and is ready to accept connections.
-
.on_stop ⇒ Object
This method is called when WEBrick is terminated.
-
.run ⇒ Object
Run SequenceServer using WEBrick.
-
.sys(command, options = {}) ⇒ Object
‘sys’ executes a shell command.
Class Attribute Details
.config ⇒ Object (readonly)
Holds SequenceServer configuration object for this process. This is available only after calling SequenceServer.init.
110 111 112 |
# File 'lib/sequenceserver.rb', line 110 def config @config end |
Class Method Details
.call(env) ⇒ Object
Rack-interface.
Add our logger to Rack env and let Routes do the rest.
115 116 117 118 |
# File 'lib/sequenceserver.rb', line 115 def call(env) env['rack.logger'] = logger Routes.call(env) end |
.development? ⇒ Boolean Also known as: verbose?
Returns true if RACK_ENV is set to ‘development’. Raw JS and CSS files are served in development mode and the logger is made more verbose.
43 44 45 |
# File 'lib/sequenceserver.rb', line 43 def development? environment == 'development' end |
.environment ⇒ Object
Returns ENV. This environment variable determines if we are in development on in production mode (default).
37 38 39 |
# File 'lib/sequenceserver.rb', line 37 def environment ENV['RACK_ENV'] end |
.init(config = {}) ⇒ Object
SequenceServer initialisation routine.
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 |
# File 'lib/sequenceserver.rb', line 67 def init(config = {}) # Reset makeblastdb cache, because configuration may have changed. @makeblastdb = nil # Use default config file if caller didn't specify one. config[:config_file] ||= DEFAULT_CONFIG_FILE # Initialise global configuration object from the above config hash. @config = Config.new(config) # When in development mode, cause SequenceServer to terminate if any # thread spawned by the main process raises an unhandled exception. In # production mode the expectation is to log at appropriate severity level # and continue operating. Thread.abort_on_exception = true if development? # Now locate binaries, scan databases directory, require any plugin files. load_extension init_binaries init_database # The above methods validate bin dir, database dir, and path to plugin # files. Port and host settings don't need to be validated: if running # in self-hosted mode, WEBrick will handle incorrect values and if # running via Apache+Passenger host and port settings are not used. # Let's validate remaining configuration keys next. # Validate number of threads to use with BLAST. check_num_threads # Doesn't make sense to activate JobRemover when testing. It anyway # keeps stumbling on the mock test jobs that miss a few keys. unless environment == 'test' @job_remover = JobRemover.new(@config[:job_lifetime]) end # 'self' is the most meaningful object that can be returned by this # method. self end |
.irb ⇒ Object
This method is invoked by the -i switch to start an IRB shell with SequenceServer loaded.
173 174 175 176 177 178 179 180 |
# File 'lib/sequenceserver.rb', line 173 def irb ARGV.clear require 'irb' IRB.setup nil IRB.conf[:MAIN_CONTEXT] = IRB::Irb.new.context require 'irb/ext/multi-irb' IRB.irb nil, self end |
.logger ⇒ Object
Logger object used in the initialisation routine and throughout the application.
50 51 52 53 54 55 56 57 58 59 |
# File 'lib/sequenceserver.rb', line 50 def logger @logger ||= case environment when 'development' Logger.new(STDERR, Logger::DEBUG) when 'test' Logger.new(STDERR, Logger::WARN) else Logger.new(STDERR, Logger::INFO) end end |
.makeblastdb ⇒ Object
MAKEBLASTDB service object.
62 63 64 |
# File 'lib/sequenceserver.rb', line 62 def makeblastdb @makeblastdb ||= MAKEBLASTDB.new(config[:database_dir]) end |
.on_start ⇒ Object
This method is called after WEBrick has bound to the host and port and is ready to accept connections.
138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 |
# File 'lib/sequenceserver.rb', line 138 def on_start puts '** SequenceServer is ready.' puts " Go to #{server_url} in your browser and start BLASTing!" if ip_address puts ' To share your setup, try one of the following addresses. These' puts ' may only work within your home, office, or university network.' puts " - http://#{ip_address}:#{config[:port]}" puts " - http://#{hostname}:#{config[:port]}" if hostname puts ' To share your setup with anyone in the world, ask your IT team' puts ' for a public IP address or consider the SequenceServer cloud' puts ' hosting service: https://sequenceserver.com/cloud' puts ' To disable sharing, set :host: key in config file to 127.0.0.1' puts ' and restart server.' end puts ' To terminate server, press CTRL+C' open_in_browser(server_url) end |
.on_stop ⇒ Object
This method is called when WEBrick is terminated.
157 158 159 160 161 162 163 164 165 166 167 168 169 |
# File 'lib/sequenceserver.rb', line 157 def on_stop puts puts '** Thank you for using SequenceServer :).' puts ' Please cite: ' puts ' Priyam A, Woodcroft BJ, Rai V, Moghul I, Munagala A, Ter F,' puts ' Chowdhary H, Pieniak I, Maynard LJ, Gibbins MA, Moon H,' puts ' Davis-Richardson A, Uludag M, Watson-Haigh N, Challis R,' puts ' Nakamura H, Favreau E, Gómez EA, Pluskal T, Leonard G,' puts ' Rumpf W & Wurm Y.' puts ' Sequenceserver: A modern graphical user interface for' puts ' custom BLAST databases.' puts ' Molecular Biology and Evolution (2019)' end |
.run ⇒ Object
Run SequenceServer using WEBrick.
121 122 123 124 125 126 127 128 129 130 131 132 133 134 |
# File 'lib/sequenceserver.rb', line 121 def run Server.run(self) rescue Errno::EADDRINUSE puts "** Could not bind to port #{config[:port]}." puts " Is SequenceServer already accessible at #{server_url}?" puts ' No? Try running SequenceServer on another port, like so:' puts puts ' sequenceserver -p 4570.' rescue Errno::EACCES puts "** Need root privilege to bind to port #{config[:port]}." puts ' It is not advisable to run SequenceServer as root.' puts ' Please use Apache/Nginx to bind to a privileged port.' puts ' Instructions available on http://sequenceserver.com.' end |
.sys(command, options = {}) ⇒ Object
‘sys’ executes a shell command.
‘sys’ can write the stdout and/or stderr from a shell command to files, or
return these values.
‘sys’ can get from a failed shell command stdout, stderr, and exit status.
Supply ‘sys’ with the shell command and optionally: dir: A directory to change to for the duration of the execution of the shell command. path: A directory to change the PATH environment variable to for the duration of the execution of the shell command. stdout: A path to a file to store stdout. stderr: A path to a file to store stderr.
Usage:
sys(command, dir: ‘/path/to/directory’, path: ‘/path/to/directory’,
stdout: '/path/to/stdout_file', stderr: '/path/to/stderr_file')
rubocop:disable Metrics/CyclomaticComplexity
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 |
# File 'lib/sequenceserver/sys.rb', line 25 def self.sys(command, = {}) # Available output channels channels = i[stdout stderr] # Make temporary files to store output from stdout and stderr. temp_files = { stdout: Tempfile.new('sequenceserver-sys'), stderr: Tempfile.new('sequenceserver-sys') } # Log the command we are going to run - use -D option to view. logger.debug("Executing: #{command}") # Run command in a child process. This allows us to control PATH # and pwd of the running process. child_pid = fork do # Set the PATH environment variable to the binary directory or # safe directory. ENV['PATH'] = [:path] if [:path] # Change to the specified directory. Dir.chdir([:dir]) if [:dir] && Dir.exist?([:dir]) # Execute the shell command, redirect stdout and stderr to the # temporary files. exec(command, out: temp_files[:stdout].path.to_s, \ err: temp_files[:stderr].path.to_s) end # Wait for the termination of the child process. _, status = Process.wait2(child_pid) # If a full path was given for stdout and stderr files, move the # temporary files to this path. If the path given does not exist, # create it. channels.each do |channel| filename = [channel] break unless filename # If the given path has a directory component, ensure it exists. file_dir = File.dirname(filename) FileUtils.mkdir_p(file_dir) unless File.directory?(file_dir) # Now move the temporary file to the given path. # TODO: don't we need to explicitly close the temp file here? FileUtils.cp(temp_files[channel], filename) end # Read the remaining temp files into memory. For large outputs, # the caller should supply a file path to prevent loading the # output in memory. temp_files.each do |channel, tempfile| temp_files[channel] = tempfile.read end # Finally, return contents of the remaining temp files if the # command completed successfully or raise CommandFailed error. return temp_files.values if status.success? raise CommandFailed.new(status.exitstatus, **temp_files) end |