feat: Rewrite acks (#741)
* feat: rewrite ack system Signed-off-by: IAmTomahawkx <iamtomahawkx@gmail.com> * feat: rewrite acks to crond + rabbit task * fix: review changes --------- Signed-off-by: IAmTomahawkx <iamtomahawkx@gmail.com>
This commit is contained in:
129
crates/daemons/crond/src/tasks/acks.rs
Normal file
129
crates/daemons/crond/src/tasks/acks.rs
Normal file
@@ -0,0 +1,129 @@
|
||||
use futures_lite::stream::StreamExt;
|
||||
use lapin::{
|
||||
options::*,
|
||||
types::FieldTable,
|
||||
uri::{AMQPAuthority, AMQPQueryString, AMQPUri, AMQPUserInfo},
|
||||
ConnectionBuilder, ConnectionProperties,
|
||||
};
|
||||
use log::info;
|
||||
use redis_kiss::{get_connection, AsyncCommands, Conn as RedisConnection};
|
||||
use revolt_config::config;
|
||||
use revolt_database::{events::rabbit::AckEventPayload, Database};
|
||||
use revolt_result::{Result, ToRevoltError};
|
||||
use serde_json;
|
||||
|
||||
pub async fn task(db: Database) -> Result<()> {
|
||||
let config = config().await;
|
||||
|
||||
let mut redis = get_connection()
|
||||
.await
|
||||
.expect("Failed to get redis connection");
|
||||
|
||||
let uri = AMQPUri {
|
||||
scheme: lapin::uri::AMQPScheme::AMQP,
|
||||
authority: AMQPAuthority {
|
||||
userinfo: AMQPUserInfo {
|
||||
username: config.rabbit.username,
|
||||
password: config.rabbit.password,
|
||||
},
|
||||
host: config.rabbit.host,
|
||||
port: config.rabbit.port,
|
||||
},
|
||||
vhost: "/".to_string(),
|
||||
query: AMQPQueryString::default(),
|
||||
};
|
||||
|
||||
let connection = ConnectionBuilder::new()
|
||||
.expect("Builder")
|
||||
.with_uri(uri)
|
||||
.with_properties(ConnectionProperties::default())
|
||||
.connect()
|
||||
.await
|
||||
.expect("Failed to connect to rabbitmq");
|
||||
|
||||
let reader_channel = connection
|
||||
.create_channel()
|
||||
.await
|
||||
.expect("Failed to create channel");
|
||||
|
||||
let mut consumer = reader_channel
|
||||
.basic_consume(
|
||||
config.rabbit.queues.acks.into(),
|
||||
"crond-ack-consumer".into(),
|
||||
BasicConsumeOptions::default(),
|
||||
FieldTable::default(),
|
||||
)
|
||||
.await
|
||||
.expect("Failed to create consumer");
|
||||
|
||||
while let Some(delivery) = consumer.next().await {
|
||||
if let Ok(delivery) = delivery {
|
||||
let payload: std::result::Result<AckEventPayload, _> =
|
||||
serde_json::from_slice(&delivery.data);
|
||||
if let Ok(payload) = payload {
|
||||
info!("{:?}", payload);
|
||||
if let Err(e) = process_channel_ack(
|
||||
&db,
|
||||
payload.user_id,
|
||||
payload.channel_id.unwrap(),
|
||||
&mut redis,
|
||||
)
|
||||
.await
|
||||
{
|
||||
revolt_config::capture_error(&e);
|
||||
_ = delivery.reject(BasicRejectOptions { requeue: false }).await;
|
||||
} else {
|
||||
_ = delivery.ack(BasicAckOptions { multiple: false }).await;
|
||||
}
|
||||
} else {
|
||||
revolt_config::capture_message(
|
||||
format!("Failed to decode ack data: {:?}", delivery.data).as_str(),
|
||||
revolt_config::Level::Error,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[allow(clippy::disallowed_methods)]
|
||||
async fn process_channel_ack(
|
||||
db: &Database,
|
||||
user: String,
|
||||
channel: String,
|
||||
redis: &mut RedisConnection,
|
||||
) -> Result<()> {
|
||||
let message_id: Option<String> = redis
|
||||
.get_del(format!("acker:{user}+{channel}"))
|
||||
.await
|
||||
.to_internal_error()?;
|
||||
|
||||
if let Some(message_id) = message_id {
|
||||
// This will be uncommented eventually, but we need to sort out the transition to lapin first. For now we'll simply disable the badge update logic.
|
||||
// We also drop a db request as a bonus.
|
||||
|
||||
//let unread = db.fetch_unread(&user, &channel).await?;
|
||||
let _updated = db.acknowledge_message(&channel, &user, &message_id).await?;
|
||||
info!("Set new state for ack: {}:{}:{}", channel, user, message_id);
|
||||
|
||||
// if let (Some(before), Some(after)) = (unread, updated) {
|
||||
// let before_mentions = before.mentions.unwrap_or_default().len();
|
||||
// let after_mentions = after.mentions.unwrap_or_default().len();
|
||||
|
||||
// let mentions_acked = before_mentions - after_mentions;
|
||||
|
||||
// if mentions_acked > 0 {
|
||||
// if let Err(err) = amqp
|
||||
// .ack_message(user.to_string(), channel.to_string(), payload.message_id)
|
||||
// .await
|
||||
// {
|
||||
// revolt_config::capture_error(&err);
|
||||
// }
|
||||
// };
|
||||
// }
|
||||
|
||||
Ok(())
|
||||
} else {
|
||||
Err(message_id.to_internal_error().expect_err("no err"))
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user