-
Notifications
You must be signed in to change notification settings - Fork 3
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
Refactor unwrap to improve error handling #937
Conversation
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #937 +/- ##
==========================================
+ Coverage 77.17% 77.18% +0.01%
==========================================
Files 32 32
Lines 25723 25722 -1
==========================================
+ Hits 19851 19854 +3
+ Misses 5872 5868 -4 ☔ View full report in Codecov by Sentry. |
src/graphql/statistics.rs
Outdated
*iter_next_values.get_mut(idx).unwrap() = item; | ||
*iter_next_values | ||
.get_mut(idx) | ||
.expect("value is always exist") = item; |
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 would like to suggest fixing grammar: is always exist
-> always exists
src/lib.rs
Outdated
@@ -166,7 +166,7 @@ extern crate proc_macro; | |||
#[proc_macro_derive(ConvertGraphQLEdgesNode, attributes(graphql_client_type))] | |||
pub fn derive_from_graphql_client_autogen(input: TokenStream) -> TokenStream { | |||
derive_from_graphql_client_autogen_2(input.into()) | |||
.unwrap() | |||
.expect("valid input struct") |
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.
Could you handle this with panic!
macro, instead of expect
please? The file lib.rs is the code for proc-macro , which runs against the Giganto codebase, during compile time only, to generate code from our custom macro. And this part can panic, when the Giganto codebase uses the custom macro incorrectly. My personal idea is that the message could be something like "ConvertGraphQLEdgesNode macro is not correctly used for {input}"
src/publish/implement.rs
Outdated
@@ -13,14 +13,16 @@ pub trait RequestStreamMessage { | |||
|
|||
impl RequestStreamMessage for RequestHogStream { | |||
fn channel_key(&self, sensor: Option<String>, record_type: &str) -> Result<Vec<String>> { | |||
let sensor = sensor | |||
.ok_or_else(|| anyhow!("Failed to generate hog channel key, sensor is required."))?; |
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 think we can use supervised model as the term. Or any other terms that refers to the supervised engine, that can be used in public space.
Could you check the commit message title's length? |
62a8574
to
7bf02b3
Compare
7bf02b3
to
5afa77b
Compare
src/graphql/export.rs
Outdated
*iter_next_values.get_mut(min_index).unwrap() = item; | ||
*iter_next_values | ||
.get_mut(min_index) | ||
.expect("min_index's vector value always exists") = item; |
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 think this message is clear enough. I suggest:
"The index is one of the actual elements in the vector, so it is always valid."
src/graphql/statistics.rs
Outdated
@@ -224,8 +224,7 @@ fn gen_statistics( | |||
for idx in next_candidate { | |||
if let Some(iter) = stats_iters.get_mut(idx) { | |||
if let Some(item) = iter.next() { | |||
// replace new value (value is always exist) | |||
*iter_next_values.get_mut(idx).unwrap() = item; | |||
*iter_next_values.get_mut(idx).expect("value always exists") = item; |
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 need to specify the reason as clearly as possible, for example:
"`next_candidate` is generated while iterating over `iter_next_value`, so any index of the former is always valid within the latter."
src/main.rs
Outdated
@@ -313,7 +313,7 @@ async fn main() -> Result<()> { | |||
if is_reboot || is_power_off || is_reload_config { | |||
loop { | |||
{ | |||
let retain_flag = retain_flag.lock().unwrap(); | |||
let retain_flag = retain_flag.lock().expect("Mutex lock is safe"); |
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.
Could you explain why this is safe?
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.
If the message in expect about why the retain_flag
is always safe needs to change, please also change the message about the running_flag
in the retain_periodically
function as well.
src/publish.rs
Outdated
@@ -528,8 +528,7 @@ where | |||
info!("start hog's publish stream : {:?}", record_type); | |||
} | |||
NodeType::Crusher => { | |||
// crusher's policy Id always exists. | |||
let id = msg.id().unwrap(); | |||
let id = msg.id().expect("crusher's policy Id always exists"); |
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.
Could you explain why this always exists?
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.
- The
id
is a method that gets the value of the id field of theRequestCrusherStream
structure that cruhser sends to giganto.pub struct RequestCrusherStream { pub start: i64, pub id: String, pub src_ip: Option<IpAddr>, pub dst_ip: Option<IpAddr>, pub sensor: Option<String>, }
- When crusher sends the value of that structure to giganto, it always includes the id value, so the value always exists.
Apart from this issue, the return value was Option because we used to call one method, source_id
, to get the source or id values from the RequestStreamMessage
trait, but now we have separated them into sensor
and id
. Id
always has a value, so I think we can remove Option from the return value of the id
method of the RequestStreamMessage
trait in the future.
src/storage/migration.rs
Outdated
@@ -196,7 +196,7 @@ where | |||
continue; | |||
}; | |||
let new_key = StorageKey::builder() | |||
.start_key(&netflow_raw_event.sensor().unwrap()) | |||
.start_key(&netflow_raw_event.sensor().expect("always exists")) |
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.
Could you explain why this is safe?
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.
- The
sensor
is a method to get the value of the source field ofNetflow5BeforeV23
andNetflow9BeforeV23
.pub struct Netflow5BeforeV23 { pub source: String, ..... } pub struct Netflow9BeforeV23 { pub source: String, ..... }
- In earlier versions of giganto, before the structure of netflow5 and netflow9 was changed, saving
Netflow5BeforeV23
andNetflow9BeforeV23
to the DB was done in the following order- Receive netflow5, netflow9 from REproduce. (via ingest)
- Extract the source from the certificate in REproduce and store the value in the source field of each structure.
- Store the final struct values to the DB.
- Due to the above processing order, the source value always exists, and so do the results of the
sensor
that fetch them.
5afa77b
to
0b7ae35
Compare
src/main.rs
Outdated
@@ -313,7 +313,7 @@ async fn main() -> Result<()> { | |||
if is_reboot || is_power_off || is_reload_config { | |||
loop { | |||
{ | |||
let retain_flag = retain_flag.lock().unwrap(); | |||
let retain_flag = retain_flag.lock().expect("Mutex lock is safe because it only guards a simple boolean flag without complex operations."); |
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 think this message sufficiently explains why we can always expect safe results.
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.
Initially, I used the “always safe” message in expect because the Mutex only protects a simple boolean flag, which makes it unlikely to panic within the lock scope.
However, after considering the possibility of other parts of the system panicking while holding the lock, I decided to replace expect with unwrap_or_else.
In case of poisoning, the value is now safely recovered, and a warning message is logged to aid debugging.
0b7ae35
to
60747ac
Compare
src/storage.rs
Outdated
@@ -1038,7 +1041,10 @@ pub async fn retain_periodically( | |||
} | |||
info!("Database cleanup completed."); | |||
{ | |||
let mut running_flag = running_flag.lock().unwrap(); | |||
let mut running_flag = running_flag.lock().unwrap_or_else(|e| { | |||
warn!("Poisoned Mutex. Recovering the boolean flag."); |
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 think we can use AtomicBool type instead of Mutex for the running_flag
. I think we can avoid potential panicking from the mutex behavior, and achieve simpler code.
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.
Thank you for the suggestion!
60747ac
to
eab96b0
Compare
@BLYKIM Could you check the line length of the commit content? |
- Refactor `Mutex<bool>` to `AtomicBool` to prevent potential panics and enhance performance.
eab96b0
to
c2392e1
Compare
Close: #899