I’ve got a race condition between WorkManager workers and my main app that I need to figure out how to prevent in the proper way.
I’m using WorkManager background workers which have access to RoomDB - we’ll call it UploadWorker.
I also have background IO threads in my main application which query the network and get the result - we’ll call that operation a Refresh.
The UploadWorker grabs the value from the db and sends it over the network to an API.
The Refresh operation also calls the API and gets most recent values for the same table for which the UploadWorker is saving changes. If the Refresh happens during the UploadWorker, it can possibly overwrite the values that were saved that UploadWorker is trying to update in the API. A classic race condition that sometimes works and sometimes fails, just depending on the timing of things.
So where should I put a lock or some synchronized code that will prevent this? Once the user hits Upload, I don’t want the value in the DB to change until the UploadWorker completes successfully. So that means I need to lock out the Refresh operation from happening.
I’m pretty sure but don’t completely understand whether a Background Worker is actually using the same threads that the main app does. So is there no other place to create a lock than using SharedPreferences or RoomDB? Is there an Android approved or recommended way of implementing the synchronization I need here?
If there isn’t already a way that’s recommended, my thought is to create a @Transaction around a RoomDB method function so that I can call a Query and another Insert or Update all at once on a separate locking table which will keep track of which operation has the lock. But this feels like I am reinventing the wheel doing something that should have already been provided by Android somehow.