-
Notifications
You must be signed in to change notification settings - Fork 18
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
Draft: [EXPERIMENT] Sketching out a RusticIssueCollector #318
Conversation
Signed-off-by: simonsan <14062932+simonsan@users.noreply.github.com>
Codecov ReportAttention: Patch coverage is
Additional details and impacted files
|
Signed-off-by: simonsan <14062932+simonsan@users.noreply.github.com>
Signed-off-by: simonsan <14062932+simonsan@users.noreply.github.com>
crates/core/src/error/collector.rs
Outdated
pub struct RusticIssueCollector { | ||
/// The errors collected | ||
errors: Option<Vec<RusticError>>, | ||
|
||
/// The warnings collected | ||
warnings: Option<Vec<RusticWarning>>, | ||
|
||
/// The info collected | ||
info: Option<Vec<RusticInfo>>, | ||
|
||
/// Whether to log items directly during addition | ||
log: bool, | ||
} |
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.
We might want to adapt it, so we can easier use it from multiple threads, and other contexts, e.g. via Mutexes or Channels.
/// An error issue, indicating that something went wrong irrecoverably | ||
Error(RusticError), |
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.
We might not have that within this Enum though? 🤔 as that should always be a hard error I think? Not sure though.
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.
Actually I do think that we can have Errors on a deeper level which are shown as warnings on a higher level. Something like backup failed for creating the first snapshot, but we want to continue creating the second one...
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.
In this case, we should handle that at the point we get that error
and start the backup for the second path
for example. The failed backup for the first will be output to the user at the match
of the result (e.g. in a loop) and we start the next one, but give user feedback.
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.
So I think this is the same topic as above, we shouldn't give errors
different meanings, I don't know if they are really contextual in that sense. There can be hard and soft errors, for sure. But I think we are going to replace the term soft error here, with an issue
which can result in a warning
or info
. But then we need to reserve the term error
for things that are irrecoverable.
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.
Besides some specific comments, a general one:
As it seems there is no crate yet to provide such a functionality we need, I propose we make a new crate out of this which we then use within rustic_core and rustic...
I could even think of having some macro functionality to simplify writing functions which collect errors without the need to explicitly create a Collector
for collecting errors. Something like
#[collect]
fn my_func() -> CollectorResult<T> {
let x = fn1()? // returns CollectorResult; on Err just bubble this up
.fn2().collect_as_err_or(0.0, MyErr); // returns CollectorResult, on error collect errors as error and use value 0.0
let y = fn3(x).collect_as_warn_or(1.0, MyWarn); // as before, but warning
Ok(x)
}
(Note this can produce a result of 1.0 with warnings and errors...)
/// An error issue, indicating that something went wrong irrecoverably | ||
Error(RusticError), |
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.
Actually I do think that we can have Errors on a deeper level which are shown as warnings on a higher level. Something like backup failed for creating the first snapshot, but we want to continue creating the second one...
crates/core/src/error/collector.rs
Outdated
/// | ||
/// An issue is a message that can be logged to the user. | ||
#[derive(Debug)] | ||
pub enum RusticIssue { |
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.
Why not using something like error: RusticError
and severity: RusticSeverity
with the latter being an enum? I can imagine we can have the exactly identical error which is at some place classified as warning (or even info) and at another place just an error.
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 don't know, I would not classify an error at one place as a warning and at the other as an info. An error is an error, and should be clearly communicated as one. If we change the general meaning of an error, then it shouldn't be an error in the first place.
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.
But I do know what you mean, something like: 'File not found'. At one place, it can be irrecoverable, e.g. a config file not found for a backend. At some other place, it maybe can be continued with default settings.
But in that case we should handle that error in-place and not return an error I feel.
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.
Also, important to say here: RusticIssue
, RusticWarning
, and RusticIssueCollector
should never go over the library boundary. So it's for internal use only, it should not be part of our public API, and we should actually not return RusticIssue
from any public function - maybe even in general - every function. It should only be used for internal error handling, so we as library authors can judge situations better internally, and give our users errors only in cases that are worthwhile.
Hence, I reduced the visibility of all the types in this file to pub(crate)
crates/core/src/error/collector.rs
Outdated
/// | ||
/// Warning messages are used to indicate that something might be wrong. | ||
#[derive(Debug, Clone, From)] | ||
pub struct RusticWarning(String); |
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 don't like having String
here. IMO we should just have RusticError
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.
Same as above, this here is a warning
, RusticError
should be something that we return to the user, in case we can't recover from something. This is pub here, but I'm not sure if we ever should make RusticWarning, RusticInfo part of our public API. Users of rustic_core
, also rustic-rs
should never have to deal with that. They will only get errors
from us. I think 🤔 If it is recoverable, then we should recover from it, not the users.
Signed-off-by: simonsan <14062932+simonsan@users.noreply.github.com>
Signed-off-by: simonsan <14062932+simonsan@users.noreply.github.com>
Signed-off-by: simonsan <14062932+simonsan@users.noreply.github.com>
I think one of our problems is the thought, that we would need to transfer warnings and information over a function boundary and not handle them as locally as possible. From this thought stems the problematic, that we want to have Some key insights:
|
From this point, there shouldn't be actually any |
The more I think about and work with it, the less I'm sure, that this is a valid approach for Especially, when it comes to just pushing a lot of errors up the call stack. I do see a use case for The problem I have with Could we do it like this: We merge #317 (otherwise we need to rebase a lot of stuff) and then I would like to try to implement a proposal on top of that of how I could imagine handling errors in I'm closing this as an experiment for now. |
Implementation to collect feedback and sketch out an idea. We should iterate more on it, to make it more ergonomic, I think.