redis compression (#6769)

* feat(labrinth): encode/decode redis values with postcard, add version in namespaces

* chore(labrinth): split cache ex special cases without version

* chore(labrinth): simplify get_many

* fix: tombi

* feat(labrinth): compression support

* chore(labrinth): cleanup redis ser/de

* fix(labrinth): use get_deserialized in tests
This commit is contained in:
François-Xavier Talbot
2026-07-19 01:25:00 +02:00
committed by GitHub
parent 6b62e3b480
commit 6b569e4ee4
40 changed files with 361 additions and 242 deletions
+17 -12
View File
@@ -1,4 +1,6 @@
use crate::database::PgPool;
use crate::database::models::notification_item::DBNotification;
use crate::models::ids::NotificationId;
use crate::models::notifications::Notification;
use crate::queue::socket::ActiveSockets;
use crate::routes::internal::statuses::{
@@ -13,10 +15,9 @@ use redis::{RedisWrite, ToRedisArgs};
use serde::{Deserialize, Serialize};
use tokio_stream::StreamExt;
pub const FRIENDS_CHANNEL_NAME: &str = "friends";
pub const FRIENDS_CHANNEL_NAME: &str = "friends:v1";
#[derive(Serialize, Deserialize)]
#[serde(tag = "type", rename_all = "snake_case")]
pub enum RedisFriendsMessage {
StatusUpdate {
status: UserStatus,
@@ -30,7 +31,7 @@ pub enum RedisFriendsMessage {
},
Notification {
to_user: UserId,
notification: Notification,
notification_id: NotificationId,
},
}
@@ -39,7 +40,7 @@ impl ToRedisArgs for RedisFriendsMessage {
where
W: ?Sized + RedisWrite,
{
out.write_arg(&serde_json::to_vec(&self).unwrap())
out.write_arg(&postcard::to_allocvec(&self).unwrap())
}
}
@@ -54,7 +55,7 @@ pub async fn handle_pubsub(
if message.get_channel_name() != FRIENDS_CHANNEL_NAME {
continue;
}
let payload = serde_json::from_slice(message.get_payload_bytes());
let payload = postcard::from_bytes(message.get_payload_bytes());
let pool = pool.clone();
let sockets = sockets.clone();
@@ -94,14 +95,18 @@ pub async fn handle_pubsub(
Ok(RedisFriendsMessage::Notification {
to_user,
notification,
notification_id,
}) => {
let _ = send_notification_to_user(
&sockets,
to_user,
&notification,
)
.await;
if let Ok(Some(notification)) =
DBNotification::get(notification_id.into(), &pool).await
{
let _ = send_notification_to_user(
&sockets,
to_user,
&Notification::from(notification),
)
.await;
}
}
Err(_) => {}
+6 -6
View File
@@ -17,10 +17,10 @@ pub async fn get_user_status(
if let Ok(mut conn) = redis.pool.get().await
&& let Ok(mut statuses) =
conn.sscan::<_, String>(get_field_name(user)).await
&& let Some(status_json) = statuses.next_item().await
conn.sscan::<_, Vec<u8>>(get_field_name(user)).await
&& let Some(status) = statuses.next_item().await
{
return serde_json::from_str::<UserStatus>(&status_json).ok();
return postcard::from_bytes::<UserStatus>(&status).ok();
}
None
@@ -40,11 +40,11 @@ pub async fn replace_user_status(
let mut pipe = redis::pipe();
pipe.atomic();
if let Some(status) = old_status {
pipe.srem(&field_name, serde_json::to_string(&status).unwrap())
pipe.srem(&field_name, postcard::to_allocvec(status).unwrap())
.ignore();
}
if let Some(status) = new_status {
pipe.sadd(&field_name, serde_json::to_string(&status).unwrap())
pipe.sadd(&field_name, postcard::to_allocvec(status).unwrap())
.ignore();
pipe.expire(&field_name, EXPIRY_TIME_SECONDS).ignore();
}
@@ -65,5 +65,5 @@ pub async fn push_back_user_expiry(
}
fn get_field_name(user: UserId) -> String {
format!("user_status:{user}")
format!("user_status:v1:{user}")
}