https://kotlinlang.org logo
#android-architecture
Title
# android-architecture
u

ursus

01/05/2022, 4:54 AM
Is it needed to sequentialize data sync? sync contains api get + db write. Db writes are synchronized. So only way this can get messed up if the 2nd concurrent sync arrived sooner than 1st Is this really relevant for production? Should I put Mutex everywhere?
g

gildor

01/05/2022, 8:30 AM
DB already atomic, if you have it, why you need any kind mutex?
j

Javier

01/05/2022, 9:00 AM
@gildor are there docs about that?
g

gildor

01/05/2022, 9:01 AM
docs about what?
j

Javier

01/05/2022, 9:02 AM
About any db being atomic
or more generic explanation is ACID: https://en.wikipedia.org/wiki/ACID
It’s not every database, I just assumed that it probably sqlite, because Vlastimil work on Android apps
also all common relational DBs are ACID
j

Javier

01/05/2022, 9:06 AM
Thank you 🙏
u

ursus

01/05/2022, 12:46 PM
What I meant was 2nd request might arrive sooner, so it enters the db transaction first i.e request1 sent at t0, request2 sent at t1, request2 response in t2, request1 response in t3
g

gildor

01/05/2022, 2:03 PM
Why is it a problem?
If you worry that request with older data will arrive later, you can of course just pass update date as part of sql requeat and ignore older data
u

ursus

01/05/2022, 2:05 PM
isnt that state smashing? request2 would carry the theoretically latest state or do we assume its fine since 99.999999% its the same?
g

gildor

01/05/2022, 2:05 PM
But honestly for me it doesn't look like a real problem
No, it wouldn't be the same if you explicitly set what request has newer data, so db would compare last update time
Though, I'm not sure why you have such case with multiple requests for the same data which
If you have a single resource, wouldn't it be better to wrap it to some repository, which will ignore unnecessary duplicate requests. I believe duplicate requests are a bigger problem than the super small chance that one of the requests will aame 20ms older data than previous
u

ursus

01/05/2022, 2:58 PM
well how would you deal with duplicates? if running then return? this means the suspend function would return successfully, lying to its callsite. So its either not care about concurrent requests, or throw, or Mutex, no?
Copy code
class DataRepository {
	suspend fun syncData() {
		val data = api.data()
		db.saveData(data)
	}
}
g

gildor

01/06/2022, 3:05 AM
Well, this mutex not necessary should be mutex, also “Should I put Mutex everywhere” is not everywhere, but only on this syncData method
I see it something like this:
Copy code
class DataRepository(private val appScope: CoroutineScope) {
    private val syncJob: Job? = null
	suspend fun syncData() {
        if (syncJob?.isActive == true) {
            syncJob.join()
        } else {
            syncJob = scope.launch { 
              val data = api.data()
		      db.saveData(data)
            }
            syncDeferred?.await()
        }
	}
}
You can add atomic access to Job and mutex if want to make it completely thread safe Similar can be done with flow instead of job At least this approach avoid duplicate requests, also you can add cooldown time, like delay(SOME_DELAY_BEFORE_SYNC) after saveData, so no additional requests would be done
u

ursus

01/06/2022, 1:29 PM
my issue with that is, this is only really a problem if responses come in different order to requests, which never happens so.. should I care? and its only valid if you get concurrent syncs which is practise is almost never
or maybe have a mutext at the api call level?
g

gildor

01/06/2022, 3:23 PM
Global mutex will destroy all concurrency for network requests, which makes everything much slower
Why have global mutex, even in theory it a problem only when requesting the same data
u

ursus

01/07/2022, 2:01 PM
Yea guess it doesnt matter if I put the mutex to left or right.
Its just almost all my GET api are not parametrized, so youre accessing the same resource, so such repo call, needs a mutex in your opinion? for every such domain specific sync?
g

gildor

01/08/2022, 2:39 PM
Why do you need mutex for get requests? For sync yeah, it looks reasonable to have some mechanism preventing useless parallel requests, though I'm not sure that mutex is best solution, it will just prevent parallel requests, but then you will have multiple requests one after another receiving probably exactly the same data
u

ursus

01/08/2022, 2:54 PM
because of force syncs, i.e. i have natural sync which sync every so often, and a force sync which overrides local flags, for example after a push message after som async action
my question actually is, is this even a issue? it only applies if parallel responses for the same resource arrive out of order, can that even happen?
g

gildor

01/08/2022, 3:03 PM
It may happen in theory of course Force sync is easy to do with my example above, just pass a param like force, and cancel previous request If you always need force update, just always cancel previous active request (also easy to do if use Flow + mapLatest
u

ursus

01/08/2022, 4:39 PM
well Id have to save with the job if the sync was force and not cancel it
and then quick return which is a lie
or throw which is a waste... or mutex
g

gildor

01/09/2022, 1:20 AM
But you said that you have force update cases, in this case having one request after another is waste
I think you just should understand what kind semantics for requests (or sync, which I believe very different case) you would like to have, not trying to use some particular technical decision (like mutex) which has own, often not expected, behavior