shotover / shotover-proxy

L7 data-layer proxy
https://docs.shotover.io
Apache License 2.0
83 stars 16 forks source link

Improve KafkaSinkCluster server error handling #1625

Closed rukai closed 3 months ago

rukai commented 3 months ago

I had previously missed that kafka-protocol provides a ResponseError type for parsing kafka error codes. This type is super useful, turning the numeric error codes into a meaningful error enum. So this PR:

PR Walkthrough notes

Some notes on rust features for newstarters reviewing this PR.

Option

rust has a core type in the standard library called Option. It is an enum defined as:

enum Option<T> {
    Some(T),
    None
}

It is similar to java's Optional but a lot better.

In other languages you may set a variable to null to say that no value exists for that variable. However no such functionality exists in rust. Instead we wrap the value in Option to allow for the case where the value does not exist.

For example:

fn print_value(value: Option<i32>) {
    if let Some(value) = value {
        println!("the value is {value}");
    }
}

print_value(Some(10)); // prints: the value is 10
print_value(None); // does not print anything

And this is equivalent:

fn print_value(value: Option<i32>) {
    match value {
        Some(value) => println!("the value is {value}");
        None => {}
    }
}

print_value(Some(10)); // prints: the value is 10
print_value(None); // does not print anything

Result

rust has a core type in the standard library called Option. It is an enum defined as:

enum Result<T, E> {
    Ok(T),
    Err(E)
}

Some languages use exceptions for error handling. Rust does not have exceptions. Some languages use function return values for error handling. Rust does do this, but almost always through the Result type.

fn fallible_operation(value: i32) -> Result<i32, Error> {
    if value == 0 {
        Err(SomethingBad)
    }
    else if value == 1 {
        Err(SomethingTerrible)
    }
    else {
        Ok(value)
    }
}

enum Error {
    SomethingBad,
    SomethingTerrible,
}

// prints: failure SomethingBad
match fallible_operation(0) {
    Ok(value) => println!("success {value}"),
    Err(err) => println!("failure {err:?}"),
}

// prints: failure SomethingTerrible
match fallible_operation(1) {
    Ok(value) => println!("success {value}"),
    Err(err) => println!("failure {err:?}"),
}

// prints: success 3
match fallible_operation(3) {
    Ok(value) => println!("success {value}"),
    Err(err) => println!("failure {err:?}"),
}

anyhow errors

codspeed-hq[bot] commented 3 months ago

CodSpeed Performance Report

Merging #1625 will not alter performance

Comparing rukai:kafka_improve_error_handling (6c845c7) with main (ab47602)

Summary

✅ 37 untouched benchmarks