rust 响应类型与字符串不兼容,“(响应为nil)查询redis时

rn0zuynd  于 2023-04-30  发布在  Redis
关注(0)|答案(1)|浏览(168)

我用这段代码在rust中做一个redis查询,我的最小复制示例包含3个文件。下面是我的main.rs函数:

#[tokio::main]
async fn main() {
    const REDIS_CON_STRING: &str = "redis://default:password@cruise-redis-headless.reddwarf-cache.svc.cluster.local:6379/3";
    let redis_client = redis::Client::open(REDIS_CON_STRING).expect("can create redis client");
    let mut redis_conn = get_con(redis_client);
    let cached_playlist = get_str(&mut redis_conn.unwrap(), "dd").await;
    if cached_playlist.as_ref().unwrap().is_empty() {
        print!("d")
    }
}

这是定义redis操作的redis_util.rs

use redis::{Commands, Connection, FromRedisValue};
use crate::mobc_error::DirectError::{RedisClientError, RedisCMDError, RedisTypeError};
use crate::mobc_error::Error;

type Result<T> = std::result::Result<T, Error>;

pub fn get_con(client: redis::Client) -> Result<Connection> {
    client
        .get_connection()
        .map_err(|e| RedisClientError(e).into())
}

pub async fn set_str(
    con: &mut Connection,
    key: &str,
    value: &str,
    ttl_seconds: usize,
) -> Result<()> {
    con.set(key, value).map_err(RedisCMDError)?;
    if ttl_seconds > 0 {
        con.expire(key, ttl_seconds).map_err(RedisCMDError)?;
    }
    Ok(())
}

pub async fn get_str(con: &mut Connection, key: &str) -> Result<String> {
    let value = con.get(key).map_err(RedisCMDError)?;
    FromRedisValue::from_redis_value(&value).map_err(|e| RedisTypeError(e).into())
}

这是错误定义mobc_error.rs

use thiserror::Error;

#[derive(Error, Debug)]
pub enum Error {
    #[error("mobc error: {0}")]
    MobcError(#[from] MobcError),
    #[error("direct redis error: {0}")]
    DirectError(#[from] DirectError),

}

#[derive(Error, Debug)]
pub enum MobcError {
    #[error("could not get redis connection from pool : {0}")]
    RedisPoolError(mobc::Error<mobc_redis::redis::RedisError>),
    #[error("error parsing string from redis result: {0}")]
    RedisTypeError(redis::RedisError),
    #[error("error executing redis command: {0}")]
    RedisCMDError(redis::RedisError),
    #[error("error creating Redis client: {0}")]
    RedisClientError(redis::RedisError),
}

#[derive(Error, Debug)]
pub enum DirectError {
    #[error("error parsing string from redis result: {0}")]
    RedisTypeError(redis::RedisError),
    #[error("error executing redis command: {0}")]
    RedisCMDError(redis::RedisError),
    #[error("error creating Redis client: {0}")]
    RedisClientError(redis::RedisError),
}

我在cargo中使用的一些依赖项。toml:

thiserror = "1.0"
mobc = "0.7"
mobc-redis = "0.7.0"
redis = "0.21.3"
tokio = { version = "1.12.0", features = ["full"] }

当我得到结果并检查这行cached_playlist.as_ref().unwrap().is_empty()中的结果时,显示如下错误:

/Users/dolphin/Documents/GitHub/rust-learn/target/debug/rust-learn
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: DirectError(RedisTypeError(Response was of incompatible type: "Response type not string compatible." (response was nil)))', src/main.rs:31:33
stack backtrace:
   0: rust_begin_unwind
             at /rustc/a178d0322ce20e33eac124758e837cbd80a6f633/library/std/src/panicking.rs:515:5
   1: core::panicking::panic_fmt
             at /rustc/a178d0322ce20e33eac124758e837cbd80a6f633/library/core/src/panicking.rs:92:14
   2: core::result::unwrap_failed
             at /rustc/a178d0322ce20e33eac124758e837cbd80a6f633/library/core/src/result.rs:1355:5
   3: core::result::Result<T,E>::unwrap
             at /rustc/a178d0322ce20e33eac124758e837cbd80a6f633/library/core/src/result.rs:1037:23
   4: rust_learn::main::{{closure}}
             at ./src/main.rs:31:8
   5: <core::future::from_generator::GenFuture<T> as core::future::future::Future>::poll
             at /rustc/a178d0322ce20e33eac124758e837cbd80a6f633/library/core/src/future/mod.rs:80:19
   6: tokio::park::thread::CachedParkThread::block_on::{{closure}}
             at /Users/dolphin/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-1.12.0/src/park/thread.rs:263:54
   7: tokio::coop::with_budget::{{closure}}
             at /Users/dolphin/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-1.12.0/src/coop.rs:106:9
   8: std::thread::local::LocalKey<T>::try_with
             at /rustc/a178d0322ce20e33eac124758e837cbd80a6f633/library/std/src/thread/local.rs:400:16
   9: std::thread::local::LocalKey<T>::with
             at /rustc/a178d0322ce20e33eac124758e837cbd80a6f633/library/std/src/thread/local.rs:376:9
  10: tokio::coop::with_budget
             at /Users/dolphin/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-1.12.0/src/coop.rs:99:5
  11: tokio::coop::budget
             at /Users/dolphin/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-1.12.0/src/coop.rs:76:5
  12: tokio::park::thread::CachedParkThread::block_on
             at /Users/dolphin/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-1.12.0/src/park/thread.rs:263:31
  13: tokio::runtime::enter::Enter::block_on
             at /Users/dolphin/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-1.12.0/src/runtime/enter.rs:151:13
  14: tokio::runtime::thread_pool::ThreadPool::block_on
             at /Users/dolphin/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-1.12.0/src/runtime/thread_pool/mod.rs:77:9
  15: tokio::runtime::Runtime::block_on
             at /Users/dolphin/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-1.12.0/src/runtime/mod.rs:463:43
  16: rust_learn::main
             at ./src/main.rs:34:5
  17: core::ops::function::FnOnce::call_once
             at /rustc/a178d0322ce20e33eac124758e837cbd80a6f633/library/core/src/ops/function.rs:227:5
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.

当它返回nil时我该怎么办?如何检查nil值?我没有发现铁 rust 中的零定义。我试过这样做:

if redis::Value::Nil == cached_playlist.as_ref().unwrap() {
        print!("d")
    }

但显示错误:

error[E0308]: mismatched types
  --> src/main.rs:32:29
   |
32 |     if redis::Value::Nil == cached_playlist.as_ref().unwrap() {
   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected enum `redis::Value`, found `&std::string::String`
ruoxqz4g

ruoxqz4g1#

正如注解中提到的,我们必须检查Nil值(当不存在值时,Redis客户端返回Nil(类型值))。
下面是更新的get_str函数:

pub async fn get_str(con: &mut Connection, key: &str) -> Result<String> {
    let value = con.get(key).map_err(RedisCMDError)?;
    match value {
        redis::Value::Nil => Ok(String::new()),
        _ => FromRedisValue::from_redis_value(&value).map_err(|e| RedisTypeError(e).into()),
    }
    // returns an empty string if the Redis response is Nil 
}

现在,检查main函数中的Nil

let cached_playlist = get_str(&mut redis_conn.unwrap(), "dd").await?;
if cached_playlist.is_empty() {
    println!("Cache is empty");
}

相关问题