Fix sockets causing actix hangs (#3089)
* Fix sockets causing actix hangs * Fix fmt issues * Retry failed S3 uploads * Ignore launcher socket from sentry
This commit is contained in:
parent
24765db045
commit
2fea772ffb
@ -74,10 +74,10 @@ impl FileHost for S3Host {
|
|||||||
content_type,
|
content_type,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
.map_err(|_| {
|
.map_err(|err| {
|
||||||
FileHostingError::S3Error(
|
FileHostingError::S3Error(format!(
|
||||||
"Error while uploading file to S3".to_string(),
|
"Error while uploading file {file_name} to S3: {err}"
|
||||||
)
|
))
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
Ok(UploadFileData {
|
Ok(UploadFileData {
|
||||||
@ -100,10 +100,10 @@ impl FileHost for S3Host {
|
|||||||
self.bucket
|
self.bucket
|
||||||
.delete_object(format!("/{file_name}"))
|
.delete_object(format!("/{file_name}"))
|
||||||
.await
|
.await
|
||||||
.map_err(|_| {
|
.map_err(|err| {
|
||||||
FileHostingError::S3Error(
|
FileHostingError::S3Error(format!(
|
||||||
"Error while deleting file from S3".to_string(),
|
"Error while deleting file {file_name} to S3: {err}"
|
||||||
)
|
))
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
Ok(DeleteFileData {
|
Ok(DeleteFileData {
|
||||||
|
|||||||
@ -92,6 +92,7 @@ async fn main() -> std::io::Result<()> {
|
|||||||
|
|
||||||
let prometheus = PrometheusMetricsBuilder::new("labrinth")
|
let prometheus = PrometheusMetricsBuilder::new("labrinth")
|
||||||
.endpoint("/metrics")
|
.endpoint("/metrics")
|
||||||
|
.exclude("/_internal/launcher_socket")
|
||||||
.build()
|
.build()
|
||||||
.expect("Failed to create prometheus metrics middleware");
|
.expect("Failed to create prometheus metrics middleware");
|
||||||
|
|
||||||
|
|||||||
@ -10,9 +10,9 @@ use crate::queue::socket::ActiveSockets;
|
|||||||
use crate::routes::ApiError;
|
use crate::routes::ApiError;
|
||||||
use actix_web::web::{Data, Payload};
|
use actix_web::web::{Data, Payload};
|
||||||
use actix_web::{get, web, HttpRequest, HttpResponse};
|
use actix_web::{get, web, HttpRequest, HttpResponse};
|
||||||
use actix_ws::AggregatedMessage;
|
use actix_ws::Message;
|
||||||
use chrono::Utc;
|
use chrono::Utc;
|
||||||
use futures_util::StreamExt;
|
use futures_util::{StreamExt, TryStreamExt};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use sqlx::PgPool;
|
use sqlx::PgPool;
|
||||||
|
|
||||||
@ -128,13 +128,13 @@ pub async fn ws_init(
|
|||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let mut stream = msg_stream.aggregate_continuations();
|
let mut stream = msg_stream.into_stream();
|
||||||
|
|
||||||
actix_web::rt::spawn(async move {
|
actix_web::rt::spawn(async move {
|
||||||
// receive messages from websocket
|
// receive messages from websocket
|
||||||
while let Some(msg) = stream.next().await {
|
while let Some(msg) = stream.next().await {
|
||||||
match msg {
|
match msg {
|
||||||
Ok(AggregatedMessage::Text(text)) => {
|
Ok(Message::Text(text)) => {
|
||||||
if let Ok(message) =
|
if let Ok(message) =
|
||||||
serde_json::from_str::<ClientToServerMessage>(&text)
|
serde_json::from_str::<ClientToServerMessage>(&text)
|
||||||
{
|
{
|
||||||
@ -159,10 +159,14 @@ pub async fn ws_init(
|
|||||||
status.profile_name = profile_name;
|
status.profile_name = profile_name;
|
||||||
status.last_update = Utc::now();
|
status.last_update = Utc::now();
|
||||||
|
|
||||||
|
let user_status = status.clone();
|
||||||
|
// We drop the pair to avoid holding the lock for too long
|
||||||
|
drop(pair);
|
||||||
|
|
||||||
let _ = broadcast_friends(
|
let _ = broadcast_friends(
|
||||||
user.id,
|
user.id,
|
||||||
ServerToClientMessage::StatusUpdate {
|
ServerToClientMessage::StatusUpdate {
|
||||||
status: status.clone(),
|
status: user_status,
|
||||||
},
|
},
|
||||||
&pool,
|
&pool,
|
||||||
&db,
|
&db,
|
||||||
@ -175,15 +179,14 @@ pub async fn ws_init(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(AggregatedMessage::Close(_)) => {
|
Ok(Message::Close(_)) => {
|
||||||
let _ = close_socket(user.id, &pool, &db).await;
|
let _ = close_socket(user.id, &pool, &db).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(AggregatedMessage::Ping(msg)) => {
|
Ok(Message::Ping(msg)) => {
|
||||||
if let Some(mut socket) = db.auth_sockets.get_mut(&user.id)
|
if let Some(socket) = db.auth_sockets.get(&user.id) {
|
||||||
{
|
let (_, socket) = socket.value();
|
||||||
let (_, socket) = socket.value_mut();
|
let _ = socket.clone().pong(&msg).await;
|
||||||
let _ = socket.pong(&msg).await;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -218,12 +221,11 @@ pub async fn broadcast_friends(
|
|||||||
};
|
};
|
||||||
|
|
||||||
if friend.accepted {
|
if friend.accepted {
|
||||||
if let Some(mut socket) =
|
if let Some(socket) = sockets.auth_sockets.get(&friend_id.into()) {
|
||||||
sockets.auth_sockets.get_mut(&friend_id.into())
|
let (_, socket) = socket.value();
|
||||||
{
|
|
||||||
let (_, socket) = socket.value_mut();
|
|
||||||
|
|
||||||
let _ = socket.text(serde_json::to_string(&message)?).await;
|
let _ =
|
||||||
|
socket.clone().text(serde_json::to_string(&message)?).await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -78,12 +78,13 @@ pub async fn add_friend(
|
|||||||
) -> Result<(), ApiError> {
|
) -> Result<(), ApiError> {
|
||||||
if let Some(pair) = sockets.auth_sockets.get(&user_id.into()) {
|
if let Some(pair) = sockets.auth_sockets.get(&user_id.into()) {
|
||||||
let (friend_status, _) = pair.value();
|
let (friend_status, _) = pair.value();
|
||||||
if let Some(mut socket) =
|
if let Some(socket) =
|
||||||
sockets.auth_sockets.get_mut(&friend_id.into())
|
sockets.auth_sockets.get(&friend_id.into())
|
||||||
{
|
{
|
||||||
let (_, socket) = socket.value_mut();
|
let (_, socket) = socket.value();
|
||||||
|
|
||||||
let _ = socket
|
let _ = socket
|
||||||
|
.clone()
|
||||||
.text(serde_json::to_string(
|
.text(serde_json::to_string(
|
||||||
&ServerToClientMessage::StatusUpdate {
|
&ServerToClientMessage::StatusUpdate {
|
||||||
status: friend_status.clone(),
|
status: friend_status.clone(),
|
||||||
@ -120,11 +121,11 @@ pub async fn add_friend(
|
|||||||
.insert(&mut transaction)
|
.insert(&mut transaction)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
if let Some(mut socket) = db.auth_sockets.get_mut(&friend.id.into())
|
if let Some(socket) = db.auth_sockets.get(&friend.id.into()) {
|
||||||
{
|
let (_, socket) = socket.value();
|
||||||
let (_, socket) = socket.value_mut();
|
|
||||||
|
|
||||||
if socket
|
if socket
|
||||||
|
.clone()
|
||||||
.text(serde_json::to_string(
|
.text(serde_json::to_string(
|
||||||
&ServerToClientMessage::FriendRequest { from: user.id },
|
&ServerToClientMessage::FriendRequest { from: user.id },
|
||||||
)?)
|
)?)
|
||||||
@ -177,10 +178,11 @@ pub async fn remove_friend(
|
|||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
if let Some(mut socket) = db.auth_sockets.get_mut(&friend.id.into()) {
|
if let Some(socket) = db.auth_sockets.get(&friend.id.into()) {
|
||||||
let (_, socket) = socket.value_mut();
|
let (_, socket) = socket.value();
|
||||||
|
|
||||||
let _ = socket
|
let _ = socket
|
||||||
|
.clone()
|
||||||
.text(serde_json::to_string(
|
.text(serde_json::to_string(
|
||||||
&ServerToClientMessage::FriendRequestRejected {
|
&ServerToClientMessage::FriendRequestRejected {
|
||||||
from: user.id,
|
from: user.id,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user