Request can now be canceled properly: it should fix the issue with live chunk being deleted.

This commit is contained in:
ganfra 2019-06-12 14:49:39 +02:00 committed by Benoit Marty
parent 5b0cab3e8a
commit 1547045165
5 changed files with 49 additions and 38 deletions

View file

@ -28,34 +28,45 @@ import com.squareup.moshi.Moshi
import im.vector.matrix.android.api.failure.Failure
import im.vector.matrix.android.api.failure.MatrixError
import im.vector.matrix.android.internal.di.MoshiProvider
import kotlinx.coroutines.suspendCancellableCoroutine
import okhttp3.ResponseBody
import retrofit2.Call
import timber.log.Timber
import java.io.IOException
import kotlin.coroutines.resume
internal inline fun <DATA> executeRequest(block: Request<DATA>.() -> Unit) = Request<DATA>().apply(block).execute()
internal suspend inline fun <DATA> executeRequest(block: Request<DATA>.() -> Unit) = Request<DATA>().apply(block).execute()
internal class Request<DATA> {
private val moshi: Moshi = MoshiProvider.providesMoshi()
lateinit var apiCall: Call<DATA>
fun execute(): Try<DATA> {
return Try {
val response = apiCall.runAsync(IO.async()).fix().unsafeRunSync()
if (response.isSuccessful) {
response.body() ?: throw IllegalStateException("The request returned a null body")
} else {
throw manageFailure(response.errorBody(), response.code())
suspend fun execute(): Try<DATA> {
return suspendCancellableCoroutine { continuation ->
continuation.invokeOnCancellation {
Timber.v("Request is canceled")
apiCall.cancel()
}
}.recoverWith {
when (it) {
is IOException -> Failure.NetworkConnection(it)
is Failure.ServerError,
is Failure.OtherServerError -> it
else -> Failure.Unknown(it)
}.failure()
val result = Try {
val response = apiCall.runAsync(IO.async()).fix().unsafeRunSync()
if (response.isSuccessful) {
response.body()
?: throw IllegalStateException("The request returned a null body")
} else {
throw manageFailure(response.errorBody(), response.code())
}
}.recoverWith {
when (it) {
is IOException -> Failure.NetworkConnection(it)
is Failure.ServerError,
is Failure.OtherServerError -> it
else -> Failure.Unknown(it)
}.failure()
}
continuation.resume(result)
}
}
private fun manageFailure(errorBody: ResponseBody?, httpCode: Int): Throwable {

View file

@ -21,13 +21,13 @@ import arrow.core.fix
import arrow.instances.`try`.monad.monad
import arrow.typeclasses.binding
import com.zhuinden.monarchy.Monarchy
import im.vector.matrix.android.internal.task.Task
import im.vector.matrix.android.internal.database.model.GroupSummaryEntity
import im.vector.matrix.android.internal.database.query.where
import im.vector.matrix.android.internal.network.executeRequest
import im.vector.matrix.android.internal.session.group.model.GroupRooms
import im.vector.matrix.android.internal.session.group.model.GroupSummaryResponse
import im.vector.matrix.android.internal.session.group.model.GroupUsers
import im.vector.matrix.android.internal.task.Task
import im.vector.matrix.android.internal.util.tryTransactionSync
import io.realm.kotlin.createObject
@ -45,21 +45,17 @@ internal class DefaultGetGroupDataTask(
override suspend fun execute(params: GetGroupDataTask.Params): Try<Unit> {
val groupId = params.groupId
val groupSummary = executeRequest<GroupSummaryResponse> {
apiCall = groupAPI.getSummary(groupId)
}
val groupRooms = executeRequest<GroupRooms> {
apiCall = groupAPI.getRooms(groupId)
}
val groupUsers = executeRequest<GroupUsers> {
apiCall = groupAPI.getUsers(groupId)
}
return Try.monad().binding {
val groupSummary = executeRequest<GroupSummaryResponse> {
apiCall = groupAPI.getSummary(groupId)
}.bind()
val groupRooms = executeRequest<GroupRooms> {
apiCall = groupAPI.getRooms(groupId)
}.bind()
val groupUsers = executeRequest<GroupUsers> {
apiCall = groupAPI.getUsers(groupId)
}.bind()
insertInDb(groupSummary, groupRooms, groupUsers, groupId).bind()
insertInDb(groupSummary.bind(), groupRooms.bind(), groupUsers.bind(), groupId).bind()
}.fix()
}
@ -71,12 +67,13 @@ internal class DefaultGetGroupDataTask(
return monarchy
.tryTransactionSync { realm ->
val groupSummaryEntity = GroupSummaryEntity.where(realm, groupId).findFirst()
?: realm.createObject(groupId)
?: realm.createObject(groupId)
groupSummaryEntity.avatarUrl = groupSummary.profile?.avatarUrl ?: ""
val name = groupSummary.profile?.name
groupSummaryEntity.displayName = if (name.isNullOrEmpty()) groupId else name
groupSummaryEntity.shortDescription = groupSummary.profile?.shortDescription ?: ""
groupSummaryEntity.shortDescription = groupSummary.profile?.shortDescription
?: ""
val roomIds = groupRooms.rooms.map { it.roomId }
groupSummaryEntity.roomIds.clear()

View file

@ -16,6 +16,7 @@
package im.vector.matrix.android.internal.session.room.relation
import android.content.Context
import androidx.work.CoroutineWorker
import androidx.work.Worker
import androidx.work.WorkerParameters
import com.squareup.moshi.JsonClass
@ -32,7 +33,7 @@ import im.vector.matrix.android.internal.util.WorkerParamsFactory
import org.koin.standalone.inject
class SendRelationWorker(context: Context, params: WorkerParameters)
: Worker(context, params), MatrixKoinComponent {
: CoroutineWorker(context, params), MatrixKoinComponent {
@JsonClass(generateAdapter = true)
@ -44,7 +45,7 @@ class SendRelationWorker(context: Context, params: WorkerParameters)
private val roomAPI by inject<RoomAPI>()
override fun doWork(): Result {
override suspend fun doWork(): Result {
val params = WorkerParamsFactory.fromData<Params>(inputData)
?: return Result.failure()

View file

@ -16,6 +16,7 @@
package im.vector.matrix.android.internal.session.room.send
import android.content.Context
import androidx.work.CoroutineWorker
import androidx.work.Worker
import androidx.work.WorkerParameters
import com.squareup.moshi.JsonClass
@ -27,7 +28,7 @@ import im.vector.matrix.android.internal.util.WorkerParamsFactory
import org.koin.standalone.inject
internal class RedactEventWorker(context: Context, params: WorkerParameters)
: Worker(context, params), MatrixKoinComponent {
: CoroutineWorker(context, params), MatrixKoinComponent {
@JsonClass(generateAdapter = true)
internal data class Params(
@ -39,7 +40,7 @@ internal class RedactEventWorker(context: Context, params: WorkerParameters)
private val roomAPI by inject<RoomAPI>()
override fun doWork(): Result {
override suspend fun doWork(): Result {
val params = WorkerParamsFactory.fromData<Params>(inputData)
?: return Result.failure()

View file

@ -17,6 +17,7 @@
package im.vector.matrix.android.internal.session.room.send
import android.content.Context
import androidx.work.CoroutineWorker
import androidx.work.Worker
import androidx.work.WorkerParameters
import com.squareup.moshi.JsonClass
@ -30,7 +31,7 @@ import im.vector.matrix.android.internal.util.WorkerParamsFactory
import org.koin.standalone.inject
internal class SendEventWorker(context: Context, params: WorkerParameters)
: Worker(context, params), MatrixKoinComponent {
: CoroutineWorker(context, params), MatrixKoinComponent {
@JsonClass(generateAdapter = true)
@ -42,7 +43,7 @@ internal class SendEventWorker(context: Context, params: WorkerParameters)
private val roomAPI by inject<RoomAPI>()
private val localEchoUpdater by inject<LocalEchoUpdater>()
override fun doWork(): Result {
override suspend fun doWork(): Result {
val params = WorkerParamsFactory.fromData<Params>(inputData)
?: return Result.success()