0

I am developing a RESTful Android app using SyncAdapter. I have watched some screencasts and read some tutorials, but they only address basic dynamics. Before starting to write the code, I would like to try and receive feedback from expert users about concurrency issues.

Step 1. The user U inserts a new entry E into the table T of the database. The entry has a column status = TO_SYNC.

Step 2. Before the entry E is synced, U decides to modify it. An activity A starts for modifying the column values of E.

Step 3. While the user is modifying the entry, the SyncAdapter starts and sends the entries with status == TO_SYNC to the server. For each entry, the SyncAdapter sets status = SYNCED once it receives a positive answer from the server.

Step 4. Let's say that a concurrent access to the same entry E causes a conflict:

  1. The SyncAdapter reads E, sends E to the server
  2. The activity A completes and sets E status to TO_SYNC
  3. The SyncAdapter receives the ok from the server and sets the status of E to SYNCED
  4. At this point the new values of E will not be synced since the value TO_SYNC has been overwritten by the SyncAdapter.

My question is: how can I avoid such issue without blocking the entire database with a begin/end transaction while syncing (which could take a long time to complete)? Should I fall back on a classical java lock on single entries? Is there a more elegant way?

Antonio Sesto
  • 2,868
  • 5
  • 33
  • 51

2 Answers2

0

You can sync to the server based on timestamps (call it LAST_UPDATED_TIME) rather than a simple flag and along with that in another column (call it HASH) you store the hash value of the concatenated string of all the values in a row. With this you check the timestamp since last sync, get those incremental data to be synced and sync to the server (of course in a separate thread) and when you get back the results you will do the following steps:

  • Compare the hash of the data currently in the database/row against what was synced.
  • Based on the truthness of the above statement two things can happen:
    1. If the hash of the data in the db/row is equals to that value that was synced, you just update the LAST_UPDATED_TIME field with the time of sync
    2. If the hash of the data in the db/row is not equals to that values that was synced, you immediately sync the row again (you can obviously optimize this even more)
Bhuvan
  • 285
  • 1
  • 3
  • 11
0

Another way, with second column "updated_at"

  1. The SyncAdapter reads E, sends E to the server
  2. The activity A completes and sets E status to TO_SYNC and updated_at at NOW
  3. The SyncAdapter receives the ok from the server
  4. The SyncAdapter reads E_bis, compare E.updated_at and E_bis.updated_at, if different => request new sync, else => sets the status of E to SYNCED
Wicowyn
  • 11
  • 1
  • 6