Daniel
12/18/2022, 7:35 PMsuspend fun doLogout(token: String) {
val userId = appService.currentUser?.id
realm.write {
var user = query<UserInfo>("_id = $0", userId).first().find()
if (user != null) {
val productIndex =
user.FCMToken.withIndex().findLast { it.value == token }!!.index
user = findLatest(user)!!.also {
it.FCMToken.removeAt(productIndex)
}
copyToRealm(user)
appService.currentUser?.logOut() // Suspension functions can be called only within coroutine body
}
}
}
Is there anyway to fix this without changing much code?
I need to do first the db operation then logOut()Mitchell Syer
12/18/2022, 9:16 PMsuspend fun doLogout(token: String) {
val userId = appService.currentUser?.id
realm.write {
var user = query<UserInfo>("_id = $0", userId).first().find()
if (user != null) {
val productIndex =
user.FCMToken.withIndex().findLast { it.value == token }!!.index
user = findLatest(user)!!.also {
it.FCMToken.removeAt(productIndex)
}
copyToRealm(user)
}
}
appService.currentUser?.logOut()
}
This should work as long as realm.write is not launching the code in another threadDaniel
12/18/2022, 9:39 PMDaniel
12/18/2022, 9:39 PMDaniel
12/18/2022, 9:39 PMMitchell Syer
12/18/2022, 9:42 PMsuspend fun doLogout(token: String) {
val userId = appService.currentUser?.id
coroutineScope {
realm.write {
var user = query<UserInfo>("_id = $0", userId).first().find()
if (user != null) {
val productIndex =
user.FCMToken.withIndex().findLast { it.value == token }!!.index
user = findLatest(user)!!.also {
it.FCMToken.removeAt(productIndex)
}
copyToRealm(user)
launch { appService.currentUser?.logOut() }
}
}
}
}
Mitchell Syer
12/18/2022, 9:43 PMDaniel
12/18/2022, 9:49 PMMitchell Syer
12/18/2022, 10:03 PMsuspend fun doLogout(token: String) {
val userId = appService.currentUser?.id
val deferred = CompletableDeferred<Unit>()
realm.write {
var user = query<UserInfo>("_id = $0", userId).first().find()
if (user != null) {
val productIndex =
user.FCMToken.withIndex().findLast { it.value == token }!!.index
user = findLatest(user)!!.also {
it.FCMToken.removeAt(productIndex)
}
copyToRealm(user)
}
deferred.complete(Unit)
}
deferred.await()
appService.currentUser?.logOut()
}
Daniel
12/18/2022, 10:12 PMMitchell Syer
12/18/2022, 10:15 PMmkrussel
12/19/2022, 2:11 PMream.write
is a blocking call, in which case it should be run in a new coroutine (suspend functions should be main thread safe).
So you would wrap the call to realm.write
in a withContext(<http://Dispatchers.IO|Dispatchers.IO> { }
And then make the call to logOut
after the withContext
returns. This is similar to the CompletableDeferred
solution above, but I think more idiomatic.mkrussel
12/19/2022, 2:15 PMrealm.write
is launching it's own thread, then I would probably use the suspendCoroutine
function or suspendCancellableCoroutine
if realm gives you a way to cancel.Daniel
12/19/2022, 9:51 PMMitchell Syer
12/19/2022, 10:07 PMmkrussel
12/19/2022, 10:08 PMrealm.write
is already suspending, so neither of our suggestions are needed