mirror of
https://github.com/spartanz51/tutabridge.git
synced 2026-06-24 10:54:32 +02:00
Paginate load_mail_ids_for_folder above the server's 1000-per-page cap
Replace the silent `min(limit, 1000)` cap with proper pagination: the server rejects a single `load_range` count > 1000, so for any user-facing `sync_limit` above that we now loop 1000-entry pages, advancing the cursor with the last (oldest in DESC) entry's element id, until we have the requested count or the list is exhausted. `limit == 0` still delegates to `load_all`, which already paginates the whole list. Honors what the user typed (1050 means 1050, not 1000).
This commit is contained in:
@@ -168,25 +168,52 @@ impl TutaSession {
|
|||||||
entries_list_id: &tutasdk::GeneratedId,
|
entries_list_id: &tutasdk::GeneratedId,
|
||||||
limit: usize,
|
limit: usize,
|
||||||
) -> Result<Vec<Mail>, ApiCallError> {
|
) -> Result<Vec<Mail>, ApiCallError> {
|
||||||
// limit == 0 means "all": paginate the whole entries list. Otherwise
|
// The server rejects a single `load_range` with `count` > 1000 (400
|
||||||
// load a single page (newest first), capped at the server-side max of
|
// Bad request). For higher user-facing `sync_limit` we page through
|
||||||
// 1000 per request. A higher user-facing `sync_limit` (e.g. 2000)
|
// by 1000 each call, advancing the cursor with the last entry id of
|
||||||
// would need multi-page stitching here; for now we honor the cap and
|
// the previous page (DESC = newest first, oldest at the end). The
|
||||||
// any excess is picked up by the realtime event bus.
|
// `limit == 0` path delegates to `load_all` which already paginates.
|
||||||
const SERVER_LOAD_RANGE_MAX: usize = 1000;
|
const SERVER_PAGE: usize = 1000;
|
||||||
let entries: Vec<MailSetEntry> = if limit == 0 {
|
let entries: Vec<MailSetEntry> = if limit == 0 {
|
||||||
self.crypto_client()
|
self.crypto_client()
|
||||||
.load_all(entries_list_id, ListLoadDirection::DESC)
|
.load_all(entries_list_id, ListLoadDirection::DESC)
|
||||||
.await?
|
.await?
|
||||||
} else {
|
} else if limit <= SERVER_PAGE {
|
||||||
self.crypto_client()
|
self.crypto_client()
|
||||||
.load_range(
|
.load_range(
|
||||||
entries_list_id,
|
entries_list_id,
|
||||||
&CustomId::default(),
|
&CustomId::default(),
|
||||||
limit.min(SERVER_LOAD_RANGE_MAX),
|
limit,
|
||||||
ListLoadDirection::DESC,
|
ListLoadDirection::DESC,
|
||||||
)
|
)
|
||||||
.await?
|
.await?
|
||||||
|
} else {
|
||||||
|
let mut out: Vec<MailSetEntry> = Vec::with_capacity(limit);
|
||||||
|
let mut start = CustomId::default();
|
||||||
|
while out.len() < limit {
|
||||||
|
let want = (limit - out.len()).min(SERVER_PAGE);
|
||||||
|
let page: Vec<MailSetEntry> = self
|
||||||
|
.crypto_client()
|
||||||
|
.load_range(entries_list_id, &start, want, ListLoadDirection::DESC)
|
||||||
|
.await?;
|
||||||
|
let got = page.len();
|
||||||
|
if got == 0 {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// Use the last (oldest in DESC) entry's element id as the
|
||||||
|
// exclusive cursor for the next page.
|
||||||
|
let next_start = page
|
||||||
|
.last()
|
||||||
|
.and_then(|e| e._id.as_ref())
|
||||||
|
.map(|id| id.element_id.clone());
|
||||||
|
out.extend(page);
|
||||||
|
if got < want {
|
||||||
|
break; // server has no more
|
||||||
|
}
|
||||||
|
let Some(ns) = next_start else { break };
|
||||||
|
start = ns;
|
||||||
|
}
|
||||||
|
out
|
||||||
};
|
};
|
||||||
|
|
||||||
// Group entries by list_id for batch loading
|
// Group entries by list_id for batch loading
|
||||||
|
|||||||
Reference in New Issue
Block a user