Skip to content

Commit 742b987

Browse files
committed
sdk-ui: fix max concurrent requests for pinned events timeline.
1 parent 1eecb2d commit 742b987

File tree

6 files changed

+149
-92
lines changed

6 files changed

+149
-92
lines changed

benchmarks/benches/room_bench.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,10 @@ pub fn load_pinned_events_benchmark(c: &mut Criterion) {
198198
client.event_cache().empty_immutable_cache().await;
199199

200200
let timeline = Timeline::builder(&room)
201-
.with_focus(TimelineFocus::PinnedEvents { max_events_to_load: 100 })
201+
.with_focus(TimelineFocus::PinnedEvents {
202+
max_events_to_load: 100,
203+
max_concurrent_requests: 10,
204+
})
202205
.build()
203206
.await
204207
.expect("Could not create timeline");

bindings/matrix-sdk-ffi/src/room.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,7 @@ impl Room {
233233
&self,
234234
internal_id_prefix: Option<String>,
235235
max_events_to_load: u16,
236+
max_concurrent_requests: u16,
236237
) -> Result<Arc<Timeline>, ClientError> {
237238
let room = &self.inner;
238239

@@ -242,8 +243,10 @@ impl Room {
242243
builder = builder.with_internal_id_prefix(internal_id_prefix);
243244
}
244245

245-
let timeline =
246-
builder.with_focus(TimelineFocus::PinnedEvents { max_events_to_load }).build().await?;
246+
let timeline = builder
247+
.with_focus(TimelineFocus::PinnedEvents { max_events_to_load, max_concurrent_requests })
248+
.build()
249+
.await?;
247250

248251
Ok(Timeline::new(timeline))
249252
}

crates/matrix-sdk-ui/src/timeline/controller/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -253,11 +253,12 @@ impl<P: RoomDataProvider> TimelineController<P> {
253253
)
254254
}
255255

256-
TimelineFocus::PinnedEvents { max_events_to_load } => (
256+
TimelineFocus::PinnedEvents { max_events_to_load, max_concurrent_requests } => (
257257
TimelineFocusData::PinnedEvents {
258258
loader: PinnedEventsLoader::new(
259259
Arc::new(room_data_provider.clone()),
260260
max_events_to_load as usize,
261+
max_concurrent_requests as usize,
261262
),
262263
},
263264
TimelineFocusKind::PinnedEvents,

crates/matrix-sdk-ui/src/timeline/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ pub enum TimelineFocus {
173173
Event { target: OwnedEventId, num_context_events: u16 },
174174

175175
/// Only show pinned events.
176-
PinnedEvents { max_events_to_load: u16 },
176+
PinnedEvents { max_events_to_load: u16, max_concurrent_requests: u16 },
177177
}
178178

179179
impl Timeline {

crates/matrix-sdk-ui/src/timeline/pinned_events_loader.rs

Lines changed: 36 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15-
use std::{fmt::Formatter, num::NonZeroUsize, sync::Arc};
15+
use std::{fmt::Formatter, sync::Arc};
1616

17-
use futures_util::{future::join_all, FutureExt as _};
17+
use futures_util::{stream, FutureExt as _, StreamExt};
1818
use matrix_sdk::{
1919
config::RequestConfig, event_cache::paginator::PaginatorError, BoxFuture, Room,
2020
SendOutsideWasm, SyncOutsideWasm,
@@ -24,8 +24,6 @@ use ruma::{EventId, MilliSecondsSinceUnixEpoch, OwnedEventId};
2424
use thiserror::Error;
2525
use tracing::{debug, warn};
2626

27-
const MAX_CONCURRENT_REQUESTS: usize = 10;
28-
2927
/// Utility to load the pinned events in a room.
3028
pub struct PinnedEventsLoader {
3129
/// Backend to load pinned events.
@@ -34,12 +32,21 @@ pub struct PinnedEventsLoader {
3432
/// Maximum number of pinned events to load (either from network or the
3533
/// cache).
3634
max_events_to_load: usize,
35+
36+
/// Number of requests to load pinned events that can run concurrently. This
37+
/// is used to avoid overwhelming a home server with dozens or hundreds
38+
/// of concurrent requests.
39+
max_concurrent_requests: usize,
3740
}
3841

3942
impl PinnedEventsLoader {
4043
/// Creates a new `PinnedEventsLoader` instance.
41-
pub fn new(room: Arc<dyn PinnedEventsRoom>, max_events_to_load: usize) -> Self {
42-
Self { room, max_events_to_load }
44+
pub fn new(
45+
room: Arc<dyn PinnedEventsRoom>,
46+
max_events_to_load: usize,
47+
max_concurrent_requests: usize,
48+
) -> Self {
49+
Self { room, max_events_to_load, max_concurrent_requests }
4350
}
4451

4552
/// Loads the pinned events in this room, using the cache first and then
@@ -64,37 +71,33 @@ impl PinnedEventsLoader {
6471
return Ok(Vec::new());
6572
}
6673

67-
let request_config = Some(
68-
RequestConfig::default()
69-
.retry_limit(3)
70-
.max_concurrent_requests(NonZeroUsize::new(MAX_CONCURRENT_REQUESTS)),
71-
);
72-
73-
let new_events = join_all(pinned_event_ids.into_iter().map(|event_id| {
74-
let provider = self.room.clone();
75-
async move {
76-
match provider.load_event_with_relations(&event_id, request_config).await {
77-
Ok((event, related_events)) => {
78-
let mut events = vec![event];
79-
events.extend(related_events);
80-
Some(events)
81-
}
82-
Err(err) => {
83-
warn!("error when loading pinned event: {err}");
84-
None
74+
let request_config = Some(RequestConfig::default().retry_limit(3));
75+
76+
let mut loaded_events: Vec<SyncTimelineEvent> =
77+
stream::iter(pinned_event_ids.into_iter().map(|event_id| {
78+
let provider = self.room.clone();
79+
async move {
80+
match provider.load_event_with_relations(&event_id, request_config).await {
81+
Ok((event, related_events)) => {
82+
let mut events = vec![event];
83+
events.extend(related_events);
84+
Some(events)
85+
}
86+
Err(err) => {
87+
warn!("error when loading pinned event: {err}");
88+
None
89+
}
8590
}
8691
}
87-
}
88-
}))
89-
.await;
90-
91-
let mut loaded_events = new_events
92-
.into_iter()
92+
}))
93+
.buffer_unordered(self.max_concurrent_requests)
9394
// Get only the `Some<Vec<_>>` results
94-
.flatten()
95+
.flat_map(stream::iter)
9596
// Flatten the `Vec`s into a single one containing all their items
96-
.flatten()
97-
.collect::<Vec<SyncTimelineEvent>>();
97+
.flat_map(stream::iter)
98+
.collect()
99+
.await;
100+
98101
if loaded_events.is_empty() {
99102
return Err(PinnedEventsLoaderError::TimelineReloadFailed);
100103
}

0 commit comments

Comments
 (0)