mirror of
https://forgejo.ellis.link/continuwuation/continuwuity.git
synced 2025-09-11 23:53:01 +02:00
fix(relations): Fix duplicate messages in thread pagination
The /relations endpoint was incorrectly modifying the pagination starting point with from.saturating_inc(dir), causing duplicate events to appear when scrolling up in message threads. This was particularly noticeable when viewing replies in Element. The fix removes the incorrect increment/decrement logic and adds proper filtering to exclude the starting event itself from results. The endpoint now uses ShortEventId directly as the pagination token, avoiding issues with PduCount in federated environments where events can arrive out of order. Fixes: #814
This commit is contained in:
parent
bd3db65cb2
commit
5dbb5b015c
2 changed files with 19 additions and 9 deletions
|
@ -109,13 +109,13 @@ async fn paginate_relations_with_filter(
|
||||||
recurse: bool,
|
recurse: bool,
|
||||||
dir: Direction,
|
dir: Direction,
|
||||||
) -> Result<get_relating_events::v1::Response> {
|
) -> Result<get_relating_events::v1::Response> {
|
||||||
let start: PduCount = from
|
let start: PduCount = from.and_then(|s| s.parse::<u64>().ok()).map_or_else(
|
||||||
.map(str::parse)
|
|| match dir {
|
||||||
.transpose()?
|
|
||||||
.unwrap_or_else(|| match dir {
|
|
||||||
| Direction::Forward => PduCount::min(),
|
| Direction::Forward => PduCount::min(),
|
||||||
| Direction::Backward => PduCount::max(),
|
| Direction::Backward => PduCount::max(),
|
||||||
});
|
},
|
||||||
|
PduCount::Normal,
|
||||||
|
);
|
||||||
|
|
||||||
let to: Option<PduCount> = to.map(str::parse).flat_ok();
|
let to: Option<PduCount> = to.map(str::parse).flat_ok();
|
||||||
|
|
||||||
|
@ -156,9 +156,7 @@ async fn paginate_relations_with_filter(
|
||||||
| Direction::Forward => events.last(),
|
| Direction::Forward => events.last(),
|
||||||
| Direction::Backward => events.first(),
|
| Direction::Backward => events.first(),
|
||||||
}
|
}
|
||||||
.map(at!(0))
|
.map(|(count, _)| count.into_unsigned().to_string());
|
||||||
.as_ref()
|
|
||||||
.map(ToString::to_string);
|
|
||||||
|
|
||||||
Ok(get_relating_events::v1::Response {
|
Ok(get_relating_events::v1::Response {
|
||||||
next_batch,
|
next_batch,
|
||||||
|
|
|
@ -61,9 +61,10 @@ impl Data {
|
||||||
from: PduCount,
|
from: PduCount,
|
||||||
dir: Direction,
|
dir: Direction,
|
||||||
) -> impl Stream<Item = (PduCount, impl Event)> + Send + '_ {
|
) -> impl Stream<Item = (PduCount, impl Event)> + Send + '_ {
|
||||||
|
let from_unsigned = from.into_unsigned();
|
||||||
let mut current = ArrayVec::<u8, 16>::new();
|
let mut current = ArrayVec::<u8, 16>::new();
|
||||||
current.extend(target.to_be_bytes());
|
current.extend(target.to_be_bytes());
|
||||||
current.extend(from.saturating_inc(dir).into_unsigned().to_be_bytes());
|
current.extend(from_unsigned.to_be_bytes());
|
||||||
let current = current.as_slice();
|
let current = current.as_slice();
|
||||||
match dir {
|
match dir {
|
||||||
| Direction::Forward => self.tofrom_relation.raw_keys_from(current).boxed(),
|
| Direction::Forward => self.tofrom_relation.raw_keys_from(current).boxed(),
|
||||||
|
@ -73,6 +74,17 @@ impl Data {
|
||||||
.ready_take_while(move |key| key.starts_with(&target.to_be_bytes()))
|
.ready_take_while(move |key| key.starts_with(&target.to_be_bytes()))
|
||||||
.map(|to_from| u64_from_u8(&to_from[8..16]))
|
.map(|to_from| u64_from_u8(&to_from[8..16]))
|
||||||
.map(PduCount::from_unsigned)
|
.map(PduCount::from_unsigned)
|
||||||
|
.ready_filter(move |count| {
|
||||||
|
if from == PduCount::min() || from == PduCount::max() {
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
let count_unsigned = count.into_unsigned();
|
||||||
|
match dir {
|
||||||
|
| Direction::Forward => count_unsigned > from_unsigned,
|
||||||
|
| Direction::Backward => count_unsigned < from_unsigned,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
.wide_filter_map(move |shorteventid| async move {
|
.wide_filter_map(move |shorteventid| async move {
|
||||||
let pdu_id: RawPduId = PduId { shortroomid, shorteventid }.into();
|
let pdu_id: RawPduId = PduId { shortroomid, shorteventid }.into();
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue