wurmlab/sequenceserver

View on GitHub
lib/sequenceserver/blast/error.rb

Summary

Maintainability
A
35 mins
Test Coverage
F
31%
# http://www.ncbi.nlm.nih.gov/books/NBK1763/ (Appendices)

module SequenceServer
  module BLAST
    class Error
      attr_reader :exitstatus, :stdout, :stderr

      def initialize(exitstatus:, stdout:, stderr:)
        @exitstatus = exitstatus
        @stdout = stdout
        @stderr = stderr
      end

      def raise!
        return true if exitstatus.zero? && !File.zero?(stdout)

        case exitstatus
        when 1..2
          # 1: Error in query sequences or options.
          # 2: Error in BLAST databases.
          error = IO.foreach(stderr).grep(ERROR_LINE).join
          error = File.read(stderr) if error.empty?
          fail InputError, "(#{exitstatus}) #{error}"
        when 4
          # Out of memory. User can retry with a shorter search, so raising
          # InputError here instead of SystemError.
          fail InputError, <<~MSG
            Ran out of memory. Please try a smaller query, fewer and smaller
            databases, or limiting the output by using advanced options.
          MSG
        when 6
          # Error creating output files. It can't be a permission issue as that
          # would have been caught while creating job directory. But we can run
          # out of storage after creating the job directory and while running
          # the job. This is a SystemError.
          fail SystemError, 'Ran out of disk space.'
        else
          # I am not sure what the exit codes 3 means and we should not
          # encounter exit code 5. The only other error that I know can happen
          # but is not yet handled is when BLAST+ binaries break such as after
          # macOS updates. So raise SystemError, include the exit status in the
          # message, and say that that the "most likely" reason is broken BLAST+
          # binaries.

          error = File.read(stderr)
          error = 'Most likely there is a problem with the BLAST+ binaries.' if error.empty?

          fail SystemError, "BLAST failed abruptly (exit status: #{exitstatus}). #{error}"
        end
      end
    end
  end
end