@@ -503,8 +503,7 @@ mod private {
503
503
} ,
504
504
linked_chunk:: {
505
505
lazy_loader:: { self } ,
506
- ChunkContent , ChunkIdentifier , ChunkIdentifierGenerator , ChunkMetadata , LinkedChunkId ,
507
- Position , Update ,
506
+ ChunkContent , ChunkIdentifierGenerator , ChunkMetadata , LinkedChunkId , Position , Update ,
508
507
} ,
509
508
serde_helpers:: extract_thread_root,
510
509
sync:: Timeline ,
@@ -1262,6 +1261,8 @@ mod private {
1262
1261
1263
1262
/// Post-process new events, after they have been added to the in-memory
1264
1263
/// linked chunk.
1264
+ ///
1265
+ /// Flushes updates to disk first.
1265
1266
async fn post_process_new_events (
1266
1267
& mut self ,
1267
1268
events : Vec < Event > ,
@@ -1568,13 +1569,43 @@ mod private {
1568
1569
Ok ( ( has_new_gap, timeline_event_diffs) )
1569
1570
}
1570
1571
1572
+ /// Handle the result of a single back-pagination request.
1573
+ ///
1574
+ /// If the `prev_token` is set, then this function will check that the
1575
+ /// corresponding gap is present in the in-memory linked chunk.
1576
+ /// If it's not the case, `Ok(None)` will be returned, and the
1577
+ /// caller may decide to do something based on that (e.g. restart a
1578
+ /// pagination).
1571
1579
#[ must_use = "Propagate `VectorDiff` updates via `RoomEventCacheUpdate`" ]
1572
1580
pub async fn handle_backpagination (
1573
1581
& mut self ,
1574
1582
events : Vec < Event > ,
1575
- mut new_gap : Option < Gap > ,
1576
- prev_gap_id : Option < ChunkIdentifier > ,
1577
- ) -> Result < ( BackPaginationOutcome , Vec < VectorDiff < Event > > ) , EventCacheError > {
1583
+ mut new_token : Option < String > ,
1584
+ prev_token : Option < String > ,
1585
+ ) -> Result < Option < ( BackPaginationOutcome , Vec < VectorDiff < Event > > ) > , EventCacheError >
1586
+ {
1587
+ // Check that the previous token still exists; otherwise it's a sign that the
1588
+ // room's timeline has been cleared.
1589
+ let prev_gap_id = if let Some ( token) = prev_token {
1590
+ // Find the corresponding gap in the in-memory linked chunk.
1591
+ let gap_chunk_id = self . room_linked_chunk . chunk_identifier ( |chunk| {
1592
+ matches ! ( chunk. content( ) , ChunkContent :: Gap ( Gap { ref prev_token } ) if * prev_token == token)
1593
+ } ) ;
1594
+
1595
+ if gap_chunk_id. is_none ( ) {
1596
+ // We got a previous-batch token from the linked chunk *before* running the
1597
+ // request, but it is missing *after* completing the request.
1598
+ //
1599
+ // It may be a sign the linked chunk has been reset, but it's fine, per this
1600
+ // function's contract.
1601
+ return Ok ( None ) ;
1602
+ }
1603
+
1604
+ gap_chunk_id
1605
+ } else {
1606
+ None
1607
+ } ;
1608
+
1578
1609
let DeduplicationOutcome {
1579
1610
all_events : mut events,
1580
1611
in_memory_duplicated_event_ids,
@@ -1610,25 +1641,26 @@ mod private {
1610
1641
events. clear ( ) ;
1611
1642
// The gap can be ditched too, as it won't be useful to backpaginate any
1612
1643
// further.
1613
- new_gap = None ;
1644
+ new_token = None ;
1614
1645
} ;
1615
1646
1616
1647
// `/messages` has been called with `dir=b` (backwards), so the events are in
1617
1648
// the inverted order; reorder them.
1618
1649
let topo_ordered_events = events. iter ( ) . rev ( ) . cloned ( ) . collect :: < Vec < _ > > ( ) ;
1619
1650
1651
+ let new_gap = new_token. map ( |prev_token| Gap { prev_token } ) ;
1620
1652
let reached_start = self . room_linked_chunk . finish_back_pagination (
1621
1653
prev_gap_id,
1622
1654
new_gap,
1623
1655
& topo_ordered_events,
1624
1656
) ;
1625
1657
1658
+ // Note: this flushes updates to the store.
1626
1659
self . post_process_new_events ( topo_ordered_events, false ) . await ?;
1627
1660
1628
1661
let event_diffs = self . room_linked_chunk . updates_as_vector_diffs ( ) ;
1629
- let backpagination_outcome = BackPaginationOutcome { events, reached_start } ;
1630
1662
1631
- Ok ( ( backpagination_outcome , event_diffs) )
1663
+ Ok ( Some ( ( BackPaginationOutcome { events , reached_start } , event_diffs) ) )
1632
1664
}
1633
1665
}
1634
1666
}
0 commit comments