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.Failure
import im.vector.matrix.android.api.failure.MatrixError import im.vector.matrix.android.api.failure.MatrixError
import im.vector.matrix.android.internal.di.MoshiProvider import im.vector.matrix.android.internal.di.MoshiProvider
import kotlinx.coroutines.suspendCancellableCoroutine
import okhttp3.ResponseBody import okhttp3.ResponseBody
import retrofit2.Call import retrofit2.Call
import timber.log.Timber import timber.log.Timber
import java.io.IOException 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> { internal class Request<DATA> {


private val moshi: Moshi = MoshiProvider.providesMoshi() private val moshi: Moshi = MoshiProvider.providesMoshi()
lateinit var apiCall: Call<DATA> lateinit var apiCall: Call<DATA>


fun execute(): Try<DATA> { suspend fun execute(): Try<DATA> {
return Try { return suspendCancellableCoroutine { continuation ->
val response = apiCall.runAsync(IO.async()).fix().unsafeRunSync() continuation.invokeOnCancellation {
if (response.isSuccessful) { Timber.v("Request is canceled")
response.body() ?: throw IllegalStateException("The request returned a null body") apiCall.cancel()
} else {
throw manageFailure(response.errorBody(), response.code())
} }
}.recoverWith { val result = Try {
when (it) { val response = apiCall.runAsync(IO.async()).fix().unsafeRunSync()
is IOException -> Failure.NetworkConnection(it) if (response.isSuccessful) {
is Failure.ServerError, response.body()
is Failure.OtherServerError -> it ?: throw IllegalStateException("The request returned a null body")
else -> Failure.Unknown(it) } else {
}.failure() 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 { 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.instances.`try`.monad.monad
import arrow.typeclasses.binding import arrow.typeclasses.binding
import com.zhuinden.monarchy.Monarchy 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.model.GroupSummaryEntity
import im.vector.matrix.android.internal.database.query.where import im.vector.matrix.android.internal.database.query.where
import im.vector.matrix.android.internal.network.executeRequest 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.GroupRooms
import im.vector.matrix.android.internal.session.group.model.GroupSummaryResponse 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.session.group.model.GroupUsers
import im.vector.matrix.android.internal.task.Task
import im.vector.matrix.android.internal.util.tryTransactionSync import im.vector.matrix.android.internal.util.tryTransactionSync
import io.realm.kotlin.createObject import io.realm.kotlin.createObject


@ -45,21 +45,17 @@ internal class DefaultGetGroupDataTask(


override suspend fun execute(params: GetGroupDataTask.Params): Try<Unit> { override suspend fun execute(params: GetGroupDataTask.Params): Try<Unit> {
val groupId = params.groupId 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 { return Try.monad().binding {

insertInDb(groupSummary.bind(), groupRooms.bind(), groupUsers.bind(), groupId).bind()
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()
}.fix() }.fix()
} }


@ -71,12 +67,13 @@ internal class DefaultGetGroupDataTask(
return monarchy return monarchy
.tryTransactionSync { realm -> .tryTransactionSync { realm ->
val groupSummaryEntity = GroupSummaryEntity.where(realm, groupId).findFirst() val groupSummaryEntity = GroupSummaryEntity.where(realm, groupId).findFirst()
?: realm.createObject(groupId) ?: realm.createObject(groupId)


groupSummaryEntity.avatarUrl = groupSummary.profile?.avatarUrl ?: "" groupSummaryEntity.avatarUrl = groupSummary.profile?.avatarUrl ?: ""
val name = groupSummary.profile?.name val name = groupSummary.profile?.name
groupSummaryEntity.displayName = if (name.isNullOrEmpty()) groupId else 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 } val roomIds = groupRooms.rooms.map { it.roomId }
groupSummaryEntity.roomIds.clear() groupSummaryEntity.roomIds.clear()

View File

@ -16,6 +16,7 @@
package im.vector.matrix.android.internal.session.room.relation package im.vector.matrix.android.internal.session.room.relation


import android.content.Context import android.content.Context
import androidx.work.CoroutineWorker
import androidx.work.Worker import androidx.work.Worker
import androidx.work.WorkerParameters import androidx.work.WorkerParameters
import com.squareup.moshi.JsonClass import com.squareup.moshi.JsonClass
@ -32,7 +33,7 @@ import im.vector.matrix.android.internal.util.WorkerParamsFactory
import org.koin.standalone.inject import org.koin.standalone.inject


class SendRelationWorker(context: Context, params: WorkerParameters) class SendRelationWorker(context: Context, params: WorkerParameters)
: Worker(context, params), MatrixKoinComponent { : CoroutineWorker(context, params), MatrixKoinComponent {




@JsonClass(generateAdapter = true) @JsonClass(generateAdapter = true)
@ -44,7 +45,7 @@ class SendRelationWorker(context: Context, params: WorkerParameters)


private val roomAPI by inject<RoomAPI>() private val roomAPI by inject<RoomAPI>()


override fun doWork(): Result { override suspend fun doWork(): Result {
val params = WorkerParamsFactory.fromData<Params>(inputData) val params = WorkerParamsFactory.fromData<Params>(inputData)
?: return Result.failure() ?: return Result.failure()



View File

@ -16,6 +16,7 @@
package im.vector.matrix.android.internal.session.room.send package im.vector.matrix.android.internal.session.room.send


import android.content.Context import android.content.Context
import androidx.work.CoroutineWorker
import androidx.work.Worker import androidx.work.Worker
import androidx.work.WorkerParameters import androidx.work.WorkerParameters
import com.squareup.moshi.JsonClass import com.squareup.moshi.JsonClass
@ -27,7 +28,7 @@ import im.vector.matrix.android.internal.util.WorkerParamsFactory
import org.koin.standalone.inject import org.koin.standalone.inject


internal class RedactEventWorker(context: Context, params: WorkerParameters) internal class RedactEventWorker(context: Context, params: WorkerParameters)
: Worker(context, params), MatrixKoinComponent { : CoroutineWorker(context, params), MatrixKoinComponent {


@JsonClass(generateAdapter = true) @JsonClass(generateAdapter = true)
internal data class Params( internal data class Params(
@ -39,7 +40,7 @@ internal class RedactEventWorker(context: Context, params: WorkerParameters)


private val roomAPI by inject<RoomAPI>() private val roomAPI by inject<RoomAPI>()


override fun doWork(): Result { override suspend fun doWork(): Result {
val params = WorkerParamsFactory.fromData<Params>(inputData) val params = WorkerParamsFactory.fromData<Params>(inputData)
?: return Result.failure() ?: return Result.failure()



View File

@ -17,6 +17,7 @@
package im.vector.matrix.android.internal.session.room.send package im.vector.matrix.android.internal.session.room.send


import android.content.Context import android.content.Context
import androidx.work.CoroutineWorker
import androidx.work.Worker import androidx.work.Worker
import androidx.work.WorkerParameters import androidx.work.WorkerParameters
import com.squareup.moshi.JsonClass import com.squareup.moshi.JsonClass
@ -30,7 +31,7 @@ import im.vector.matrix.android.internal.util.WorkerParamsFactory
import org.koin.standalone.inject import org.koin.standalone.inject


internal class SendEventWorker(context: Context, params: WorkerParameters) internal class SendEventWorker(context: Context, params: WorkerParameters)
: Worker(context, params), MatrixKoinComponent { : CoroutineWorker(context, params), MatrixKoinComponent {




@JsonClass(generateAdapter = true) @JsonClass(generateAdapter = true)
@ -42,7 +43,7 @@ internal class SendEventWorker(context: Context, params: WorkerParameters)
private val roomAPI by inject<RoomAPI>() private val roomAPI by inject<RoomAPI>()
private val localEchoUpdater by inject<LocalEchoUpdater>() private val localEchoUpdater by inject<LocalEchoUpdater>()


override fun doWork(): Result { override suspend fun doWork(): Result {


val params = WorkerParamsFactory.fromData<Params>(inputData) val params = WorkerParamsFactory.fromData<Params>(inputData)
?: return Result.success() ?: return Result.success()