-
Notifications
You must be signed in to change notification settings - Fork 1.2k
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
Change cli to propagate error to exit code #8856
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This makes a lot of sense to me @tshauck -- thank you 🙏
Thanks @alamb... so looking into the error display, it looks like the printed message is With those changes, this is what the error now looks like:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @tshauck
datafusion-cli/src/main.rs
Outdated
@@ -138,7 +139,7 @@ struct Args { | |||
} | |||
|
|||
#[tokio::main] | |||
pub async fn main() -> Result<()> { | |||
pub async fn main() -> Result<(), DataFusionCLIError> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rather than implementing an entire new error class just to reuse the existing error handler, what do you think about handling the error explicitly? Perhaps something like
#[tokio::main]
/// Handle errors in `main_inner`
pub async fn main() {
// print nice error and return error status from process on error
if let Err(e) = main_inner().await {
println!("Execution Error: {e}");
std::process:exit(1);
}
}
/// Main CLI entrypoint
async fn main_inner() -> Result<()> {
env_logger::init();
let args = Args::parse();
...
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Works for me too... I'll take another crack at it this evening and follow up when it's ready.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I ended up going a slightly different route and wrapped main as suggested but am having it return ExitCode
vs ()
.
From the std::process::exit
docs, it seems like while it can work, it's preferable to either return Result
(initial impl if verbose) or ExitCode
(i.e. something that implements Termination
) to better handle cleanup, not that it matters a ton here, but 🤷 .
Note that because this function never returns, and that it terminates the process, no destructors on the current stack or any other thread’s stack will be run. If a clean shutdown is needed it is recommended to only call this function at a known point where there are no more destructors left to run; or, preferably, simply return a type implementing Termination (such as ExitCode or Result) from the main function and avoid this function altogether:
https://doc.rust-lang.org/std/process/fn.exit.html
Happy to go w/ exit if you still think it's the best route.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me -- thank you @tshauck
@@ -138,7 +139,18 @@ struct Args { | |||
} | |||
|
|||
#[tokio::main] | |||
pub async fn main() -> Result<()> { | |||
/// Calls [`main_inner`], then handles printing errors and returning the correct exit code | |||
pub async fn main() -> ExitCode { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
I also double checked with a quick test locally: venv) andrewlamb@Andrews-MacBook-Pro:~/Software/arrow-datafusion/datafusion-cli$ ./target/debug/datafusion-cli -c 'select foo()' || echo "fail"
DataFusion CLI v34.0.0
Error: Error during planning: Invalid function 'foo'.
Did you mean 'cos'?
fail
(venv) andrewlamb@Andrews-MacBook-Pro:~/Software/arrow-datafusion/datafusion-cli$ ./target/debug/datafusion-cli -c 'select 1' || echo "fail"
DataFusion CLI v34.0.0
+----------+
| Int64(1) |
+----------+
| 1 |
+----------+
1 row in set. Query took 0.014 seconds. And it seems to work great. Thanks @tshauck ! |
Which issue does this PR close?
TODO:
Rationale for this change
The rationale is that currently when using the cli, if you use -c and -f, both of which are useful to use datafusion in workflows (e.g. and ETL pipeline), the exit code if the query fails is still 0. Most job orchestration tools can propagate the exit code from a CLI tool "up", so this makes using the CLI more ergonomic for that use case.
What changes are included in this PR?
Generally, adds
Result
return enums so that the CLI will eventually return the 0 or 1 exit code to the caller.Are these changes tested?
I ran the
-c
,-f
, and interactive mode. Things are functional, though the main difference I've noticed is the error printed out is a bit more verbose right now. E.g.If this is to be merged, I'll try to cleanup the error message, but I thought I'd open this to get feedback as to if this is something the project would consider merging.
Thanks