1
0
Fork 0
forked from gorb/backend

feat: use new error type in structs, utils and config

This commit is contained in:
Radical 2025-05-23 12:54:52 +02:00
parent 3e698edf8c
commit 49db25e454
3 changed files with 144 additions and 221 deletions

View file

@ -1,4 +1,4 @@
use crate::Error; use crate::error::Error;
use log::debug; use log::debug;
use serde::Deserialize; use serde::Deserialize;
use tokio::fs::read_to_string; use tokio::fs::read_to_string;

View file

@ -1,11 +1,17 @@
use actix_web::HttpResponse;
use diesel::{delete, insert_into, prelude::{Insertable, Queryable}, ExpressionMethods, QueryDsl, Selectable, SelectableHelper}; use diesel::{delete, insert_into, prelude::{Insertable, Queryable}, ExpressionMethods, QueryDsl, Selectable, SelectableHelper};
use log::error;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use uuid::Uuid; use uuid::Uuid;
use diesel_async::{pooled_connection::AsyncDieselConnectionManager, RunQueryDsl}; use diesel_async::{pooled_connection::AsyncDieselConnectionManager, RunQueryDsl};
use crate::{Conn, Data, schema::*}; use crate::{error::Error, Conn, Data, schema::*};
fn load_or_empty<T>(query_result: Result<Vec<T>, diesel::result::Error>) -> Result<Vec<T>, diesel::result::Error> {
match query_result {
Ok(vec) => Ok(vec),
Err(diesel::result::Error::NotFound) => Ok(Vec::new()),
Err(e) => Err(e),
}
}
#[derive(Queryable, Selectable, Insertable, Clone)] #[derive(Queryable, Selectable, Insertable, Clone)]
#[diesel(table_name = channels)] #[diesel(table_name = channels)]
@ -18,13 +24,15 @@ struct ChannelBuilder {
} }
impl ChannelBuilder { impl ChannelBuilder {
async fn build(self, conn: &mut Conn) -> Result<Channel, crate::Error> { async fn build(self, conn: &mut Conn) -> Result<Channel, Error> {
use self::channel_permissions::dsl::*; use self::channel_permissions::dsl::*;
let channel_permission: Vec<ChannelPermission> = channel_permissions let channel_permission: Vec<ChannelPermission> = load_or_empty(
.filter(channel_uuid.eq(self.uuid)) channel_permissions
.select((role_uuid, permissions)) .filter(channel_uuid.eq(self.uuid))
.load(conn) .select(ChannelPermission::as_select())
.await?; .load(conn)
.await
)?;
Ok(Channel { Ok(Channel {
uuid: self.uuid, uuid: self.uuid,
@ -45,7 +53,7 @@ pub struct Channel {
pub permissions: Vec<ChannelPermission>, pub permissions: Vec<ChannelPermission>,
} }
#[derive(Serialize, Deserialize, Clone, Queryable)] #[derive(Serialize, Deserialize, Clone, Queryable, Selectable)]
#[diesel(table_name = channel_permissions)] #[diesel(table_name = channel_permissions)]
#[diesel(check_for_backend(diesel::pg::Pg))] #[diesel(check_for_backend(diesel::pg::Pg))]
pub struct ChannelPermission { pub struct ChannelPermission {
@ -57,69 +65,38 @@ impl Channel {
pub async fn fetch_all( pub async fn fetch_all(
pool: &deadpool::managed::Pool<AsyncDieselConnectionManager<diesel_async::AsyncPgConnection>, Conn>, pool: &deadpool::managed::Pool<AsyncDieselConnectionManager<diesel_async::AsyncPgConnection>, Conn>,
guild_uuid: Uuid, guild_uuid: Uuid,
) -> Result<Vec<Self>, HttpResponse> { ) -> Result<Vec<Self>, Error> {
let mut conn = pool.get().await.unwrap(); let mut conn = pool.get().await?;
use channels::dsl; use channels::dsl;
let channel_builders_result: Result<Vec<ChannelBuilder>, diesel::result::Error> = dsl::channels let channel_builders: Vec<ChannelBuilder> = load_or_empty(
.filter(dsl::guild_uuid.eq(guild_uuid)) dsl::channels
.select(ChannelBuilder::as_select()) .filter(dsl::guild_uuid.eq(guild_uuid))
.load(&mut conn) .select(ChannelBuilder::as_select())
.await; .load(&mut conn)
.await
if let Err(error) = channel_builders_result { )?;
error!("{}", error);
return Err(HttpResponse::InternalServerError().finish());
}
let channel_builders = channel_builders_result.unwrap();
let channel_futures = channel_builders.iter().map(async move |c| { let channel_futures = channel_builders.iter().map(async move |c| {
let mut conn = pool.get().await?; let mut conn = pool.get().await?;
c.clone().build(&mut conn).await c.clone().build(&mut conn).await
}); });
futures::future::try_join_all(channel_futures).await
let channels = futures::future::try_join_all(channel_futures).await;
if let Err(error) = channels {
error!("{}", error);
return Err(HttpResponse::InternalServerError().finish())
}
Ok(channels.unwrap())
} }
pub async fn fetch_one( pub async fn fetch_one(
conn: &mut Conn, conn: &mut Conn,
channel_uuid: Uuid, channel_uuid: Uuid,
) -> Result<Self, HttpResponse> { ) -> Result<Self, Error> {
use channels::dsl; use channels::dsl;
let channel_builder_result: Result<ChannelBuilder, diesel::result::Error> = dsl::channels let channel_builder: ChannelBuilder = dsl::channels
.filter(dsl::uuid.eq(channel_uuid)) .filter(dsl::uuid.eq(channel_uuid))
.select(ChannelBuilder::as_select()) .select(ChannelBuilder::as_select())
.get_result(conn) .get_result(conn)
.await; .await?;
if let Err(error) = channel_builder_result { channel_builder.build(conn).await
error!("{}", error);
return Err(HttpResponse::InternalServerError().finish())
}
let channel_builder = channel_builder_result.unwrap();
let channel = channel_builder.build(conn).await;
if let Err(error) = channel {
error!("{}", error);
return Err(HttpResponse::InternalServerError().finish())
}
Ok(channel.unwrap())
} }
pub async fn new( pub async fn new(
@ -127,8 +104,8 @@ impl Channel {
guild_uuid: Uuid, guild_uuid: Uuid,
name: String, name: String,
description: Option<String>, description: Option<String>,
) -> Result<Self, HttpResponse> { ) -> Result<Self, Error> {
let mut conn = data.pool.get().await.unwrap(); let mut conn = data.pool.get().await?;
let channel_uuid = Uuid::now_v7(); let channel_uuid = Uuid::now_v7();
@ -139,15 +116,10 @@ impl Channel {
description: description.clone(), description: description.clone(),
}; };
let insert_result = insert_into(channels::table) insert_into(channels::table)
.values(new_channel) .values(new_channel)
.execute(&mut conn) .execute(&mut conn)
.await; .await?;
if let Err(error) = insert_result {
error!("{}", error);
return Err(HttpResponse::InternalServerError().finish());
}
// returns different object because there's no reason to build the channelbuilder (wastes 1 database request) // returns different object because there's no reason to build the channelbuilder (wastes 1 database request)
let channel = Self { let channel = Self {
@ -158,37 +130,21 @@ impl Channel {
permissions: vec![], permissions: vec![],
}; };
let cache_result = data data
.set_cache_key(channel_uuid.to_string(), channel.clone(), 1800) .set_cache_key(channel_uuid.to_string(), channel.clone(), 1800)
.await; .await?;
if let Err(error) = cache_result { data.del_cache_key(format!("{}_channels", guild_uuid)).await?;
error!("{}", error);
return Err(HttpResponse::InternalServerError().finish());
}
let cache_deletion_result = data.del_cache_key(format!("{}_channels", guild_uuid)).await;
if let Err(error) = cache_deletion_result {
error!("{}", error);
return Err(HttpResponse::InternalServerError().finish());
}
Ok(channel) Ok(channel)
} }
pub async fn delete(self, conn: &mut Conn) -> Result<(), HttpResponse> { pub async fn delete(self, conn: &mut Conn) -> Result<(), Error> {
use channels::dsl; use channels::dsl;
let result = delete(channels::table) delete(channels::table)
.filter(dsl::uuid.eq(self.uuid)) .filter(dsl::uuid.eq(self.uuid))
.execute(conn) .execute(conn)
.await; .await?;
if let Err(error) = result {
error!("{}", error);
return Err(HttpResponse::InternalServerError().finish());
}
Ok(()) Ok(())
} }
@ -198,22 +154,19 @@ impl Channel {
conn: &mut Conn, conn: &mut Conn,
amount: i64, amount: i64,
offset: i64, offset: i64,
) -> Result<Vec<Message>, HttpResponse> { ) -> Result<Vec<Message>, Error> {
use messages::dsl; use messages::dsl;
let messages: Result<Vec<Message>, diesel::result::Error> = dsl::messages let messages: Vec<Message> = load_or_empty(
.filter(dsl::channel_uuid.eq(self.uuid)) dsl::messages
.select(Message::as_select()) .filter(dsl::channel_uuid.eq(self.uuid))
.limit(amount) .select(Message::as_select())
.offset(offset) .limit(amount)
.load(conn) .offset(offset)
.await; .load(conn)
.await
)?;
if let Err(error) = messages { Ok(messages)
error!("{}", error);
return Err(HttpResponse::InternalServerError().finish());
}
Ok(messages.unwrap())
} }
pub async fn new_message( pub async fn new_message(
@ -221,7 +174,7 @@ impl Channel {
conn: &mut Conn, conn: &mut Conn,
user_uuid: Uuid, user_uuid: Uuid,
message: String, message: String,
) -> Result<Message, HttpResponse> { ) -> Result<Message, Error> {
let message_uuid = Uuid::now_v7(); let message_uuid = Uuid::now_v7();
let message = Message { let message = Message {
@ -231,15 +184,10 @@ impl Channel {
message, message,
}; };
let insert_result = insert_into(messages::table) insert_into(messages::table)
.values(message.clone()) .values(message.clone())
.execute(conn) .execute(conn)
.await; .await?;
if let Err(error) = insert_result {
error!("{}", error);
return Err(HttpResponse::InternalServerError().finish());
}
Ok(message) Ok(message)
} }
@ -294,7 +242,7 @@ struct GuildBuilder {
} }
impl GuildBuilder { impl GuildBuilder {
async fn build(self, conn: &mut Conn) -> Result<Guild, HttpResponse> { async fn build(self, conn: &mut Conn) -> Result<Guild, Error> {
let member_count = Member::count(conn, self.uuid).await?; let member_count = Member::count(conn, self.uuid).await?;
let roles = Role::fetch_all(conn, self.uuid).await?; let roles = Role::fetch_all(conn, self.uuid).await?;
@ -323,49 +271,39 @@ pub struct Guild {
} }
impl Guild { impl Guild {
pub async fn fetch_one(conn: &mut Conn, guild_uuid: Uuid) -> Result<Self, HttpResponse> { pub async fn fetch_one(conn: &mut Conn, guild_uuid: Uuid) -> Result<Self, Error> {
use guilds::dsl; use guilds::dsl;
let guild_builder: Result<GuildBuilder, diesel::result::Error> = dsl::guilds let guild_builder: GuildBuilder = dsl::guilds
.filter(dsl::uuid.eq(guild_uuid)) .filter(dsl::uuid.eq(guild_uuid))
.select(GuildBuilder::as_select()) .select(GuildBuilder::as_select())
.get_result(conn) .get_result(conn)
.await; .await?;
if let Err(error) = guild_builder { guild_builder.build(conn).await
error!("{}", error);
return Err(HttpResponse::InternalServerError().finish());
}
let guild = guild_builder.unwrap().build(conn).await?;
Ok(guild)
} }
pub async fn fetch_amount( pub async fn fetch_amount(
pool: &deadpool::managed::Pool<AsyncDieselConnectionManager<diesel_async::AsyncPgConnection>, Conn>, pool: &deadpool::managed::Pool<AsyncDieselConnectionManager<diesel_async::AsyncPgConnection>, Conn>,
offset: i64, offset: i64,
amount: i64, amount: i64,
) -> Result<Vec<Self>, HttpResponse> { ) -> Result<Vec<Self>, Error> {
// Fetch guild data from database // Fetch guild data from database
let mut conn = pool.get().await.unwrap(); let mut conn = pool.get().await?;
use guilds::dsl; use guilds::dsl;
let guild_builders: Vec<GuildBuilder> = dsl::guilds let guild_builders: Vec<GuildBuilder> = load_or_empty(
.select(GuildBuilder::as_select()) dsl::guilds
.order_by(dsl::uuid) .select(GuildBuilder::as_select())
.offset(offset) .order_by(dsl::uuid)
.limit(amount) .offset(offset)
.load(&mut conn) .limit(amount)
.await .load(&mut conn)
.map_err(|error| { .await
error!("{}", error); )?;
HttpResponse::InternalServerError().finish()
})?;
// Process each guild concurrently // Process each guild concurrently
let guild_futures = guild_builders.iter().map(async move |g| { let guild_futures = guild_builders.iter().map(async move |g| {
let mut conn = pool.get().await.unwrap(); let mut conn = pool.get().await?;
g.clone().build(&mut conn).await g.clone().build(&mut conn).await
}); });
@ -378,7 +316,7 @@ impl Guild {
name: String, name: String,
description: Option<String>, description: Option<String>,
owner_uuid: Uuid, owner_uuid: Uuid,
) -> Result<Self, HttpResponse> { ) -> Result<Self, Error> {
let guild_uuid = Uuid::now_v7(); let guild_uuid = Uuid::now_v7();
let guild_builder = GuildBuilder { let guild_builder = GuildBuilder {
@ -391,11 +329,21 @@ impl Guild {
insert_into(guilds::table) insert_into(guilds::table)
.values(guild_builder) .values(guild_builder)
.execute(conn) .execute(conn)
.await .await?;
.map_err(|error| {
error!("{}", error); let member_uuid = Uuid::now_v7();
HttpResponse::InternalServerError().finish()
})?; let member = Member {
uuid: member_uuid,
nickname: None,
user_uuid: owner_uuid,
guild_uuid,
};
insert_into(guild_members::table)
.values(member)
.execute(conn)
.await?;
Ok(Guild { Ok(Guild {
uuid: guild_uuid, uuid: guild_uuid,
@ -408,17 +356,15 @@ impl Guild {
}) })
} }
pub async fn get_invites(&self, conn: &mut Conn) -> Result<Vec<Invite>, HttpResponse> { pub async fn get_invites(&self, conn: &mut Conn) -> Result<Vec<Invite>, Error> {
use invites::dsl; use invites::dsl;
let invites = dsl::invites let invites = load_or_empty(
.filter(dsl::guild_uuid.eq(self.uuid)) dsl::invites
.select(Invite::as_select()) .filter(dsl::guild_uuid.eq(self.uuid))
.load(conn) .select(Invite::as_select())
.await .load(conn)
.map_err(|error| { .await
error!("{}", error); )?;
HttpResponse::InternalServerError().finish()
})?;
Ok(invites) Ok(invites)
} }
@ -428,13 +374,13 @@ impl Guild {
conn: &mut Conn, conn: &mut Conn,
member: &Member, member: &Member,
custom_id: Option<String>, custom_id: Option<String>,
) -> Result<Invite, HttpResponse> { ) -> Result<Invite, Error> {
let invite_id; let invite_id;
if let Some(id) = custom_id { if let Some(id) = custom_id {
invite_id = id; invite_id = id;
if invite_id.len() > 32 { if invite_id.len() > 32 {
return Err(HttpResponse::BadRequest().finish()); return Err(Error::BadRequest("MAX LENGTH".to_string()))
} }
} else { } else {
let charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; let charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
@ -451,11 +397,7 @@ impl Guild {
insert_into(invites::table) insert_into(invites::table)
.values(invite.clone()) .values(invite.clone())
.execute(conn) .execute(conn)
.await .await?;
.map_err(|error| {
error!("{}", error);
HttpResponse::InternalServerError().finish()
})?;
Ok(invite) Ok(invite)
} }
@ -477,17 +419,15 @@ impl Role {
pub async fn fetch_all( pub async fn fetch_all(
conn: &mut Conn, conn: &mut Conn,
guild_uuid: Uuid, guild_uuid: Uuid,
) -> Result<Vec<Self>, HttpResponse> { ) -> Result<Vec<Self>, Error> {
use roles::dsl; use roles::dsl;
let roles: Vec<Role> = dsl::roles let roles: Vec<Role> = load_or_empty(
.filter(dsl::guild_uuid.eq(guild_uuid)) dsl::roles
.select(Role::as_select()) .filter(dsl::guild_uuid.eq(guild_uuid))
.load(conn) .select(Role::as_select())
.await .load(conn)
.map_err(|error| { .await
error!("{}", error); )?;
HttpResponse::InternalServerError().finish()
})?;
Ok(roles) Ok(roles)
} }
@ -495,17 +435,13 @@ impl Role {
pub async fn fetch_one( pub async fn fetch_one(
conn: &mut Conn, conn: &mut Conn,
role_uuid: Uuid, role_uuid: Uuid,
) -> Result<Self, HttpResponse> { ) -> Result<Self, Error> {
use roles::dsl; use roles::dsl;
let role: Role = dsl::roles let role: Role = dsl::roles
.filter(dsl::uuid.eq(role_uuid)) .filter(dsl::uuid.eq(role_uuid))
.select(Role::as_select()) .select(Role::as_select())
.get_result(conn) .get_result(conn)
.await .await?;
.map_err(|error| {
error!("{}", error);
HttpResponse::InternalServerError().finish()
})?;
Ok(role) Ok(role)
} }
@ -514,7 +450,7 @@ impl Role {
conn: &mut Conn, conn: &mut Conn,
guild_uuid: Uuid, guild_uuid: Uuid,
name: String, name: String,
) -> Result<Self, HttpResponse> { ) -> Result<Self, Error> {
let role_uuid = Uuid::now_v7(); let role_uuid = Uuid::now_v7();
let role = Role { let role = Role {
@ -529,11 +465,7 @@ impl Role {
insert_into(roles::table) insert_into(roles::table)
.values(role.clone()) .values(role.clone())
.execute(conn) .execute(conn)
.await .await?;
.map_err(|error| {
error!("{}", error);
HttpResponse::InternalServerError().finish()
})?;
Ok(role) Ok(role)
} }
@ -550,17 +482,13 @@ pub struct Member {
} }
impl Member { impl Member {
async fn count(conn: &mut Conn, guild_uuid: Uuid) -> Result<i64, HttpResponse> { async fn count(conn: &mut Conn, guild_uuid: Uuid) -> Result<i64, Error> {
use guild_members::dsl; use guild_members::dsl;
let count: i64 = dsl::guild_members let count: i64 = dsl::guild_members
.filter(dsl::guild_uuid.eq(guild_uuid)) .filter(dsl::guild_uuid.eq(guild_uuid))
.count() .count()
.get_result(conn) .get_result(conn)
.await .await?;
.map_err(|error| {
error!("{}", error);
HttpResponse::InternalServerError()
})?;
Ok(count) Ok(count)
} }
@ -569,18 +497,14 @@ impl Member {
conn: &mut Conn, conn: &mut Conn,
user_uuid: Uuid, user_uuid: Uuid,
guild_uuid: Uuid, guild_uuid: Uuid,
) -> Result<Self, HttpResponse> { ) -> Result<Self, Error> {
use guild_members::dsl; use guild_members::dsl;
let member: Member = dsl::guild_members let member: Member = dsl::guild_members
.filter(dsl::user_uuid.eq(user_uuid)) .filter(dsl::user_uuid.eq(user_uuid))
.filter(dsl::guild_uuid.eq(guild_uuid)) .filter(dsl::guild_uuid.eq(guild_uuid))
.select(Member::as_select()) .select(Member::as_select())
.get_result(conn) .get_result(conn)
.await .await?;
.map_err(|error| {
error!("{}", error);
HttpResponse::InternalServerError().finish()
})?;
Ok(member) Ok(member)
} }
@ -589,7 +513,7 @@ impl Member {
conn: &mut Conn, conn: &mut Conn,
user_uuid: Uuid, user_uuid: Uuid,
guild_uuid: Uuid, guild_uuid: Uuid,
) -> Result<Self, HttpResponse> { ) -> Result<Self, Error> {
let member_uuid = Uuid::now_v7(); let member_uuid = Uuid::now_v7();
let member = Member { let member = Member {
@ -602,11 +526,7 @@ impl Member {
insert_into(guild_members::table) insert_into(guild_members::table)
.values(member) .values(member)
.execute(conn) .execute(conn)
.await .await?;
.map_err(|error| {
error!("{}", error);
HttpResponse::InternalServerError().finish()
})?;
Ok(Self { Ok(Self {
uuid: member_uuid, uuid: member_uuid,
@ -639,17 +559,13 @@ pub struct Invite {
} }
impl Invite { impl Invite {
pub async fn fetch_one(conn: &mut Conn, invite_id: String) -> Result<Self, HttpResponse> { pub async fn fetch_one(conn: &mut Conn, invite_id: String) -> Result<Self, Error> {
use invites::dsl; use invites::dsl;
let invite: Invite = dsl::invites let invite: Invite = dsl::invites
.filter(dsl::id.eq(invite_id)) .filter(dsl::id.eq(invite_id))
.select(Invite::as_select()) .select(Invite::as_select())
.get_result(conn) .get_result(conn)
.await .await?;
.map_err(|error| {
error!("{}", error);
HttpResponse::InternalServerError().finish()
})?;
Ok(invite) Ok(invite)
} }
@ -657,6 +573,6 @@ impl Invite {
#[derive(Deserialize)] #[derive(Deserialize)]
pub struct StartAmountQuery { pub struct StartAmountQuery {
pub start: Option<i32>, pub start: Option<i64>,
pub amount: Option<i32>, pub amount: Option<i64>,
} }

View file

@ -1,5 +1,4 @@
use actix_web::{ use actix_web::{
HttpResponse,
cookie::{Cookie, SameSite, time::Duration}, cookie::{Cookie, SameSite, time::Duration},
http::header::HeaderMap, http::header::HeaderMap,
}; };
@ -8,25 +7,31 @@ use hex::encode;
use redis::RedisError; use redis::RedisError;
use serde::Serialize; use serde::Serialize;
use crate::Data; use crate::{error::Error, Data};
pub fn get_auth_header(headers: &HeaderMap) -> Result<&str, HttpResponse> { pub fn get_auth_header(headers: &HeaderMap) -> Result<&str, Error> {
let auth_token = headers.get(actix_web::http::header::AUTHORIZATION); let auth_token = headers.get(actix_web::http::header::AUTHORIZATION);
if auth_token.is_none() { if auth_token.is_none() {
return Err(HttpResponse::Unauthorized().finish()); return Err(Error::Unauthorized("No authorization header provided".to_string()));
} }
let auth = auth_token.unwrap().to_str(); let auth_raw = auth_token.unwrap().to_str()?;
if let Err(error) = auth { let mut auth = auth_raw.split_whitespace();
return Err(HttpResponse::Unauthorized().json(format!(r#" {{ "error": "{}" }} "#, error)));
let auth_type = auth.nth(0);
let auth_value = auth.nth(0);
if auth_type.is_none() {
return Err(Error::BadRequest("Authorization header is empty".to_string()));
} else if auth_type.is_some_and(|at| at != "Bearer") {
return Err(Error::BadRequest("Only token auth is supported".to_string()));
} }
let auth_value = auth.unwrap().split_whitespace().nth(1);
if auth_value.is_none() { if auth_value.is_none() {
return Err(HttpResponse::BadRequest().finish()); return Err(Error::BadRequest("No token provided".to_string()));
} }
Ok(auth_value.unwrap()) Ok(auth_value.unwrap())
@ -60,12 +65,12 @@ impl Data {
key: String, key: String,
value: impl Serialize, value: impl Serialize,
expire: u32, expire: u32,
) -> Result<(), RedisError> { ) -> Result<(), Error> {
let mut conn = self.cache_pool.get_multiplexed_tokio_connection().await?; let mut conn = self.cache_pool.get_multiplexed_tokio_connection().await?;
let key_encoded = encode(key); let key_encoded = encode(key);
let value_json = serde_json::to_string(&value).unwrap(); let value_json = serde_json::to_string(&value)?;
redis::cmd("SET") redis::cmd("SET")
.arg(&[key_encoded.clone(), value_json]) .arg(&[key_encoded.clone(), value_json])
@ -75,7 +80,9 @@ impl Data {
redis::cmd("EXPIRE") redis::cmd("EXPIRE")
.arg(&[key_encoded, expire.to_string()]) .arg(&[key_encoded, expire.to_string()])
.exec_async(&mut conn) .exec_async(&mut conn)
.await .await?;
Ok(())
} }
pub async fn get_cache_key(&self, key: String) -> Result<String, RedisError> { pub async fn get_cache_key(&self, key: String) -> Result<String, RedisError> {