use napi::bindgen_prelude::*;
use napi_derive::napi;
use redis::AsyncCommands;
use redis_swapplex::get_connection;
use serde_json::Value;
#[napi]
pub async fn get(key: String) -> Result<Option<Value>> {
let mut conn = get_connection();
let bytes: Option<Vec<u8>> = conn
.get(key)
.await
.map_err(|err| Error::new(Status::GenericFailure, format!("{:?}", err)))?;
if let Some(mut bytes) = bytes {
let value: Value = simd_json::serde::from_slice(bytes.as_mut_slice())
.map_err(|err| Error::new(Status::GenericFailure, err.to_string()))?;
Ok(Some(value))
} else {
Ok(None)
}
}
#[napi]
pub async fn mget(keys: Vec<String>) -> Result<Vec<Option<Value>>> {
let mut conn = get_connection();
let data: Vec<Option<Vec<u8>>> = redis::cmd("MGET")
.arg(&keys)
.query_async(&mut conn)
.await
.map_err(|err| Error::new(Status::GenericFailure, format!("{:?}", err)))?;
data
.into_iter()
.map(|bytes| {
if let Some(mut bytes) = bytes {
let value = simd_json::serde::from_slice(bytes.as_mut_slice())
.map_err(|err| Error::new(Status::GenericFailure, err.to_string()))?;
Ok(Some(value))
} else {
Ok(None)
}
})
.collect::<Result<Vec<Option<Value>>>>()
}
#[napi]
pub async fn set(key: String, value: Option<Value>) -> Result<()> {
let value = match value {
Some(value) => Some(
simd_json::to_vec(&value)
.map_err(|err| Error::new(Status::GenericFailure, err.to_string()))?,
),
None => None,
};
let mut conn = get_connection();
let _: () = conn
.set(key, value)
.await
.map_err(|err| Error::new(Status::GenericFailure, format!("{:?}", err)))?;
Ok(())
}
#[napi]
pub async fn compare_and_swap(key: String, current: Value, value: Option<Value>) -> Result<i64> {
let current = simd_json::to_vec(¤t)
.map_err(|err| Error::new(Status::GenericFailure, err.to_string()))?;
let value = match value {
Some(value) => simd_json::to_vec(&value)
.map_err(|err| Error::new(Status::GenericFailure, err.to_string()))?,
None => vec![],
};
let mut conn = get_connection();
let n_modified: i64 = redis::cmd("CAS")
.arg(&[key.as_bytes(), ¤t, &value])
.query_async(&mut conn)
.await
.map_err(|err| Error::new(Status::GenericFailure, format!("{:?}", err)))?;
Ok(n_modified)
}
#[napi]
pub async fn mset(data: Vec<(String, Option<Value>)>) -> Result<()> {
let data = data
.into_iter()
.map(|(key, value)| match value {
Some(value) => {
let bytes: Vec<u8> = simd_json::to_vec(&value)
.map_err(|err| Error::new(Status::GenericFailure, err.to_string()))?;
Ok((key, Some(bytes)))
}
None => Ok((key, None)),
})
.collect::<Result<Vec<(String, Option<Vec<u8>>)>>>()?;
let mut conn = get_connection();
let _: () = redis::cmd("MSET")
.arg(&data[..])
.query_async(&mut conn)
.await
.map_err(|err| Error::new(Status::GenericFailure, format!("{:?}", err)))?;
Ok(())
}