diff --git a/src/api.rs b/src/api.rs index 8295a8b..2f623ff 100644 --- a/src/api.rs +++ b/src/api.rs @@ -165,8 +165,8 @@ fn items_sync(db: DbConn, u: user::User, params: Json) -> Custom) -> Custom = None; - let mut max_id: Option = None; + let mut had_cursor = false; if let Some(cursor_token) = inner_params.cursor_token { // If the client provides cursor_token, // then, we return all records // until sync_token (the head of the last sync) from_id = cursor_token.parse().ok(); - max_id = inner_params.sync_token.clone() - .and_then(|i| i.parse().ok()); - } else if let Some(sync_token) = inner_params.sync_token { + had_cursor = true; + } else if let Some(sync_token) = inner_params.sync_token.clone() { // If there is no cursor_token, then we are doing // a normal sync, so just return all records from sync_token from_id = sync_token.parse().ok(); @@ -206,7 +205,7 @@ fn items_sync(db: DbConn, u: user::User, params: Json) -> Custom { @@ -214,15 +213,33 @@ fn items_sync(db: DbConn, u: user::User, params: Json) -> Custom { if !items.is_empty() { - // max_id = the last sync token - // if we still haven't reached the last sync token yet, - // return a new cursor token and keep the sync token - if let Some(max_id) = max_id { - resp.cursor_token = Some(items[0].id.to_string()); - resp.sync_token = Some(max_id.to_string()); + // If we fetched something + // we should record the current last id to *some* token + // this may be `cursor_token` or `sync_token` + // if we have more to fetch, we set `cursor_token` to this id + // so that the client knows to continue + // and we set `sync_token` to this id regardless, for the + // client to remember where we were even if + // it doesn't need to continue + let next_from = items.last().unwrap().id; + if let Some(limit) = inner_params.limit { + if items.len() as i64 == limit { + // We may still have something to fetch + resp.cursor_token = Some(next_from.to_string()); + } + } + + // Always set sync_token to equal cursor_token in this case + resp.sync_token = Some(next_from.to_string()); + } else { + if had_cursor { + // If we already have no item to give, but the client still holds a cursor + // Revoke that cursor, and make it the sync_token + resp.sync_token = resp.cursor_token.clone(); + resp.cursor_token = None; } else { - // Else, use the current max id as the sync_token - resp.sync_token = Some(items[0].id.to_string()); + // Pass the same sync_token back + resp.sync_token = inner_params.sync_token.clone(); } } resp.retrieved_items = items.into_iter().map(|x| x.into()).collect(); diff --git a/src/item.rs b/src/item.rs index 69d5e20..2d8fe99 100644 --- a/src/item.rs +++ b/src/item.rs @@ -95,7 +95,7 @@ impl SyncItem { stmt = stmt.filter(id.le(max_id)); } - stmt.order(id.desc()) + stmt.order(id.asc()) .load::(db) .map_err(|_| "Database error".into()) })