sending.rs: factor out event handlers into separate functions

This allows for much nicer control flow, since they don't need to return
Result<OutgoingKind, (OutgoingKind, Error)>.
This commit is contained in:
Lambda 2024-05-22 20:34:47 +00:00
parent 5caafdec06
commit 13f79dfee1

View file

@ -627,12 +627,10 @@ impl Service {
} }
#[tracing::instrument(skip(events))] #[tracing::instrument(skip(events))]
async fn handle_events( async fn handle_appservice_event(
kind: OutgoingKind, id: &str,
events: Vec<SendingEventType>, events: Vec<SendingEventType>,
) -> HandlerResponse { ) -> Result<()> {
match &kind {
OutgoingKind::Appservice(id) => {
let mut pdu_jsons = Vec::new(); let mut pdu_jsons = Vec::new();
for event in &events { for event in &events {
@ -642,16 +640,11 @@ impl Service {
services() services()
.rooms .rooms
.timeline .timeline
.get_pdu_from_id(pdu_id) .get_pdu_from_id(pdu_id)?
.map_err(|e| (kind.clone(), e))?
.ok_or_else(|| { .ok_or_else(|| {
(
kind.clone(),
Error::bad_database( Error::bad_database(
"[Appservice] Event in \ "[Appservice] Event in \
servernameevent_data not \ servernameevent_data not found in db.",
found in db.",
),
) )
})? })?
.to_room_event(), .to_room_event(),
@ -663,27 +656,20 @@ impl Service {
} }
} }
let permit = let permit = services().sending.maximum_requests.acquire().await;
services().sending.maximum_requests.acquire().await;
let response = match appservice_server::send_request( appservice_server::send_request(
services() services().appservice.get_registration(id).await.ok_or_else(
.appservice || {
.get_registration(id)
.await
.ok_or_else(|| {
(
kind.clone(),
Error::bad_database( Error::bad_database(
"[Appservice] Could not load registration \ "[Appservice] Could not load registration from db.",
from db.",
),
) )
})?, },
)?,
appservice::event::push_events::v1::Request { appservice::event::push_events::v1::Request {
events: pdu_jsons, events: pdu_jsons,
txn_id: (&*general_purpose::URL_SAFE_NO_PAD.encode( txn_id: general_purpose::URL_SAFE_NO_PAD
calculate_hash( .encode(calculate_hash(
&events &events
.iter() .iter()
.map(|e| match e { .map(|e| match e {
@ -691,22 +677,23 @@ impl Service {
| SendingEventType::Pdu(b) => &**b, | SendingEventType::Pdu(b) => &**b,
}) })
.collect::<Vec<_>>(), .collect::<Vec<_>>(),
),
)) ))
.into(), .into(),
}, },
) )
.await .await?;
{
Ok(_) => Ok(kind.clone()),
Err(e) => Err((kind.clone(), e)),
};
drop(permit); drop(permit);
response Ok(())
} }
OutgoingKind::Push(userid, pushkey) => {
#[tracing::instrument(skip(events))]
async fn handle_push_event(
userid: &UserId,
pushkey: &str,
events: Vec<SendingEventType>,
) -> Result<()> {
let mut pdus = Vec::new(); let mut pdus = Vec::new();
for event in &events { for event in &events {
@ -716,16 +703,11 @@ impl Service {
services() services()
.rooms .rooms
.timeline .timeline
.get_pdu_from_id(pdu_id) .get_pdu_from_id(pdu_id)?
.map_err(|e| (kind.clone(), e))?
.ok_or_else(|| { .ok_or_else(|| {
(
kind.clone(),
Error::bad_database( Error::bad_database(
"[Push] Event in \ "[Push] Event in servernamevent_datas not \
servernamevent_datas not \
found in db.", found in db.",
),
) )
})?, })?,
); );
@ -740,9 +722,7 @@ impl Service {
// send push for them) // send push for them)
if let Some(unsigned) = &pdu.unsigned { if let Some(unsigned) = &pdu.unsigned {
if let Ok(unsigned) = if let Ok(unsigned) =
serde_json::from_str::<serde_json::Value>( serde_json::from_str::<serde_json::Value>(unsigned.get())
unsigned.get(),
)
{ {
if unsigned.get("redacted_because").is_some() { if unsigned.get("redacted_because").is_some() {
continue; continue;
@ -750,18 +730,7 @@ impl Service {
} }
} }
let Some(pusher) = services() let Some(pusher) = services().pusher.get_pusher(userid, pushkey)?
.pusher
.get_pusher(userid, pushkey)
.map_err(|e| {
(
OutgoingKind::Push(
userid.clone(),
pushkey.clone(),
),
e,
)
})?
else { else {
continue; continue;
}; };
@ -771,14 +740,11 @@ impl Service {
.get( .get(
None, None,
userid, userid,
GlobalAccountDataEventType::PushRules GlobalAccountDataEventType::PushRules.to_string().into(),
.to_string()
.into(),
) )
.unwrap_or_default() .unwrap_or_default()
.and_then(|event| { .and_then(|event| {
serde_json::from_str::<PushRulesEvent>(event.get()) serde_json::from_str::<PushRulesEvent>(event.get()).ok()
.ok()
}) })
.map_or_else( .map_or_else(
|| push::Ruleset::server_default(userid), || push::Ruleset::server_default(userid),
@ -788,32 +754,28 @@ impl Service {
let unread: UInt = services() let unread: UInt = services()
.rooms .rooms
.user .user
.notification_count(userid, &pdu.room_id) .notification_count(userid, &pdu.room_id)?
.map_err(|e| (kind.clone(), e))?
.try_into() .try_into()
.expect("notification count can't go that high"); .expect("notification count can't go that high");
let permit = let permit = services().sending.maximum_requests.acquire().await;
services().sending.maximum_requests.acquire().await;
let _response = services() services()
.pusher .pusher
.send_push_notice( .send_push_notice(userid, unread, &pusher, rules_for_user, &pdu)
userid, .await?;
unread,
&pusher,
rules_for_user,
&pdu,
)
.await
.map(|_response| kind.clone())
.map_err(|e| (kind.clone(), e));
drop(permit); drop(permit);
} }
Ok(OutgoingKind::Push(userid.clone(), pushkey.clone()))
Ok(())
} }
OutgoingKind::Normal(server) => {
#[tracing::instrument(skip(events))]
async fn handle_federation_event(
server: &ServerName,
events: Vec<SendingEventType>,
) -> Result<()> {
let mut edu_jsons = Vec::new(); let mut edu_jsons = Vec::new();
let mut pdu_jsons = Vec::new(); let mut pdu_jsons = Vec::new();
@ -822,38 +784,23 @@ impl Service {
SendingEventType::Pdu(pdu_id) => { SendingEventType::Pdu(pdu_id) => {
// TODO: check room version and remove event_id if // TODO: check room version and remove event_id if
// needed // needed
let raw = pdu_jsons.push(
PduEvent::convert_to_outgoing_federation_event( PduEvent::convert_to_outgoing_federation_event(
services() services()
.rooms .rooms
.timeline .timeline
.get_pdu_json_from_id(pdu_id) .get_pdu_json_from_id(pdu_id)?
.map_err(|e| {
(
OutgoingKind::Normal(
server.clone(),
),
e,
)
})?
.ok_or_else(|| { .ok_or_else(|| {
error!( error!(
"event not found: {server} \ "event not found: {server} {pdu_id:?}"
{pdu_id:?}"
); );
(
OutgoingKind::Normal(
server.clone(),
),
Error::bad_database( Error::bad_database(
"[Normal] Event in \ "[Normal] Event in \
servernamevent_datas not \ servernamevent_datas not found in db.",
found in db.",
),
) )
})?, })?,
),
); );
pdu_jsons.push(raw);
} }
SendingEventType::Edu(edu) => { SendingEventType::Edu(edu) => {
if let Ok(raw) = serde_json::from_slice(edu) { if let Ok(raw) = serde_json::from_slice(edu) {
@ -863,8 +810,7 @@ impl Service {
} }
} }
let permit = let permit = services().sending.maximum_requests.acquire().await;
services().sending.maximum_requests.acquire().await;
let response = server_server::send_request( let response = server_server::send_request(
server, server,
@ -873,7 +819,7 @@ impl Service {
pdus: pdu_jsons, pdus: pdu_jsons,
edus: edu_jsons, edus: edu_jsons,
origin_server_ts: MilliSecondsSinceUnixEpoch::now(), origin_server_ts: MilliSecondsSinceUnixEpoch::now(),
transaction_id: (&*general_purpose::URL_SAFE_NO_PAD transaction_id: general_purpose::URL_SAFE_NO_PAD
.encode(calculate_hash( .encode(calculate_hash(
&events &events
.iter() .iter()
@ -882,25 +828,43 @@ impl Service {
| SendingEventType::Pdu(b) => &**b, | SendingEventType::Pdu(b) => &**b,
}) })
.collect::<Vec<_>>(), .collect::<Vec<_>>(),
))) ))
.into(), .into(),
}, },
) )
.await .await?;
.map(|response| {
for pdu in response.pdus { for pdu in response.pdus {
if pdu.1.is_err() { if pdu.1.is_err() {
warn!("Failed to send to {}: {:?}", server, pdu); warn!("Failed to send to {}: {:?}", server, pdu);
} }
} }
kind.clone()
})
.map_err(|e| (kind, e));
drop(permit); drop(permit);
response Ok(())
} }
#[tracing::instrument(skip_all)]
async fn handle_events(
kind: OutgoingKind,
events: Vec<SendingEventType>,
) -> HandlerResponse {
let ret = match &kind {
OutgoingKind::Appservice(id) => {
Self::handle_appservice_event(id, events).await
}
OutgoingKind::Push(userid, pushkey) => {
Self::handle_push_event(userid, pushkey, events).await
}
OutgoingKind::Normal(server) => {
Self::handle_federation_event(server, events).await
}
};
match ret {
Ok(()) => Ok(kind),
Err(e) => Err((kind, e)),
} }
} }