fix: increase cache size to hopefully deduplicate events (#865)

* fix: presence key was incorrect after other related update

Signed-off-by: IAmTomahawkx <iamtomahawkx@gmail.com>

* rust analyzer try not to be annoying challenge

Signed-off-by: IAmTomahawkx <iamtomahawkx@gmail.com>

* fix: increase seen events cache and reenable typing events when disabling overload events

Signed-off-by: IAmTomahawkx <iamtomahawkx@gmail.com>

* add canary publisher and ability to lower job count to not OOM

Signed-off-by: IAmTomahawkx <iamtomahawkx@gmail.com>

---------

Signed-off-by: IAmTomahawkx <iamtomahawkx@gmail.com>
This commit is contained in:
Tom
2026-07-21 18:28:16 -07:00
committed by GitHub
parent 3f393ea24b
commit 44c35bfb51
8 changed files with 109 additions and 28 deletions

View File

@@ -1,11 +1,14 @@
use std::{
collections::{HashMap, HashSet}, num::NonZeroUsize, sync::Arc, time::Duration
collections::{HashMap, HashSet},
num::NonZeroUsize,
sync::Arc,
time::Duration,
};
use tokio::sync::{Mutex, RwLock};
use lru::LruCache;
use lru_time_cache::{LruCache as LruTimeCache, TimedEntry};
use revolt_database::{Channel, Member, Server, User};
use tokio::sync::{Mutex, RwLock};
/// Enumeration representing some change in subscriptions
pub enum SubscriptionStateChange {
@@ -44,6 +47,16 @@ pub struct Cache {
pub seen_events: LruCache<String, ()>,
}
impl Cache {
fn with_events_size(user_id: Option<String>, seen_events_size: NonZeroUsize) -> Self {
Self {
user_id: user_id.unwrap_or(String::default()),
seen_events: LruCache::new(seen_events_size),
..Default::default()
}
}
}
impl Default for Cache {
fn default() -> Self {
Cache {
@@ -55,7 +68,7 @@ impl Default for Cache {
members: Default::default(),
servers: Default::default(),
seen_events: LruCache::new(NonZeroUsize::new(20).unwrap()),
seen_events: LruCache::new(NonZeroUsize::new(2048).unwrap()),
}
}
}
@@ -74,16 +87,13 @@ pub struct State {
impl State {
/// Create state from User
pub fn from(user: User, session_id: String) -> State {
pub fn from(user: User, session_id: String, cache_size: NonZeroUsize) -> State {
let mut subscribed = HashSet::new();
let private_topic = format!("{}!", user.id);
subscribed.insert(private_topic.clone());
subscribed.insert(user.id.clone());
let mut cache: Cache = Cache {
user_id: user.id.clone(),
..Default::default()
};
let mut cache: Cache = Cache::with_events_size(Some(user.id.clone()), cache_size);
cache.users.insert(user.id.clone(), user);

View File

@@ -1,4 +1,4 @@
use std::{collections::HashSet, net::SocketAddr, sync::Arc};
use std::{collections::HashSet, net::SocketAddr, num::NonZeroUsize, sync::Arc};
use async_tungstenite::WebSocketStream;
use fred::{
@@ -21,21 +21,22 @@ use revolt_database::{
};
use revolt_presence::{create_session, delete_session};
use revolt_result::create_error;
use sentry::Level;
use tokio::{
net::TcpStream,
sync::{Mutex, RwLock},
task::spawn,
};
use tokio_util::compat::{TokioAsyncReadCompatExt, Compat};
use revolt_result::create_error;
use sentry::Level;
use tokio_util::compat::{Compat, TokioAsyncReadCompatExt};
use crate::config::{ProtocolConfiguration, WebsocketHandshakeCallback};
use crate::events::state::{State, SubscriptionStateChange};
use revolt_models::v0;
type WsReader = SplitStream<WebSocketStream<Compat<TcpStream>>>;
type WsWriter = SplitSink<WebSocketStream<Compat<TcpStream>>, async_tungstenite::tungstenite::Message>;
type WsWriter =
SplitSink<WebSocketStream<Compat<TcpStream>>, async_tungstenite::tungstenite::Message>;
/// Start a new WebSocket client worker given access to the database,
/// the relevant TCP stream and the remote address of the client.
@@ -106,8 +107,15 @@ pub async fn client(db: &'static Database, stream: TcpStream, addr: SocketAddr)
.await
.ok();
let backend_config = revolt_config::config().await;
// Create local state.
let mut state = State::from(user, session_id);
let mut state = State::from(
user,
session_id,
NonZeroUsize::new(backend_config.features.advanced.seen_events_cache_size as usize)
.expect("config.features.advanced.seen_events_cache_size cannot be 0!"),
);
let user_id = state.cache.user_id.clone();
// Notify socket we have authenticated.
@@ -440,8 +448,6 @@ async fn worker(
mut read: WsReader,
write: &Mutex<WsWriter>,
) {
let revolt_config = revolt_config::config().await;
loop {
let t1 = read.try_next().fuse();
let t2 = kill_signal_r.recv().fuse();
@@ -478,10 +484,6 @@ async fn worker(
match payload {
ClientMessage::BeginTyping { channel } => {
if revolt_config.disable_events_dont_use {
continue;
}
if !subscribed.read().await.contains(&channel) {
continue;
}
@@ -494,10 +496,6 @@ async fn worker(
.await;
}
ClientMessage::EndTyping { channel } => {
if revolt_config.disable_events_dont_use {
continue;
}
if !subscribed.read().await.contains(&channel) {
continue;
}

View File

@@ -333,6 +333,9 @@ emojis = 500_000
# The max amount of messages the rabbitmq provider/db mention adder job will delay for before forcing handling of a channel.
# default: 5
process_message_delay_limit = 5
# How many event ids to cache per bonfire connections.
# Higher numbers result in more deduplication but more ram usage.
seen_events_cache_size = 2048
[features.legal_links]
# URLs for legal documents

View File

@@ -429,12 +429,15 @@ pub struct LegalLinks {
pub struct FeaturesAdvanced {
#[serde(default)]
pub process_message_delay_limit: u16,
#[serde(default)]
pub seen_events_cache_size: u32,
}
impl Default for FeaturesAdvanced {
fn default() -> Self {
Self {
process_message_delay_limit: 5,
seen_events_cache_size: 20,
}
}
}