Adjust federation send handler sans applying topological sort.
Signed-off-by: Jason Volk <jason@zemos.net>
This commit is contained in:
@@ -32,12 +32,13 @@ use tuwunel_core::{
|
|||||||
debug_warn, defer, err, error,
|
debug_warn, defer, err, error,
|
||||||
itertools::Itertools,
|
itertools::Itertools,
|
||||||
result::LogErr,
|
result::LogErr,
|
||||||
|
smallvec::SmallVec,
|
||||||
trace,
|
trace,
|
||||||
utils::{
|
utils::{
|
||||||
IterStream, ReadyExt,
|
|
||||||
debug::str_truncated,
|
debug::str_truncated,
|
||||||
|
future::TryExtExt,
|
||||||
millis_since_unix_epoch,
|
millis_since_unix_epoch,
|
||||||
stream::{BroadbandExt, TryBroadbandExt, automatic_width},
|
stream::{BroadbandExt, IterStream, ReadyExt, TryBroadbandExt, automatic_width},
|
||||||
},
|
},
|
||||||
warn,
|
warn,
|
||||||
};
|
};
|
||||||
@@ -49,6 +50,9 @@ use tuwunel_service::{
|
|||||||
use crate::Ruma;
|
use crate::Ruma;
|
||||||
|
|
||||||
type ResolvedMap = BTreeMap<OwnedEventId, Result>;
|
type ResolvedMap = BTreeMap<OwnedEventId, Result>;
|
||||||
|
type RoomsPdus = SmallVec<[RoomPdus; 1]>;
|
||||||
|
type RoomPdus = (OwnedRoomId, TxnPdus);
|
||||||
|
type TxnPdus = SmallVec<[(usize, Pdu); 1]>;
|
||||||
type Pdu = (OwnedRoomId, OwnedEventId, CanonicalJsonObject);
|
type Pdu = (OwnedRoomId, OwnedEventId, CanonicalJsonObject);
|
||||||
|
|
||||||
/// # `PUT /_matrix/federation/v1/send/{txnId}`
|
/// # `PUT /_matrix/federation/v1/send/{txnId}`
|
||||||
@@ -99,22 +103,27 @@ pub(crate) async fn send_transaction_message_route(
|
|||||||
.pdus
|
.pdus
|
||||||
.iter()
|
.iter()
|
||||||
.stream()
|
.stream()
|
||||||
.broad_then(|pdu| services.event_handler.parse_incoming_pdu(pdu))
|
.enumerate()
|
||||||
.inspect_err(|e| debug_warn!("Could not parse PDU: {e}"))
|
.broad_filter_map(|(i, pdu)| {
|
||||||
.ready_filter_map(Result::ok);
|
services
|
||||||
|
.event_handler
|
||||||
|
.parse_incoming_pdu(pdu)
|
||||||
|
.inspect_err(move |e| debug_warn!("Could not parse PDU[{i}]: {e}"))
|
||||||
|
.map_ok(move |pdu| (i, pdu))
|
||||||
|
.ok()
|
||||||
|
});
|
||||||
|
|
||||||
let edus = body
|
let edus = body
|
||||||
.edus
|
.edus
|
||||||
.iter()
|
.iter()
|
||||||
.map(|edu| edu.json().get())
|
.stream()
|
||||||
.map(serde_json::from_str)
|
.enumerate()
|
||||||
.filter_map(Result::ok)
|
.ready_filter_map(|(i, edu)| {
|
||||||
.stream();
|
serde_json::from_str(edu.json().get())
|
||||||
|
.inspect_err(|e| debug_warn!("Could not parse EDU[{i}]: {e}"))
|
||||||
trace!(
|
.map(|edu| (i, edu))
|
||||||
elapsed = ?txn_start_time.elapsed(),
|
.ok()
|
||||||
"Parsed txn",
|
});
|
||||||
);
|
|
||||||
|
|
||||||
let results = handle(
|
let results = handle(
|
||||||
&services,
|
&services,
|
||||||
@@ -156,8 +165,8 @@ async fn handle(
|
|||||||
origin: &ServerName,
|
origin: &ServerName,
|
||||||
txn_id: &TransactionId,
|
txn_id: &TransactionId,
|
||||||
started: Instant,
|
started: Instant,
|
||||||
pdus: impl Stream<Item = Pdu> + Send,
|
pdus: impl Stream<Item = (usize, Pdu)> + Send,
|
||||||
edus: impl Stream<Item = Edu> + Send,
|
edus: impl Stream<Item = (usize, Edu)> + Send,
|
||||||
) -> Result<ResolvedMap> {
|
) -> Result<ResolvedMap> {
|
||||||
let results = handle_pdus(services, client, origin, txn_id, started, pdus).await?;
|
let results = handle_pdus(services, client, origin, txn_id, started, pdus).await?;
|
||||||
|
|
||||||
@@ -172,25 +181,24 @@ async fn handle_pdus(
|
|||||||
origin: &ServerName,
|
origin: &ServerName,
|
||||||
txn_id: &TransactionId,
|
txn_id: &TransactionId,
|
||||||
started: Instant,
|
started: Instant,
|
||||||
pdus: impl Stream<Item = Pdu> + Send,
|
pdus: impl Stream<Item = (usize, Pdu)> + Send,
|
||||||
) -> Result<ResolvedMap> {
|
) -> Result<ResolvedMap> {
|
||||||
// group pdus by room
|
pdus.collect()
|
||||||
let pdus = pdus
|
.map(Ok)
|
||||||
.enumerate()
|
.map_ok(|pdus: TxnPdus| {
|
||||||
.collect()
|
|
||||||
.map(|mut pdus: Vec<_>| {
|
|
||||||
pdus.sort_by(|(_, (room_a, ..)), (_, (room_b, ..))| room_a.cmp(room_b));
|
|
||||||
pdus.into_iter()
|
pdus.into_iter()
|
||||||
|
.sorted_by(|(_, (room_a, ..)), (_, (room_b, ..))| room_a.cmp(room_b))
|
||||||
.into_grouping_map_by(|(_, (room_id, ..))| room_id.clone())
|
.into_grouping_map_by(|(_, (room_id, ..))| room_id.clone())
|
||||||
.collect()
|
.collect()
|
||||||
|
.into_iter()
|
||||||
|
.try_stream()
|
||||||
})
|
})
|
||||||
.await;
|
.try_flatten_stream()
|
||||||
|
.try_collect::<RoomsPdus>()
|
||||||
// we can evaluate rooms concurrently
|
.map_ok(IntoIterator::into_iter)
|
||||||
let results: ResolvedMap = pdus
|
.map_ok(IterStream::try_stream)
|
||||||
.into_iter()
|
.try_flatten_stream()
|
||||||
.try_stream()
|
.broad_and_then(async |(room_id, pdus)| {
|
||||||
.broad_and_then(async |(room_id, pdus): (_, Vec<_>)| {
|
|
||||||
handle_room(services, client, origin, txn_id, started, room_id, pdus.into_iter())
|
handle_room(services, client, origin, txn_id, started, room_id, pdus.into_iter())
|
||||||
.map_ok(ResolvedMap::into_iter)
|
.map_ok(ResolvedMap::into_iter)
|
||||||
.map_ok(IterStream::try_stream)
|
.map_ok(IterStream::try_stream)
|
||||||
@@ -198,9 +206,7 @@ async fn handle_pdus(
|
|||||||
})
|
})
|
||||||
.try_flatten()
|
.try_flatten()
|
||||||
.try_collect()
|
.try_collect()
|
||||||
.await?;
|
.await
|
||||||
|
|
||||||
Ok(results)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tracing::instrument(
|
#[tracing::instrument(
|
||||||
@@ -218,24 +224,24 @@ async fn handle_room(
|
|||||||
ref room_id: OwnedRoomId,
|
ref room_id: OwnedRoomId,
|
||||||
pdus: impl Iterator<Item = (usize, Pdu)> + Send,
|
pdus: impl Iterator<Item = (usize, Pdu)> + Send,
|
||||||
) -> Result<ResolvedMap> {
|
) -> Result<ResolvedMap> {
|
||||||
let _room_lock = services
|
services
|
||||||
.event_handler
|
.event_handler
|
||||||
.mutex_federation
|
.mutex_federation
|
||||||
.lock(room_id)
|
.lock(room_id)
|
||||||
.await;
|
.then(async |_lock| {
|
||||||
|
pdus.enumerate()
|
||||||
pdus.enumerate()
|
.try_stream()
|
||||||
.try_stream()
|
.and_then(async |pdu| {
|
||||||
.and_then(|(ri, (ti, (room_id, event_id, value)))| {
|
services.server.check_running().map(|()| pdu) // interruption point
|
||||||
handle_pdu(
|
})
|
||||||
services,
|
.and_then(|(ri, (ti, (room_id, event_id, value)))| {
|
||||||
(origin, txn_id, txn_start_time, ti),
|
let meta = (origin, txn_id, txn_start_time, ti);
|
||||||
(room_id, event_id, ri),
|
let pdu = (ri, (room_id, event_id, value));
|
||||||
value,
|
handle_pdu(services, meta, pdu).map(Ok)
|
||||||
)
|
})
|
||||||
|
.try_collect()
|
||||||
|
.await
|
||||||
})
|
})
|
||||||
.try_collect()
|
|
||||||
.boxed()
|
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -248,11 +254,8 @@ async fn handle_room(
|
|||||||
async fn handle_pdu(
|
async fn handle_pdu(
|
||||||
services: &Services,
|
services: &Services,
|
||||||
(origin, txn_id, txn_start_time, ti): (&ServerName, &TransactionId, Instant, usize),
|
(origin, txn_id, txn_start_time, ti): (&ServerName, &TransactionId, Instant, usize),
|
||||||
(ref room_id, event_id, ri): (OwnedRoomId, OwnedEventId, usize),
|
(ri, (ref room_id, event_id, value)): (usize, Pdu),
|
||||||
value: CanonicalJsonObject,
|
) -> (OwnedEventId, Result) {
|
||||||
) -> Result<(OwnedEventId, Result)> {
|
|
||||||
services.server.check_running()?;
|
|
||||||
|
|
||||||
let pdu_start_time = Instant::now();
|
let pdu_start_time = Instant::now();
|
||||||
let completed: AtomicBool = Default::default();
|
let completed: AtomicBool = Default::default();
|
||||||
defer! {{
|
defer! {{
|
||||||
@@ -279,6 +282,7 @@ async fn handle_pdu(
|
|||||||
.event_handler
|
.event_handler
|
||||||
.handle_incoming_pdu(origin, room_id, &event_id, value, true)
|
.handle_incoming_pdu(origin, room_id, &event_id, value, true)
|
||||||
.map_ok(|_| ())
|
.map_ok(|_| ())
|
||||||
|
.boxed()
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
completed.store(true, Ordering::Release);
|
completed.store(true, Ordering::Release);
|
||||||
@@ -289,7 +293,7 @@ async fn handle_pdu(
|
|||||||
"Finished PDU",
|
"Finished PDU",
|
||||||
);
|
);
|
||||||
|
|
||||||
Ok((event_id.clone(), result))
|
(event_id.clone(), result)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tracing::instrument(name = "edus", level = "debug", skip_all)]
|
#[tracing::instrument(name = "edus", level = "debug", skip_all)]
|
||||||
@@ -298,13 +302,12 @@ async fn handle_edus(
|
|||||||
client: &IpAddr,
|
client: &IpAddr,
|
||||||
origin: &ServerName,
|
origin: &ServerName,
|
||||||
txn_id: &TransactionId,
|
txn_id: &TransactionId,
|
||||||
edus: impl Stream<Item = Edu> + Send,
|
edus: impl Stream<Item = (usize, Edu)> + Send,
|
||||||
) -> Result {
|
) -> Result {
|
||||||
edus.enumerate()
|
edus.for_each_concurrent(automatic_width(), |(i, edu)| {
|
||||||
.for_each_concurrent(automatic_width(), |(i, edu)| {
|
handle_edu(services, client, origin, txn_id, i, edu)
|
||||||
handle_edu(services, client, origin, txn_id, i, edu)
|
})
|
||||||
})
|
.await;
|
||||||
.await;
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user