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![],
|
retrieved_items: vec![],
|
||||||
saved_items: vec![],
|
saved_items: vec![],
|
||||||
unsaved: vec![],
|
unsaved: vec![],
|
||||||
sync_token: params.sync_token.clone(),
|
sync_token: None,
|
||||||
cursor_token: params.cursor_token.clone()
|
cursor_token: None
|
||||||
};
|
};
|
||||||
|
|
||||||
let inner_params = params.into_inner();
|
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 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 let Some(cursor_token) = inner_params.cursor_token {
|
||||||
// If the client provides cursor_token,
|
// If the client provides cursor_token,
|
||||||
// then, we return all records
|
// then, we return all records
|
||||||
// until sync_token (the head of the last sync)
|
// until sync_token (the head of the last sync)
|
||||||
from_id = cursor_token.parse().ok();
|
from_id = cursor_token.parse().ok();
|
||||||
max_id = inner_params.sync_token.clone()
|
had_cursor = true;
|
||||||
.and_then(|i| i.parse().ok());
|
} else if let Some(sync_token) = inner_params.sync_token.clone() {
|
||||||
} else if let Some(sync_token) = inner_params.sync_token {
|
|
||||||
// If there is no cursor_token, then we are doing
|
// If there is no cursor_token, then we are doing
|
||||||
// a normal sync, so just return all records from sync_token
|
// a normal sync, so just return all records from sync_token
|
||||||
from_id = sync_token.parse().ok();
|
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
|
// Then, retrieve what the client needs
|
||||||
let result = item::SyncItem::items_of_user(&db, &u,
|
let result = item::SyncItem::items_of_user(&db, &u,
|
||||||
from_id, max_id, inner_params.limit);
|
from_id, None, inner_params.limit);
|
||||||
|
|
||||||
match result {
|
match result {
|
||||||
Err(item::ItemOpError(e)) => {
|
Err(item::ItemOpError(e)) => {
|
||||||
|
@ -214,15 +213,33 @@ fn items_sync(db: DbConn, u: user::User, params: Json<SyncParams>) -> Custom<Jso
|
||||||
},
|
},
|
||||||
Ok(items) => {
|
Ok(items) => {
|
||||||
if !items.is_empty() {
|
if !items.is_empty() {
|
||||||
// max_id = the last sync token
|
// If we fetched something
|
||||||
// if we still haven't reached the last sync token yet,
|
// we should record the current last id to *some* token
|
||||||
// return a new cursor token and keep the sync token
|
// this may be `cursor_token` or `sync_token`
|
||||||
if let Some(max_id) = max_id {
|
// if we have more to fetch, we set `cursor_token` to this id
|
||||||
resp.cursor_token = Some(items[0].id.to_string());
|
// so that the client knows to continue
|
||||||
resp.sync_token = Some(max_id.to_string());
|
// 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 {
|
||||||
// Else, use the current max id as the sync_token
|
// Pass the same sync_token back
|
||||||
resp.sync_token = Some(items[0].id.to_string());
|
resp.sync_token = inner_params.sync_token.clone();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
resp.retrieved_items = items.into_iter().map(|x| x.into()).collect();
|
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 = stmt.filter(id.le(max_id));
|
||||||
}
|
}
|
||||||
|
|
||||||
stmt.order(id.desc())
|
stmt.order(id.asc())
|
||||||
.load::<Item>(db)
|
.load::<Item>(db)
|
||||||
.map_err(|_| "Database error".into())
|
.map_err(|_| "Database error".into())
|
||||||
})
|
})
|
||||||
|
|
Loading…
Reference in a new issue