redis-derive icon indicating copy to clipboard operation
redis-derive copied to clipboard

Non-existent keys throw an odd error instead of `Option::None`

Open ooliver1 opened this issue 2 years ago • 2 comments

use redis_derive::{FromRedisValue, ToRedisArgs};

use std::collections::HashMap;

use redis::Commands;

#[derive(FromRedisValue, ToRedisArgs, Debug)]
enum Color {
    Red,
    Green,
}

#[derive(Default, FromRedisValue, ToRedisArgs, Debug)]
#[redis(rename_all = "snake_case")]
enum Group {
    #[default]
    MemberGroup,
    AdminGroup,
}

#[derive(FromRedisValue, ToRedisArgs, Debug)]
struct MySuperCoolStruct {
    first_field: String,
    second_field: Option<i64>,
    third_field: Vec<String>,
    color: Color,
    group: Group,
}

fn main() -> redis::RedisResult<()> {
    let client = redis::Client::open("redis://127.0.0.1:6379/")?;
    let mut con = client.get_connection()?;

    let test1 = MySuperCoolStruct {
        first_field: "Hello World".to_owned(),
        second_field: Some(42),
        third_field: vec!["abc".to_owned(), "cba".to_owned()],
        color: Color::Red,
        group: Group::AdminGroup,
    };

    // let _ = redis::cmd("HSET")
    //     .arg("test1")
    //     .arg(&test1)
    //     .query(&mut con)?;

    let db_test1: MySuperCoolStruct = con.hgetall("test1")?;

    println!("send : {:#?}, got : {:#?}", test1, db_test1);

    let db_test1: HashMap<String, String> = con.hgetall("test1")?;
    assert_eq!(db_test1["group"], "admin_group");

    Ok(())
}
Error: Response was of incompatible type: "Response type not string compatible." (response was nil)

This happens because https://github.com/kkharji/redis-derive/blob/014526ffacd998d88d58b57622309e73fef96e29/src/data_struct.rs#L134 expects fields to exist and simply defaults to Nil otherwise, which cannot be converted into String

ooliver1 avatar Mar 18 '23 18:03 ooliver1

Indeed the error is misleading. It should indicate that it got nil/not found.

Maybe also support Option<MySuperCoolStruct>, so we know that the command executed successfully but we got nil

In terms of supporting default values. It's a bit tricky. As of right now, I'm not sure how I would know as well as handle the case where the struct derives Default, and just do MySuperCoolStruct::default() in case redis return nil value.

Thanks @ooliver1 for debugging. Will look into it soon, unless you did find a solution.

kkharji avatar Mar 19 '23 00:03 kkharji

Ideally at least Option<Struct> would be cool, since then it's very explicit as to if the key exists or not. Thank you for replying so quickly!

ooliver1 avatar Mar 19 '23 01:03 ooliver1