api: item/sync: fix cursor_token and sync_token logic
This commit is contained in:
parent
fd9b1310b0
commit
5d5e88fcef
47
src/api.rs
47
src/api.rs
|
@ -165,8 +165,8 @@ fn items_sync(db: DbConn, u: user::User, params: Json<SyncParams>) -> Custom<Jso
|
|||
retrieved_items: vec![],
|
||||
saved_items: vec![],
|
||||
unsaved: vec![],
|
||||
sync_token: params.sync_token.clone(),
|
||||
cursor_token: params.cursor_token.clone()
|
||||
sync_token: None,
|
||||
cursor_token: None
|
||||
};
|
||||
|
||||
let inner_params = params.into_inner();
|
||||
|
@ -189,16 +189,15 @@ fn items_sync(db: DbConn, u: user::User, params: Json<SyncParams>) -> Custom<Jso
|
|||
}
|
||||
|
||||
let mut from_id: Option<i64> = None;
|
||||
let mut max_id: Option<i64> = 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<SyncParams>) -> Custom<Jso
|
|||
|
||||
// Then, retrieve what the client needs
|
||||
let result = item::SyncItem::items_of_user(&db, &u,
|
||||
from_id, max_id, inner_params.limit);
|
||||
from_id, None, inner_params.limit);
|
||||
|
||||
match result {
|
||||
Err(item::ItemOpError(e)) => {
|
||||
|
@ -214,15 +213,33 @@ fn items_sync(db: DbConn, u: user::User, params: Json<SyncParams>) -> Custom<Jso
|
|||
},
|
||||
Ok(items) => {
|
||||
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();
|
||||
|
|
|
@ -95,7 +95,7 @@ impl SyncItem {
|
|||
stmt = stmt.filter(id.le(max_id));
|
||||
}
|
||||
|
||||
stmt.order(id.desc())
|
||||
stmt.order(id.asc())
|
||||
.load::<Item>(db)
|
||||
.map_err(|_| "Database error".into())
|
||||
})
|
||||
|
|
Loading…
Reference in New Issue