mirror of
https://forgejo.ellis.link/continuwuation/continuwuity.git
synced 2025-09-11 12:53:00 +02:00
fix(relations): Fix duplicate messages in thread pagination
The /relations endpoint incorrectly handled pagination tokens, causing duplicate messages when scrolling through threads. This was due to: 1. Incorrectly modifying the 'from' parameter with saturating_inc() 2. Not excluding the 'from' event from results Changed pagination to use ShortEventId directly as the next_batch token instead of complex PduCount handling. This provides more reliable pagination that handles federation edge cases. The fix ensures proper event ordering and prevents duplicates by: - Using ShortEventId (u64) directly in pagination tokens - Properly filtering events based on direction - Excluding the starting event from results
This commit is contained in:
parent
7a3493d1ac
commit
39671718ac
2 changed files with 19 additions and 9 deletions
|
@ -109,13 +109,13 @@ async fn paginate_relations_with_filter(
|
|||
recurse: bool,
|
||||
dir: Direction,
|
||||
) -> Result<get_relating_events::v1::Response> {
|
||||
let start: PduCount = from
|
||||
.map(str::parse)
|
||||
.transpose()?
|
||||
.unwrap_or_else(|| match dir {
|
||||
let start: PduCount = from.and_then(|s| s.parse::<u64>().ok()).map_or_else(
|
||||
|| match dir {
|
||||
| Direction::Forward => PduCount::min(),
|
||||
| Direction::Backward => PduCount::max(),
|
||||
});
|
||||
},
|
||||
PduCount::Normal,
|
||||
);
|
||||
|
||||
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::Backward => events.first(),
|
||||
}
|
||||
.map(at!(0))
|
||||
.as_ref()
|
||||
.map(ToString::to_string);
|
||||
.map(|(count, _)| count.into_unsigned().to_string());
|
||||
|
||||
Ok(get_relating_events::v1::Response {
|
||||
next_batch,
|
||||
|
|
|
@ -61,9 +61,10 @@ impl Data {
|
|||
from: PduCount,
|
||||
dir: Direction,
|
||||
) -> impl Stream<Item = (PduCount, impl Event)> + Send + '_ {
|
||||
let from_unsigned = from.into_unsigned();
|
||||
let mut current = ArrayVec::<u8, 16>::new();
|
||||
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();
|
||||
match dir {
|
||||
| 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()))
|
||||
.map(|to_from| u64_from_u8(&to_from[8..16]))
|
||||
.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 {
|
||||
let pdu_id: RawPduId = PduId { shortroomid, shorteventid }.into();
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue