Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added error handling to multiple functions in R/assign_job_queue.R, R/blastWrappers.R #76

Merged
merged 8 commits into from
Oct 30, 2024

Conversation

Seyi007
Copy link
Collaborator

@Seyi007 Seyi007 commented Oct 8, 2024

  • Implement error handling for mapOption2Process, get_proc_medians, write_proc_medians_table, get_proc_weights, advanced_opts2est_walltime, assign_job_queue, and plot_estimated_walltimes .

  • Validate input arguments for each function to ensure they meet expected criteria.

  • Use tryCatch blocks to handle errors and warnings gracefully.

  • Provide informative error messages and detailed logging where appropriate.

  • Ensure functions fail gracefully and provide useful feedback.

  • Feature (adds or updates new capabilities)

  • Bug fix (fixes an issue).

  • Enhancement (adds functionality).

  • Breaking change (these changes would cause existing functionality to not work as expected).

Checklist

  • I have read and followed the CONTRIBUTING.md guidelines.
  • I have searched for existing content to ensure this is not a duplicate.
  • I have performed a self-review of these additions (including spelling, grammar, and related).
  • I have added comments to my code to help provide understanding.
  • I have added a test which covers the code changes found within this PR.
  • I have deleted all non-relevant text in this pull request template.
  • Reviewer assignment: @jananiravi @the-mayer

@Seyi007 Seyi007 requested a review from the-mayer October 8, 2024 07:45
@Seyi007 Seyi007 changed the title Add error handling to multiple functions Add error handling to multiple functions in R/assign_job_queue.R Oct 8, 2024
@Seyi007 Seyi007 changed the title Add error handling to multiple functions in R/assign_job_queue.R Added error handling to multiple functions in R/assign_job_queue.R Oct 8, 2024
@Seyi007 Seyi007 changed the title Added error handling to multiple functions in R/assign_job_queue.R Added error handling to multiple functions in R/assign_job_queue.R, R/blastWrappers.R Oct 9, 2024
@the-mayer the-mayer linked an issue Oct 9, 2024 that may be closed by this pull request
@the-mayer the-mayer self-assigned this Oct 9, 2024
@the-mayer the-mayer added the enhancement New feature or request label Oct 9, 2024
Copy link
Collaborator

@the-mayer the-mayer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the extra work here @Seyi007! Providing error handling for these functions will definitely be a worthwhile endeavor. I've rebased this PR on the current main branch to pull in some function name changes and .Rd files that have been submitted in other PRs.

I'd like to see a few modifications before I review further:

tryCatch()

In R, the finally portion is always evaluated, even if the function generates an error or warning.

Printing “{function} execution completed.” might introduce confusion among our users, as they may think the function executed successfully even if an error occurred. Additionally, it could be overly verbose. I’d prefer to reserve the finally portion of each tryCatch() for cleanup or custom handler functions rather than messaging.

print() VS message()

This is both a stylistic and functional request. Given the choice between message() and print() I'd prefer that we use message(). Essentially, when using message, users may choose to suppress the additional messaging with suppressWarnings() or suppressMessages() -- print() is harder to escape and I'd rather give the user the choice.

Best option

Use rlang::inform(), rlang::warn(), and rlang::abort() where appropriate:

Next Steps

Please consider the suggested modifications and submit the PR again for further review. Your efforts are greatly appreciated, and I’m looking forward to seeing the improvements!

@jananiravi
Copy link
Member

Thanks for all your work on this @Seyi007. excellent points, @the-mayer! Looking forward to the changes!

@Seyi007
Copy link
Collaborator Author

Seyi007 commented Oct 11, 2024

Duly noted @the-mayer , I'll get to work on this!

- Replaced base R error handling with rlang functions: `abort()`, `warn()`, and `inform()`.
- Improved clarity and consistency in error and warning messages.
- Enhanced robustness with detailed context for errors and warnings.
@Seyi007
Copy link
Collaborator Author

Seyi007 commented Oct 14, 2024

Hi @the-mayer @jananiravi , I've implemented the suggestions made earlier and have updated the error handling in the R/acc2lin.R. Kindly review and let me know if I'm missing anything, while I work on the remaining functions.

…file

- Replaced base R error handling with rlang functions: `abort()`, `warn()`, and `inform()`.
- Improved clarity and consistency in error and warning messages.
- Enhanced robustness with detailed context for errors and warnings.
@falquaddoomi falquaddoomi self-requested a review October 16, 2024 15:08
Copy link
Contributor

@falquaddoomi falquaddoomi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice work! Generally, I think having better error reporting will really help things, so thank you for the contribution.

I'm inexperienced at R, so take my comments with a grain of salt. Anyway, I made some suggestions in keeping with what @the-mayer had recommended in a previous comment.

Comment on lines 26 to 42
stop("The DELTABLAST executable path is invalid: ", deltablast_path)
}
if (!dir.exists(db_search_path)) {
stop("The database search path is invalid: ", db_search_path)
}
if (!file.exists(query)) {
stop("The query file path is invalid: ", query)
}
if (!is.numeric(as.numeric(evalue)) || as.numeric(evalue) <= 0) {
stop("The evalue must be a positive number: ", evalue)
}
if (!is.numeric(num_alignments) || num_alignments <= 0) {
stop("The number of alignments must be a
positive integer: ", num_alignments)
}
if (!is.numeric(num_threads) || num_threads <= 0) {
stop("The number of threads must be a positive integer: ", num_threads)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMHO it would be better to use rlang::abort() here rather than stop(), as you do in the rest of your code.

Comment on lines 63 to 69
}, error = function(e) {
message(paste("Error in run_deltablast: ", e))
}, warning = function(w) {
message(paste("Warning in run_deltablast: ", w))
}, finally = {
message("run_deltablast completed")
})
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd consider switching out these message() calls for the rlang equivalents, e.g. rlang::error() in the error handler, and rlang::warn() in the warning.

As @the-mayer mentioned, I'd also remove the finally clause entirely, since it'll also be displayed with an error/warning output. Generally, finally should be used when you really need to clean something up, even if there's an error that would ordinarily terminate execution, not for regular reporting.

Comment on lines 92 to 106
if (!file.exists(rpsblast_path)) {
stop("The RPSBLAST executable path is invalid: ", rpsblast_path)
}
if (!dir.exists(db_search_path)) {
stop("The database search path is invalid: ", db_search_path)
}
if (!file.exists(query)) {
stop("The query file path is invalid: ", query)
}
if (!is.numeric(as.numeric(evalue)) || as.numeric(evalue) <= 0) {
stop("The evalue must be a positive number: ", evalue)
}
if (!is.numeric(num_threads) || num_threads <= 0) {
stop("The number of threads must be a positive integer: ", num_threads)
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above; rlang::abort() is a better option than stop().

Comment on lines 125 to 131
}, error = function(e) {
message(paste("Error in run_rpsblast: ", e))
}, warning = function(w) {
message(paste("Warning in run_rpsblast: ", w))
}, finally = {
message("run_rpsblast completed")
})
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above; the error handler should call rlang::error() rather than message(), warning should call rlang::warn(), and the finally handler should be removed.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I haven't updated the R/blastWrappers.R file with the suggestions from @the-mayer . I've only updated the first 2 files, and I'm currently working on the said file.

@@ -1,3 +1,4 @@
suppressPackageStartupMessages(library(rlang))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ideally packages shouldn't invoke library(), since it'll import symbols into the user's namespace that they might not be expecting.

Instead, you should add the following line to the docstrings of functions that use rlang::abort(), rlang::warn(), etc. (with the elements after rlang being the symbols you're using from rlang in that specific function):

#' @importFrom rlang abort warn

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Duly noted! I'll include it in my next commit.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, if you are importing multiple functions from that library, it is better to include it as a dependency in the imports list here.

R/msa.R Outdated
)
prot_aa
prot_aa <- readAAStringSet(
fa_file,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice catch! The path parameter is indeed named filepath, not path as it was in the original code.

It's fine to leave it as a positional parameter as you have it here, since it's the first parameter.

R/acc2lin.R Outdated
Comment on lines 174 to 175
# capturing the call stack
call = sys.call(),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you can leave call at its default value, i.e. remove it from the list of arguments. FAICT the argument is intended to be used when you want the stack trace to appear as if it came from another method (e.g., not a helper method). I didn't see any difference in my testing, at least, with it unset versus setting it to sys.call().

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Faisal, what's FAICT?

R/acc2lin.R Outdated
message = paste("Warning during IPG fetching
or lineage processing:", w$message),
class = "lineage_processing_warning",
call = sys.call(), # capturing the call stack
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above; its default value seems to work fine, so you can remove call here.

R/acc2lin.R Outdated
Comment on lines 288 to 304
abort(
message = paste("An error occurred: ", e$message),
class = "fetch_error",
call = sys.call(),
accnums = accnums,
out_path = out_path,
plan = plan
)
}, warning = function(w) {
warn(
message = paste("Warning: ", w$message),
class = "fetch_warning",
call = sys.call(),
accnums = accnums,
out_path = out_path,
plan = plan
)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Like the other invocations above, these both include call as well, but don't need to.

R/acc2lin.R Outdated
Comment on lines 393 to 411
abort(
message = paste("An error occurred: ", e$message),
class = "processing_error",
call = sys.call(),
accessions = accessions,
ipg_file = ipg_file,
assembly_path = assembly_path,
lineagelookup_path = lineagelookup_path
)
}, warning = function(w) {
warn(
message = paste("Warning: ", w$message),
class = "processing_warning",
call = sys.call(),
accessions = accessions,
ipg_file = ipg_file,
assembly_path = assembly_path,
lineagelookup_path = lineagelookup_path
)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above; you don't need to specify call here.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Duly Noted!

- Added robust error handling in run_deltablast and run_rpsblast functions.
- Updated Roxygen documentation to import rlang::abort, rlang::warn and rlang::inform for better error management.
- Refactored code for clarity and consistency based on the suggestion from the last review.
@Seyi007
Copy link
Collaborator Author

Seyi007 commented Oct 20, 2024

Hi @jananiravi @falquaddoomi, I've implemented all the changes required from the previous review in my latest commit. Could you review this and let me know if I'm missing anything?

@jananiravi jananiravi added the outreachy for outreachy interns label Oct 20, 2024
Copy link
Contributor

@falquaddoomi falquaddoomi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice, looks like you got to everything I raised.

@jananiravi
Copy link
Member

@falquaddoomi @the-mayer followed the conversation but not the most recent line-by-line edits. Feel free to merge if this looks good.

Thanks, @Seyi007 !

@Seyi007
Copy link
Collaborator Author

Seyi007 commented Oct 23, 2024

Yay! Thank you @falquaddoomi @jananiravi

@the-mayer
Copy link
Collaborator

Thanks for the additional work here, @Seyi007!

Finishing up with #97 and will tackle merging this one next.

Copy link
Collaborator

@the-mayer the-mayer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @Seyi007, sending to main!

@the-mayer the-mayer merged commit 2ef3f56 into JRaviLab:main Oct 30, 2024
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request outreachy for outreachy interns
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Rename the listed function names in the following files.
4 participants