mirror of
https://github.com/chatmail/core.git
synced 2026-04-27 02:16:29 +03:00
limit rate of webxdc updates (#3417)
* more flexible render_webxdc_status_update_object() * delay webxdc updates when ratelimit is reached * inject updates messages to the SMTP loop as needed this avoids starting several tasks and allows sending updates out after a restart of the app. * use mutex to prevent race conditions in status updates * check ratelimiter only before the sending loop; it won't change until messages are actually sent out * fix typo * prefer standard type declaration over turbofish syntax * use UNIQUE and ON CONFLICT for query smtp_status_updates * combine DELETE+SELECT to one atomic statement * as all operations on smtp_status_updates are now atomic, a mutex is no longer needed * test DELETE+RETURNING statement * simplify calls to can_send() * comment about ratelimit boolean in send_smtp_messages()
This commit is contained in:
24
src/smtp.rs
24
src/smtp.rs
@@ -496,14 +496,22 @@ async fn send_mdns(context: &Context, connection: &mut Smtp) -> Result<bool> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Tries to send all messages currently in `smtp` and `smtp_mdns` tables.
|
||||
/// Tries to send all messages currently in `smtp`, `smtp_status_updates` and `smtp_mdns` tables.
|
||||
///
|
||||
/// Logs and ignores SMTP errors to ensure that a single SMTP message constantly failing to be sent
|
||||
/// does not block other messages in the queue from being sent.
|
||||
///
|
||||
/// Returns true if sending was ratelimited, false otherwise. Errors are propagated to the caller.
|
||||
pub(crate) async fn send_smtp_messages(context: &Context, connection: &mut Smtp) -> Result<bool> {
|
||||
context.send_sync_msg().await?; // Add sync message to the end of the queue if needed.
|
||||
let mut ratelimited = if context.ratelimit.read().await.can_send() {
|
||||
// add status updates and sync messages to end of sending queue
|
||||
context.flush_status_updates().await?;
|
||||
context.send_sync_msg().await?;
|
||||
false
|
||||
} else {
|
||||
true
|
||||
};
|
||||
|
||||
let rowids = context
|
||||
.sql
|
||||
.query_map(
|
||||
@@ -526,9 +534,15 @@ pub(crate) async fn send_smtp_messages(context: &Context, connection: &mut Smtp)
|
||||
.context("failed to send message")?;
|
||||
}
|
||||
|
||||
let ratelimited = send_mdns(context, connection)
|
||||
.await
|
||||
.context("failed to send MDNs")?;
|
||||
// although by slow sending, ratelimit may have been expired meanwhile,
|
||||
// do not attempt to send MDNs if ratelimited happend before on status-updates/sync:
|
||||
// instead, let the caller recall this function so that more important status-updates/sync are sent out.
|
||||
if !ratelimited {
|
||||
ratelimited = send_mdns(context, connection)
|
||||
.await
|
||||
.context("failed to send MDNs")?;
|
||||
}
|
||||
|
||||
Ok(ratelimited)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user