Files
continuwuity/src/service/sending/data.rs
T

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

258 lines
6.9 KiB
Rust
Raw Normal View History

2024-11-16 23:13:27 +00:00
use std::{fmt::Debug, sync::Arc};
2024-05-27 03:17:20 +00:00
2024-12-14 21:58:01 -05:00
use conduwuit::{
Error, Result, at, utils,
utils::{ReadyExt, stream::TryIgnore},
2024-08-08 17:18:30 +00:00
};
use database::{Database, Deserialized, Map};
use futures::{Stream, StreamExt};
2026-04-07 12:17:35 -04:00
use ruma::{ServerName, UserId};
2022-10-08 13:02:52 +02:00
2024-04-23 16:00:39 -07:00
use super::{Destination, SendingEvent};
use crate::{Dep, globals};
2022-10-08 13:02:52 +02:00
2024-08-08 17:18:30 +00:00
pub(super) type OutgoingItem = (Key, SendingEvent, Destination);
pub(super) type SendingItem = (Key, SendingEvent);
pub(super) type QueueItem = (Key, SendingEvent);
pub(super) type Key = Vec<u8>;
2024-05-27 03:17:20 +00:00
pub struct Data {
2024-06-28 22:51:39 +00:00
servercurrentevent_data: Arc<Map>,
servernameevent_data: Arc<Map>,
servername_educount: Arc<Map>,
2024-07-17 01:00:57 +00:00
pub(super) db: Arc<Database>,
2024-07-18 06:37:47 +00:00
services: Services,
}
struct Services {
globals: Dep<globals::Service>,
2022-10-08 13:02:52 +02:00
}
2024-05-26 21:29:19 +00:00
2024-05-27 03:17:20 +00:00
impl Data {
2024-07-18 06:37:47 +00:00
pub(super) fn new(args: &crate::Args<'_>) -> Self {
let db = &args.db;
2024-05-27 03:17:20 +00:00
Self {
2024-06-28 22:51:39 +00:00
servercurrentevent_data: db["servercurrentevent_data"].clone(),
servernameevent_data: db["servernameevent_data"].clone(),
servername_educount: db["servername_educount"].clone(),
2024-07-18 06:37:47 +00:00
db: args.db.clone(),
services: Services {
globals: args.depend::<globals::Service>("globals"),
},
2024-05-27 03:17:20 +00:00
}
}
pub(super) fn delete_active_request(&self, key: &[u8]) {
self.servercurrentevent_data.remove(key);
}
2024-05-26 21:29:19 +00:00
2024-08-08 17:18:30 +00:00
pub(super) async fn delete_all_active_requests_for(&self, destination: &Destination) {
2024-05-26 21:29:19 +00:00
let prefix = destination.get_prefix();
2024-08-08 17:18:30 +00:00
self.servercurrentevent_data
.raw_keys_prefix(&prefix)
.ignore_err()
.ready_for_each(|key| self.servercurrentevent_data.remove(key))
.await;
2024-05-26 21:29:19 +00:00
}
2024-08-08 17:18:30 +00:00
pub(super) async fn delete_all_requests_for(&self, destination: &Destination) {
2024-05-26 21:29:19 +00:00
let prefix = destination.get_prefix();
2024-08-08 17:18:30 +00:00
self.servercurrentevent_data
.raw_keys_prefix(&prefix)
.ignore_err()
.ready_for_each(|key| self.servercurrentevent_data.remove(key))
.await;
2024-05-26 21:29:19 +00:00
self.servernameevent_data
2024-08-08 17:18:30 +00:00
.raw_keys_prefix(&prefix)
.ignore_err()
.ready_for_each(|key| self.servernameevent_data.remove(key))
.await;
2024-05-26 21:29:19 +00:00
}
2024-11-16 23:13:27 +00:00
pub(super) fn mark_as_active<'a, I>(&self, events: I)
where
I: Iterator<Item = &'a QueueItem>,
{
events
.filter(|(key, _)| !key.is_empty())
.for_each(|(key, val)| {
let val = if let SendingEvent::Edu(val) = &val { &**val } else { &[] };
2024-05-26 21:29:19 +00:00
2024-11-16 23:13:27 +00:00
self.servercurrentevent_data.insert(key, val);
self.servernameevent_data.remove(key);
});
2024-08-08 17:18:30 +00:00
}
#[inline]
pub fn active_requests(&self) -> impl Stream<Item = OutgoingItem> + Send + '_ {
self.servercurrentevent_data
.raw_stream()
.ignore_err()
.map(|(key, val)| {
let (dest, event) =
parse_servercurrentevent(key, val).expect("invalid servercurrentevent");
2024-08-08 17:18:30 +00:00
(key.to_vec(), event, dest)
})
}
#[inline]
pub fn active_requests_for(
&self,
destination: &Destination,
) -> impl Stream<Item = SendingItem> + Send + '_ + use<'_> {
2024-08-08 17:18:30 +00:00
let prefix = destination.get_prefix();
self.servercurrentevent_data
.raw_stream_from(&prefix)
2024-08-08 17:18:30 +00:00
.ignore_err()
.ready_take_while(move |(key, _)| key.starts_with(&prefix))
2024-08-08 17:18:30 +00:00
.map(|(key, val)| {
let (_, event) =
parse_servercurrentevent(key, val).expect("invalid servercurrentevent");
2024-08-08 17:18:30 +00:00
(key.to_vec(), event)
})
}
2024-11-16 23:13:27 +00:00
pub(super) fn queue_requests<'a, I>(&self, requests: I) -> Vec<Vec<u8>>
where
I: Iterator<Item = (&'a SendingEvent, &'a Destination)> + Clone + Debug + Send,
{
let keys: Vec<_> = requests
.clone()
.map(|(event, dest)| {
let mut key = dest.get_prefix();
if let SendingEvent::Pdu(value) = event {
key.extend(value.as_ref());
} else {
let count = self.services.globals.next_count().unwrap();
key.extend(&count.to_be_bytes());
}
key
})
.collect();
self.servernameevent_data.insert_batch(
keys.iter()
.map(Vec::as_slice)
.zip(requests.map(at!(0)))
.map(|(key, event)| {
let value = if let SendingEvent::Edu(value) = &event {
&**value
} else {
&[]
};
(key, value)
}),
);
2024-05-26 21:29:19 +00:00
2024-08-08 17:18:30 +00:00
keys
2024-05-26 21:29:19 +00:00
}
pub fn queued_requests(
&self,
destination: &Destination,
) -> impl Stream<Item = QueueItem> + Send + '_ + use<'_> {
2024-08-08 17:18:30 +00:00
let prefix = destination.get_prefix();
self.servernameevent_data
.raw_stream_from(&prefix)
2024-08-08 17:18:30 +00:00
.ignore_err()
.ready_take_while(move |(key, _)| key.starts_with(&prefix))
2024-08-08 17:18:30 +00:00
.map(|(key, val)| {
let (_, event) =
parse_servercurrentevent(key, val).expect("invalid servercurrentevent");
2024-05-26 21:29:19 +00:00
2024-08-08 17:18:30 +00:00
(key.to_vec(), event)
2024-05-26 21:29:19 +00:00
})
}
2024-08-08 17:18:30 +00:00
pub(super) fn set_latest_educount(&self, server_name: &ServerName, last_count: u64) {
2024-10-07 17:54:27 +00:00
self.servername_educount.raw_put(server_name, last_count);
2024-08-08 17:18:30 +00:00
}
pub async fn get_latest_educount(&self, server_name: &ServerName) -> u64 {
self.servername_educount
.get(server_name)
2024-08-08 17:18:30 +00:00
.await
.deserialized()
.unwrap_or(0)
}
2024-05-26 21:29:19 +00:00
}
2024-08-08 17:18:30 +00:00
fn parse_servercurrentevent(key: &[u8], value: &[u8]) -> Result<(Destination, SendingEvent)> {
2024-05-26 21:29:19 +00:00
// Appservices start with a plus
Ok::<_, Error>(if key.starts_with(b"+") {
let mut parts = key[1..].splitn(2, |&b| b == 0xFF);
let server = parts.next().expect("splitn always returns one element");
let event = parts
.next()
.ok_or_else(|| Error::bad_database("Invalid bytes in servercurrentpdus."))?;
let server = utils::string_from_bytes(server).map_err(|_| {
Error::bad_database("Invalid server bytes in server_currenttransaction")
})?;
2024-05-26 21:29:19 +00:00
(
Destination::Appservice(server),
if value.is_empty() {
2024-11-02 06:12:54 +00:00
SendingEvent::Pdu(event.into())
2024-05-26 21:29:19 +00:00
} else {
SendingEvent::Edu(value.into())
2024-05-26 21:29:19 +00:00
},
)
} else if key.starts_with(b"$") {
let mut parts = key[1..].splitn(3, |&b| b == 0xFF);
let user = parts.next().expect("splitn always returns one element");
2024-12-28 23:31:24 +00:00
let user_string = utils::str_from_bytes(user)
2024-05-26 21:29:19 +00:00
.map_err(|_| Error::bad_database("Invalid user string in servercurrentevent"))?;
let user_id = UserId::parse(user_string)
.map_err(|_| Error::bad_database("Invalid user id in servercurrentevent"))?;
2024-05-26 21:29:19 +00:00
let pushkey = parts
.next()
.ok_or_else(|| Error::bad_database("Invalid bytes in servercurrentpdus."))?;
let pushkey_string = utils::string_from_bytes(pushkey)
.map_err(|_| Error::bad_database("Invalid pushkey in servercurrentevent"))?;
let event = parts
.next()
.ok_or_else(|| Error::bad_database("Invalid bytes in servercurrentpdus."))?;
(
2026-04-13 17:31:52 -04:00
Destination::Push(user_id, pushkey_string),
2024-05-26 21:29:19 +00:00
if value.is_empty() {
2024-11-02 06:12:54 +00:00
SendingEvent::Pdu(event.into())
2024-05-26 21:29:19 +00:00
} else {
// I'm pretty sure this should never be called
SendingEvent::Edu(value.into())
2024-05-26 21:29:19 +00:00
},
)
} else {
let mut parts = key.splitn(2, |&b| b == 0xFF);
let server = parts.next().expect("splitn always returns one element");
let event = parts
.next()
.ok_or_else(|| Error::bad_database("Invalid bytes in servercurrentpdus."))?;
let server = utils::string_from_bytes(server).map_err(|_| {
Error::bad_database("Invalid server bytes in server_currenttransaction")
})?;
2024-05-26 21:29:19 +00:00
(
Destination::Federation(ServerName::parse(&server).map_err(|_| {
Error::bad_database("Invalid server string in server_currenttransaction")
})?),
2024-05-26 21:29:19 +00:00
if value.is_empty() {
2024-11-02 06:12:54 +00:00
SendingEvent::Pdu(event.into())
2024-05-26 21:29:19 +00:00
} else {
SendingEvent::Edu(value.into())
2024-05-26 21:29:19 +00:00
},
)
})
}