feat(bonfire): don't fan out UserUpdate (server) by default

This commit is contained in:
Paul Makles
2024-06-19 18:24:51 +01:00
parent ba411fef43
commit 36ecb48c7b
7 changed files with 237 additions and 94 deletions

View File

@@ -92,6 +92,7 @@ impl State {
/// Generate a Ready packet for the current user
pub async fn generate_ready_payload(&mut self, db: &Database) -> Result<EventV1> {
let user = self.clone_user();
self.cache.is_bot = user.bot.is_some();
// Find all relationships to the user.
let mut user_ids: HashSet<String> = user
@@ -191,6 +192,10 @@ impl State {
for server in &servers {
self.insert_subscription(server.id.clone()).await;
if self.cache.is_bot {
self.insert_subscription(format!("{}u", server.id)).await;
}
}
for channel in &channels {
@@ -397,6 +402,11 @@ impl State {
emojis: _,
} => {
self.insert_subscription(id.clone()).await;
if self.cache.is_bot {
self.insert_subscription(format!("{}u", id)).await;
}
self.cache.servers.insert(id.clone(), server.clone().into());
let member = Member {
id: MemberCompositeKey {

View File

@@ -1,10 +1,12 @@
use std::{
collections::{HashMap, HashSet},
sync::Arc,
time::Duration,
};
use async_std::sync::RwLock;
use async_std::sync::{Mutex, RwLock};
use lru::LruCache;
use lru_time_cache::{LruCache as LruTimeCache, TimedEntry};
use revolt_database::{Channel, Member, Server, User};
/// Enumeration representing some change in subscriptions
@@ -34,6 +36,7 @@ pub enum SubscriptionStateChange {
#[derive(Debug)]
pub struct Cache {
pub user_id: String,
pub is_bot: bool,
pub users: HashMap<String, User>,
pub channels: HashMap<String, Channel>,
@@ -47,6 +50,7 @@ impl Default for Cache {
fn default() -> Self {
Cache {
user_id: Default::default(),
is_bot: false,
users: Default::default(),
channels: Default::default(),
@@ -65,7 +69,9 @@ pub struct State {
pub session_id: String,
pub private_topic: String,
pub state: SubscriptionStateChange,
pub subscribed: Arc<RwLock<HashSet<String>>>,
pub active_servers: Arc<Mutex<LruTimeCache<String, ()>>>,
}
impl State {
@@ -86,6 +92,10 @@ impl State {
State {
cache,
subscribed: Arc::new(RwLock::new(subscribed)),
active_servers: Arc::new(Mutex::new(LruTimeCache::with_expiry_duration_and_capacity(
Duration::from_secs(900),
5,
))),
session_id,
private_topic,
state: SubscriptionStateChange::Reset,
@@ -94,6 +104,39 @@ impl State {
/// Apply currently queued state
pub async fn apply_state(&mut self) -> SubscriptionStateChange {
// Check if we need to change subscriptions to member event topics
if !self.cache.is_bot {
enum Server {
Subscribe(String),
Unsubscribe(String),
}
let active_server_changes: Vec<Server> = {
let mut active_servers = self.active_servers.lock().await;
active_servers
.notify_iter()
.map(|e| match e {
TimedEntry::Valid(k, _) => Server::Subscribe(format!("{}u", k)),
TimedEntry::Expired(k, _) => Server::Unsubscribe(format!("{}u", k)),
})
.collect()
// It is bad practice to open more than one Mutex at once and could
// lead to a deadlock, so instead we choose to collect the changes.
};
for entry in active_server_changes {
match entry {
Server::Subscribe(k) => {
self.insert_subscription(k).await;
}
Server::Unsubscribe(k) => {
self.remove_subscription(&k).await;
}
}
}
}
// Flush changes to subscriptions
let state = std::mem::replace(&mut self.state, SubscriptionStateChange::None);
let mut subscribed = self.subscribed.write().await;
if let SubscriptionStateChange::Change { add, remove } = &state {