api: items/sync: explain why we need the per-user lock

This commit is contained in:
Peter Cai 2020-02-23 11:22:08 +08:00
parent fb7beff3e0
commit d4c4be4d63
No known key found for this signature in database
GPG Key ID: 71F5FB4E4F3FD54F
1 changed files with 13 additions and 0 deletions

View File

@ -198,11 +198,24 @@ fn items_sync(
u: user::User, params: Json<SyncParams>
) -> Custom<JsonResp<SyncResp>> {
// Only allow one sync per user at the same time
// Operations below are far from atomic (neither are they in Ruby or Go impl)
// so allowing multiple synchronize sessions each time can cause
// some confusing behavior, e.g. another sync session might insert
// something new into the database after this one gets the current_max_id
// but before this one returns. It can also mess things up during
// insertions into the database.
// In short, do not let the same user synchronize from two clients
// at the same time. All code below assumes that this lock works
// and at any given point in time, up to one sync process is running
// for each user.
let mutex = lock.get_mutex(u.id);
let _lock = mutex.lock().unwrap();
// sync_token should always be set to the maximum ID currently available
// (for this user, of course)
// Remember that we have a mutex at the beginning of this function,
// so all that can change the current_max_id for the current user
// is operations later in this function.
let new_sync_token = match item::SyncItem::get_current_max_id(&db, &u) {
Ok(Some(id)) => Some(id.to_string()),
Ok(None) => None,