Task: use a builder with DSL and introduce Constraints (only boolean connectedToNetwork at the moment)

This commit is contained in:
ganfra 2019-08-05 17:27:40 +02:00
parent c413321a22
commit 4a74f58516
24 changed files with 528 additions and 404 deletions

View File

@ -72,7 +72,6 @@ import im.vector.matrix.android.internal.session.room.membership.RoomMembers
import im.vector.matrix.android.internal.session.sync.model.SyncResponse import im.vector.matrix.android.internal.session.sync.model.SyncResponse
import im.vector.matrix.android.internal.task.TaskExecutor import im.vector.matrix.android.internal.task.TaskExecutor
import im.vector.matrix.android.internal.task.configureWith import im.vector.matrix.android.internal.task.configureWith
import im.vector.matrix.android.internal.task.toConfigurableTask
import im.vector.matrix.android.internal.util.JsonCanonicalizer import im.vector.matrix.android.internal.util.JsonCanonicalizer
import im.vector.matrix.android.internal.util.MatrixCoroutineDispatchers import im.vector.matrix.android.internal.util.MatrixCoroutineDispatchers
import im.vector.matrix.android.internal.util.fetchCopied import im.vector.matrix.android.internal.util.fetchCopied
@ -167,22 +166,25 @@ internal class CryptoManager @Inject constructor(


override fun setDeviceName(deviceId: String, deviceName: String, callback: MatrixCallback<Unit>) { override fun setDeviceName(deviceId: String, deviceName: String, callback: MatrixCallback<Unit>) {
setDeviceNameTask setDeviceNameTask
.configureWith(SetDeviceNameTask.Params(deviceId, deviceName)) .configureWith(SetDeviceNameTask.Params(deviceId, deviceName)) {
.dispatchTo(callback) this.callback = callback
}
.executeBy(taskExecutor) .executeBy(taskExecutor)
} }


override fun deleteDevice(deviceId: String, callback: MatrixCallback<Unit>) { override fun deleteDevice(deviceId: String, callback: MatrixCallback<Unit>) {
deleteDeviceTask deleteDeviceTask
.configureWith(DeleteDeviceTask.Params(deviceId)) .configureWith(DeleteDeviceTask.Params(deviceId)) {
.dispatchTo(callback) this.callback = callback
}
.executeBy(taskExecutor) .executeBy(taskExecutor)
} }


override fun deleteDeviceWithUserPassword(deviceId: String, authSession: String?, password: String, callback: MatrixCallback<Unit>) { override fun deleteDeviceWithUserPassword(deviceId: String, authSession: String?, password: String, callback: MatrixCallback<Unit>) {
deleteDeviceWithUserPasswordTask deleteDeviceWithUserPasswordTask
.configureWith(DeleteDeviceWithUserPasswordTask.Params(deviceId, authSession, password)) .configureWith(DeleteDeviceWithUserPasswordTask.Params(deviceId, authSession, password)) {
.dispatchTo(callback) this.callback = callback
}
.executeBy(taskExecutor) .executeBy(taskExecutor)
} }


@ -196,8 +198,9 @@ internal class CryptoManager @Inject constructor(


override fun getDevicesList(callback: MatrixCallback<DevicesListResponse>) { override fun getDevicesList(callback: MatrixCallback<DevicesListResponse>) {
getDevicesTask getDevicesTask
.toConfigurableTask() .configureWith {
.dispatchTo(callback) this.callback = callback
}
.executeBy(taskExecutor) .executeBy(taskExecutor)
} }


@ -1046,8 +1049,9 @@ internal class CryptoManager @Inject constructor(


override fun clearCryptoCache(callback: MatrixCallback<Unit>) { override fun clearCryptoCache(callback: MatrixCallback<Unit>) {
clearCryptoDataTask clearCryptoDataTask
.toConfigurableTask() .configureWith {
.dispatchTo(callback) this.callback = callback
}
.executeBy(taskExecutor) .executeBy(taskExecutor)
} }



View File

@ -299,10 +299,12 @@ internal class OutgoingRoomKeyRequestManager @Inject constructor(
// TODO Change this two hard coded key to something better // TODO Change this two hard coded key to something better
contentMap.setObject(recipient["userId"], recipient["deviceId"], message) contentMap.setObject(recipient["userId"], recipient["deviceId"], message)
} }
sendToDeviceTask.configureWith(SendToDeviceTask.Params(EventType.ROOM_KEY_REQUEST, contentMap, transactionId)) sendToDeviceTask
.dispatchTo(callback) .configureWith(SendToDeviceTask.Params(EventType.ROOM_KEY_REQUEST, contentMap, transactionId)) {
.executeOn(TaskThread.CALLER) this.callback = callback
.callbackOn(TaskThread.CALLER) this.callbackThread = TaskThread.CALLER
this.executionThread = TaskThread.CALLER
}
.executeBy(taskExecutor) .executeBy(taskExecutor)
} }



View File

@ -51,7 +51,10 @@ import im.vector.matrix.android.internal.crypto.store.db.model.KeysBackupDataEnt
import im.vector.matrix.android.internal.di.MoshiProvider import im.vector.matrix.android.internal.di.MoshiProvider
import im.vector.matrix.android.internal.extensions.foldToCallback import im.vector.matrix.android.internal.extensions.foldToCallback
import im.vector.matrix.android.internal.session.SessionScope import im.vector.matrix.android.internal.session.SessionScope
import im.vector.matrix.android.internal.task.* import im.vector.matrix.android.internal.task.Task
import im.vector.matrix.android.internal.task.TaskExecutor
import im.vector.matrix.android.internal.task.TaskThread
import im.vector.matrix.android.internal.task.configureWith
import im.vector.matrix.android.internal.util.JsonCanonicalizer import im.vector.matrix.android.internal.util.JsonCanonicalizer
import im.vector.matrix.android.internal.util.MatrixCoroutineDispatchers import im.vector.matrix.android.internal.util.MatrixCoroutineDispatchers
import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.GlobalScope
@ -200,8 +203,8 @@ internal class KeysBackup @Inject constructor(
keysBackupStateManager.state = KeysBackupState.Enabling keysBackupStateManager.state = KeysBackupState.Enabling


createKeysBackupVersionTask createKeysBackupVersionTask
.configureWith(createKeysBackupVersionBody) .configureWith(createKeysBackupVersionBody) {
.dispatchTo(object : MatrixCallback<KeysVersion> { this.callback = object : MatrixCallback<KeysVersion> {
override fun onSuccess(info: KeysVersion) { override fun onSuccess(info: KeysVersion) {
// Reset backup markers. // Reset backup markers.
cryptoStore.resetBackupMarkers() cryptoStore.resetBackupMarkers()
@ -224,7 +227,8 @@ internal class KeysBackup @Inject constructor(
keysBackupStateManager.state = KeysBackupState.Disabled keysBackupStateManager.state = KeysBackupState.Disabled
callback.onFailure(failure) callback.onFailure(failure)
} }
}) }
}
.executeBy(taskExecutor) .executeBy(taskExecutor)
} }


@ -239,8 +243,9 @@ internal class KeysBackup @Inject constructor(
keysBackupStateManager.state = KeysBackupState.Unknown keysBackupStateManager.state = KeysBackupState.Unknown
} }


deleteBackupTask.configureWith(DeleteBackupTask.Params(version)) deleteBackupTask
.dispatchTo(object : MatrixCallback<Unit> { .configureWith(DeleteBackupTask.Params(version)) {
this.callback = object : MatrixCallback<Unit> {
private fun eventuallyRestartBackup() { private fun eventuallyRestartBackup() {
// Do not stay in KeysBackupState.Unknown but check what is available on the homeserver // Do not stay in KeysBackupState.Unknown but check what is available on the homeserver
if (state == KeysBackupState.Unknown) { if (state == KeysBackupState.Unknown) {
@ -259,7 +264,8 @@ internal class KeysBackup @Inject constructor(


uiHandler.post { callback?.onFailure(failure) } uiHandler.post { callback?.onFailure(failure) }
} }
}) }
}
.executeBy(taskExecutor) .executeBy(taskExecutor)
} }
} }
@ -355,9 +361,10 @@ internal class KeysBackup @Inject constructor(
return getKeysBackupTrustBg(params) return getKeysBackupTrustBg(params)
} }
} }
.configureWith(keysBackupVersion) .configureWith(keysBackupVersion) {
.dispatchTo(callback) this.callback = callback
.executeOn(TaskThread.COMPUTATION) this.executionThread = TaskThread.COMPUTATION
}
.executeBy(taskExecutor) .executeBy(taskExecutor)
} }


@ -487,8 +494,8 @@ internal class KeysBackup @Inject constructor(


// And send it to the homeserver // And send it to the homeserver
updateKeysBackupVersionTask updateKeysBackupVersionTask
.configureWith(UpdateKeysBackupVersionTask.Params(keysBackupVersion.version!!, updateKeysBackupVersionBody)) .configureWith(UpdateKeysBackupVersionTask.Params(keysBackupVersion.version!!, updateKeysBackupVersionBody)) {
.dispatchTo(object : MatrixCallback<Unit> { this.callback = object : MatrixCallback<Unit> {
override fun onSuccess(data: Unit) { override fun onSuccess(data: Unit) {
// Relaunch the state machine on this updated backup version // Relaunch the state machine on this updated backup version
val newKeysBackupVersion = KeysVersionResult() val newKeysBackupVersion = KeysVersionResult()
@ -507,7 +514,8 @@ internal class KeysBackup @Inject constructor(
override fun onFailure(failure: Throwable) { override fun onFailure(failure: Throwable) {
callback.onFailure(failure) callback.onFailure(failure)
} }
}) }
}
.executeBy(taskExecutor) .executeBy(taskExecutor)
} }
} }
@ -753,8 +761,8 @@ internal class KeysBackup @Inject constructor(
if (roomId != null && sessionId != null) { if (roomId != null && sessionId != null) {
// Get key for the room and for the session // Get key for the room and for the session
getRoomSessionDataTask getRoomSessionDataTask
.configureWith(GetRoomSessionDataTask.Params(roomId, sessionId, version)) .configureWith(GetRoomSessionDataTask.Params(roomId, sessionId, version)) {
.dispatchTo(object : MatrixCallback<KeyBackupData> { this.callback = object : MatrixCallback<KeyBackupData> {
override fun onSuccess(data: KeyBackupData) { override fun onSuccess(data: KeyBackupData) {
// Convert to KeysBackupData // Convert to KeysBackupData
val keysBackupData = KeysBackupData() val keysBackupData = KeysBackupData()
@ -770,13 +778,14 @@ internal class KeysBackup @Inject constructor(
override fun onFailure(failure: Throwable) { override fun onFailure(failure: Throwable) {
callback.onFailure(failure) callback.onFailure(failure)
} }
}) }
}
.executeBy(taskExecutor) .executeBy(taskExecutor)
} else if (roomId != null) { } else if (roomId != null) {
// Get all keys for the room // Get all keys for the room
getRoomSessionsDataTask getRoomSessionsDataTask
.configureWith(GetRoomSessionsDataTask.Params(roomId, version)) .configureWith(GetRoomSessionsDataTask.Params(roomId, version)) {
.dispatchTo(object : MatrixCallback<RoomKeysBackupData> { this.callback = object : MatrixCallback<RoomKeysBackupData> {
override fun onSuccess(data: RoomKeysBackupData) { override fun onSuccess(data: RoomKeysBackupData) {
// Convert to KeysBackupData // Convert to KeysBackupData
val keysBackupData = KeysBackupData() val keysBackupData = KeysBackupData()
@ -789,13 +798,15 @@ internal class KeysBackup @Inject constructor(
override fun onFailure(failure: Throwable) { override fun onFailure(failure: Throwable) {
callback.onFailure(failure) callback.onFailure(failure)
} }
}) }
}
.executeBy(taskExecutor) .executeBy(taskExecutor)
} else { } else {
// Get all keys // Get all keys
getSessionsDataTask getSessionsDataTask
.configureWith(GetSessionsDataTask.Params(version)) .configureWith(GetSessionsDataTask.Params(version)) {
.dispatchTo(callback) this.callback = callback
}
.executeBy(taskExecutor) .executeBy(taskExecutor)
} }
} }
@ -850,8 +861,8 @@ internal class KeysBackup @Inject constructor(
override fun getVersion(version: String, override fun getVersion(version: String,
callback: MatrixCallback<KeysVersionResult?>) { callback: MatrixCallback<KeysVersionResult?>) {
getKeysBackupVersionTask getKeysBackupVersionTask
.configureWith(version) .configureWith(version) {
.dispatchTo(object : MatrixCallback<KeysVersionResult> { this.callback = object : MatrixCallback<KeysVersionResult> {
override fun onSuccess(data: KeysVersionResult) { override fun onSuccess(data: KeysVersionResult) {
callback.onSuccess(data) callback.onSuccess(data)
} }
@ -866,14 +877,15 @@ internal class KeysBackup @Inject constructor(
callback.onFailure(failure) callback.onFailure(failure)
} }
} }
}) }
}
.executeBy(taskExecutor) .executeBy(taskExecutor)
} }


override fun getCurrentVersion(callback: MatrixCallback<KeysVersionResult?>) { override fun getCurrentVersion(callback: MatrixCallback<KeysVersionResult?>) {
getKeysBackupLastVersionTask getKeysBackupLastVersionTask
.toConfigurableTask() .configureWith {
.dispatchTo(object : MatrixCallback<KeysVersionResult> { this.callback = object : MatrixCallback<KeysVersionResult> {
override fun onSuccess(data: KeysVersionResult) { override fun onSuccess(data: KeysVersionResult) {
callback.onSuccess(data) callback.onSuccess(data)
} }
@ -888,7 +900,8 @@ internal class KeysBackup @Inject constructor(
callback.onFailure(failure) callback.onFailure(failure)
} }
} }
}) }
}
.executeBy(taskExecutor) .executeBy(taskExecutor)
} }


@ -1231,10 +1244,7 @@ internal class KeysBackup @Inject constructor(


Timber.v("backupKeys: 4 - Sending request") Timber.v("backupKeys: 4 - Sending request")


// Make the request val sendingRequestCallback = object : MatrixCallback<BackupKeysResult> {
storeSessionDataTask
.configureWith(StoreSessionsDataTask.Params(keysBackupVersion!!.version!!, keysBackupData))
.dispatchTo(object : MatrixCallback<BackupKeysResult> {
override fun onSuccess(data: BackupKeysResult) { override fun onSuccess(data: BackupKeysResult) {
uiHandler.post { uiHandler.post {
Timber.v("backupKeys: 5a - Request complete") Timber.v("backupKeys: 5a - Request complete")
@ -1293,7 +1303,13 @@ internal class KeysBackup @Inject constructor(
} }
} }
} }
}) }

// Make the request
storeSessionDataTask
.configureWith(StoreSessionsDataTask.Params(keysBackupVersion!!.version!!, keysBackupData)){
this.callback = sendingRequestCallback
}
.executeBy(taskExecutor) .executeBy(taskExecutor)
} }
} }

View File

@ -37,6 +37,7 @@ import im.vector.matrix.android.internal.crypto.model.rest.*
import im.vector.matrix.android.internal.crypto.store.IMXCryptoStore import im.vector.matrix.android.internal.crypto.store.IMXCryptoStore
import im.vector.matrix.android.internal.crypto.tasks.SendToDeviceTask import im.vector.matrix.android.internal.crypto.tasks.SendToDeviceTask
import im.vector.matrix.android.internal.session.SessionScope import im.vector.matrix.android.internal.session.SessionScope
import im.vector.matrix.android.internal.task.TaskConstraints
import im.vector.matrix.android.internal.task.TaskExecutor import im.vector.matrix.android.internal.task.TaskExecutor
import im.vector.matrix.android.internal.task.configureWith import im.vector.matrix.android.internal.task.configureWith
import im.vector.matrix.android.internal.util.MatrixCoroutineDispatchers import im.vector.matrix.android.internal.util.MatrixCoroutineDispatchers
@ -415,8 +416,9 @@ internal class DefaultSasVerificationService @Inject constructor(private val cre
val contentMap = MXUsersDevicesMap<Any>() val contentMap = MXUsersDevicesMap<Any>()
contentMap.setObject(userId, userDevice, cancelMessage) contentMap.setObject(userId, userDevice, cancelMessage)


sendToDeviceTask.configureWith(SendToDeviceTask.Params(EventType.KEY_VERIFICATION_CANCEL, contentMap, transactionId)) sendToDeviceTask
.dispatchTo(object : MatrixCallback<Unit> { .configureWith(SendToDeviceTask.Params(EventType.KEY_VERIFICATION_CANCEL, contentMap, transactionId)) {
this.callback = object : MatrixCallback<Unit> {
override fun onSuccess(data: Unit) { override fun onSuccess(data: Unit) {
Timber.v("## SAS verification [$transactionId] canceled for reason ${code.value}") Timber.v("## SAS verification [$transactionId] canceled for reason ${code.value}")
} }
@ -424,7 +426,8 @@ internal class DefaultSasVerificationService @Inject constructor(private val cre
override fun onFailure(failure: Throwable) { override fun onFailure(failure: Throwable) {
Timber.e(failure, "## SAS verification [$transactionId] failed to cancel.") Timber.e(failure, "## SAS verification [$transactionId] failed to cancel.")
} }
}) }
}
.executeBy(taskExecutor) .executeBy(taskExecutor)
} }
} }

View File

@ -287,8 +287,9 @@ internal abstract class SASVerificationTransaction(
val contentMap = MXUsersDevicesMap<Any>() val contentMap = MXUsersDevicesMap<Any>()
contentMap.setObject(otherUserId, otherDeviceId, keyToDevice) contentMap.setObject(otherUserId, otherDeviceId, keyToDevice)


sendToDeviceTask.configureWith(SendToDeviceTask.Params(type, contentMap, transactionId)) sendToDeviceTask
.dispatchTo(object : MatrixCallback<Unit> { .configureWith(SendToDeviceTask.Params(type, contentMap, transactionId)) {
this.callback = object : MatrixCallback<Unit> {
override fun onSuccess(data: Unit) { override fun onSuccess(data: Unit) {
Timber.v("## SAS verification [$transactionId] toDevice type '$type' success.") Timber.v("## SAS verification [$transactionId] toDevice type '$type' success.")
if (onDone != null) { if (onDone != null) {
@ -303,7 +304,8 @@ internal abstract class SASVerificationTransaction(


cancel(onErrorReason) cancel(onErrorReason)
} }
}) }
}
.executeBy(taskExecutor) .executeBy(taskExecutor)
} }



View File

@ -24,6 +24,8 @@ import timber.log.Timber
import java.util.* import java.util.*
import javax.inject.Inject import javax.inject.Inject
import kotlin.collections.ArrayList import kotlin.collections.ArrayList
import kotlin.coroutines.resume
import kotlin.coroutines.suspendCoroutine


@MatrixScope @MatrixScope
internal class NetworkConnectivityChecker @Inject constructor(context: Context) { internal class NetworkConnectivityChecker @Inject constructor(context: Context) {
@ -34,24 +36,41 @@ internal class NetworkConnectivityChecker @Inject constructor(context: Context)
.build(context) .build(context)


private val merlinsBeard = MerlinsBeard.Builder().build(context) private val merlinsBeard = MerlinsBeard.Builder().build(context)
private val listeners = Collections.synchronizedList(ArrayList<Listener>()) private val listeners = ArrayList<Listener>()


init { init {
merlin.bind() merlin.bind()
merlin.registerDisconnectable { merlin.registerDisconnectable {
Timber.v("On Disconnect") Timber.v("On Disconnect")
listeners.forEach { val localListeners = Collections.synchronizedList(listeners)
localListeners.forEach {
it.onDisconnect() it.onDisconnect()
} }
} }
merlin.registerConnectable { merlin.registerConnectable {
Timber.v("On Connect") Timber.v("On Connect")
listeners.forEach { val localListeners = Collections.synchronizedList(listeners)
localListeners.forEach {
it.onConnect() it.onConnect()
} }
} }
} }


suspend fun waitUntilConnected() {
if (isConnected()) {
return
} else {
suspendCoroutine<Unit> { continuation ->
register(object : Listener {
override fun onConnect() {
unregister(this)
continuation.resume(Unit)
}
})
}
}
}

fun register(listener: Listener) { fun register(listener: Listener) {
listeners.add(listener) listeners.add(listener)
} }

View File

@ -20,7 +20,7 @@ import im.vector.matrix.android.api.MatrixCallback
import im.vector.matrix.android.api.session.cache.CacheService import im.vector.matrix.android.api.session.cache.CacheService
import im.vector.matrix.android.internal.di.SessionDatabase import im.vector.matrix.android.internal.di.SessionDatabase
import im.vector.matrix.android.internal.task.TaskExecutor import im.vector.matrix.android.internal.task.TaskExecutor
import im.vector.matrix.android.internal.task.toConfigurableTask import im.vector.matrix.android.internal.task.configureWith
import javax.inject.Inject import javax.inject.Inject


internal class DefaultCacheService @Inject constructor(@SessionDatabase internal class DefaultCacheService @Inject constructor(@SessionDatabase
@ -30,8 +30,9 @@ internal class DefaultCacheService @Inject constructor(@SessionDatabase
override fun clearCache(callback: MatrixCallback<Unit>) { override fun clearCache(callback: MatrixCallback<Unit>) {
taskExecutor.cancelAll() taskExecutor.cancelAll()
clearCacheTask clearCacheTask
.toConfigurableTask() .configureWith {
.dispatchTo(callback) this.callback = callback
}
.executeBy(taskExecutor) .executeBy(taskExecutor)
} }
} }

View File

@ -83,9 +83,10 @@ internal class DefaultPushRuleService @Inject constructor(


override fun updatePushRuleEnableStatus(kind: String, pushRule: PushRule, enabled: Boolean, callback: MatrixCallback<Unit>): Cancelable { override fun updatePushRuleEnableStatus(kind: String, pushRule: PushRule, enabled: Boolean, callback: MatrixCallback<Unit>): Cancelable {
return updatePushRuleEnableStatusTask return updatePushRuleEnableStatusTask
.configureWith(UpdatePushRuleEnableStatusTask.Params(kind, pushRule, enabled)) .configureWith(UpdatePushRuleEnableStatusTask.Params(kind, pushRule, enabled)) {
this.callback = callback
}
// TODO Fetch the rules // TODO Fetch the rules
.dispatchTo(callback)
.executeBy(taskExecutor) .executeBy(taskExecutor)
} }



View File

@ -29,7 +29,6 @@ import im.vector.matrix.android.internal.database.model.PusherEntity
import im.vector.matrix.android.internal.database.query.where import im.vector.matrix.android.internal.database.query.where
import im.vector.matrix.android.internal.task.TaskExecutor import im.vector.matrix.android.internal.task.TaskExecutor
import im.vector.matrix.android.internal.task.configureWith import im.vector.matrix.android.internal.task.configureWith
import im.vector.matrix.android.internal.task.toConfigurableTask
import im.vector.matrix.android.internal.worker.WorkManagerUtil import im.vector.matrix.android.internal.worker.WorkManagerUtil
import im.vector.matrix.android.internal.worker.WorkManagerUtil.matrixOneTimeWorkRequestBuilder import im.vector.matrix.android.internal.worker.WorkManagerUtil.matrixOneTimeWorkRequestBuilder
import im.vector.matrix.android.internal.worker.WorkerParamsFactory import im.vector.matrix.android.internal.worker.WorkerParamsFactory
@ -50,7 +49,7 @@ internal class DefaultPusherService @Inject constructor(


override fun refreshPushers() { override fun refreshPushers() {
getPusherTask getPusherTask
.toConfigurableTask() .configureWith()
.executeBy(taskExecutor) .executeBy(taskExecutor)
} }


@ -85,8 +84,9 @@ internal class DefaultPusherService @Inject constructor(
override fun removeHttpPusher(pushkey: String, appId: String, callback: MatrixCallback<Unit>) { override fun removeHttpPusher(pushkey: String, appId: String, callback: MatrixCallback<Unit>) {
val params = RemovePusherTask.Params(sessionParam.credentials.userId, pushkey, appId) val params = RemovePusherTask.Params(sessionParam.credentials.userId, pushkey, appId)
removePusherTask removePusherTask
.configureWith(params) .configureWith(params) {
.dispatchTo(callback) this.callback = callback
}
//.enableRetry() ?? //.enableRetry() ??
.executeBy(taskExecutor) .executeBy(taskExecutor)
} }

View File

@ -18,7 +18,6 @@ package im.vector.matrix.android.internal.session.pushers


import com.zhuinden.monarchy.Monarchy import com.zhuinden.monarchy.Monarchy
import im.vector.matrix.android.api.session.pushers.PusherState import im.vector.matrix.android.api.session.pushers.PusherState
import im.vector.matrix.android.internal.database.awaitTransaction
import im.vector.matrix.android.internal.database.mapper.asDomain import im.vector.matrix.android.internal.database.mapper.asDomain
import im.vector.matrix.android.internal.database.model.PusherEntity import im.vector.matrix.android.internal.database.model.PusherEntity
import im.vector.matrix.android.internal.database.query.where import im.vector.matrix.android.internal.database.query.where
@ -40,12 +39,13 @@ internal class DefaultRemovePusherTask @Inject constructor(
) : RemovePusherTask { ) : RemovePusherTask {


override suspend fun execute(params: RemovePusherTask.Params) { override suspend fun execute(params: RemovePusherTask.Params) {
val existing = Realm.getInstance(monarchy.realmConfiguration).use { realm -> monarchy.awaitTransaction { realm ->
val existingEntity = PusherEntity.where(realm, params.userId, params.pushKey).findFirst() val existingEntity = PusherEntity.where(realm, params.userId, params.pushKey).findFirst()
realm.awaitTransaction {
existingEntity?.state = PusherState.UNREGISTERING existingEntity?.state = PusherState.UNREGISTERING
} }
existingEntity?.asDomain()
val existing = Realm.getInstance(monarchy.realmConfiguration).use { realm ->
PusherEntity.where(realm, params.userId, params.pushKey).findFirst()?.asDomain()
} ?: throw Exception("No existing pusher") } ?: throw Exception("No existing pusher")


val deleteBody = JsonPusher( val deleteBody = JsonPusher(

View File

@ -27,7 +27,6 @@ import im.vector.matrix.android.internal.session.room.directory.GetThirdPartyPro
import im.vector.matrix.android.internal.session.room.membership.joining.JoinRoomTask import im.vector.matrix.android.internal.session.room.membership.joining.JoinRoomTask
import im.vector.matrix.android.internal.task.TaskExecutor import im.vector.matrix.android.internal.task.TaskExecutor
import im.vector.matrix.android.internal.task.configureWith import im.vector.matrix.android.internal.task.configureWith
import im.vector.matrix.android.internal.task.toConfigurableTask
import javax.inject.Inject import javax.inject.Inject


internal class DefaultRoomDirectoryService @Inject constructor(private val getPublicRoomTask: GetPublicRoomTask, internal class DefaultRoomDirectoryService @Inject constructor(private val getPublicRoomTask: GetPublicRoomTask,
@ -39,22 +38,25 @@ internal class DefaultRoomDirectoryService @Inject constructor(private val getPu
publicRoomsParams: PublicRoomsParams, publicRoomsParams: PublicRoomsParams,
callback: MatrixCallback<PublicRoomsResponse>): Cancelable { callback: MatrixCallback<PublicRoomsResponse>): Cancelable {
return getPublicRoomTask return getPublicRoomTask
.configureWith(GetPublicRoomTask.Params(server, publicRoomsParams)) .configureWith(GetPublicRoomTask.Params(server, publicRoomsParams)) {
.dispatchTo(callback) this.callback = callback
}
.executeBy(taskExecutor) .executeBy(taskExecutor)
} }


override fun joinRoom(roomId: String, callback: MatrixCallback<Unit>): Cancelable { override fun joinRoom(roomId: String, callback: MatrixCallback<Unit>): Cancelable {
return joinRoomTask return joinRoomTask
.configureWith(JoinRoomTask.Params(roomId)) .configureWith(JoinRoomTask.Params(roomId)) {
.dispatchTo(callback) this.callback = callback
}
.executeBy(taskExecutor) .executeBy(taskExecutor)
} }


override fun getThirdPartyProtocol(callback: MatrixCallback<Map<String, ThirdPartyProtocol>>): Cancelable { override fun getThirdPartyProtocol(callback: MatrixCallback<Map<String, ThirdPartyProtocol>>): Cancelable {
return getThirdPartyProtocolsTask return getThirdPartyProtocolsTask
.toConfigurableTask() .configureWith {
.dispatchTo(callback) this.callback = callback
}
.executeBy(taskExecutor) .executeBy(taskExecutor)
} }
} }

View File

@ -46,8 +46,9 @@ internal class DefaultRoomService @Inject constructor(private val monarchy: Mona


override fun createRoom(createRoomParams: CreateRoomParams, callback: MatrixCallback<String>): Cancelable { override fun createRoom(createRoomParams: CreateRoomParams, callback: MatrixCallback<String>): Cancelable {
return createRoomTask return createRoomTask
.configureWith(createRoomParams) .configureWith(createRoomParams) {
.dispatchTo(callback) this.callback = callback
}
.executeBy(taskExecutor) .executeBy(taskExecutor)
} }


@ -74,8 +75,9 @@ internal class DefaultRoomService @Inject constructor(private val monarchy: Mona


override fun joinRoom(roomId: String, viaServers: List<String>, callback: MatrixCallback<Unit>): Cancelable { override fun joinRoom(roomId: String, viaServers: List<String>, callback: MatrixCallback<Unit>): Cancelable {
return joinRoomTask return joinRoomTask
.configureWith(JoinRoomTask.Params(roomId, viaServers)) .configureWith(JoinRoomTask.Params(roomId, viaServers)) {
.dispatchTo(callback) this.callback = callback
}
.executeBy(taskExecutor) .executeBy(taskExecutor)
} }
} }

View File

@ -44,8 +44,10 @@ internal class DefaultMembershipService @Inject constructor(private val roomId:


override fun loadRoomMembersIfNeeded(matrixCallback: MatrixCallback<Unit>): Cancelable { override fun loadRoomMembersIfNeeded(matrixCallback: MatrixCallback<Unit>): Cancelable {
val params = LoadRoomMembersTask.Params(roomId, Membership.LEAVE) val params = LoadRoomMembersTask.Params(roomId, Membership.LEAVE)
return loadRoomMembersTask.configureWith(params) return loadRoomMembersTask
.dispatchTo(matrixCallback) .configureWith(params) {
this.callback = matrixCallback
}
.executeBy(taskExecutor) .executeBy(taskExecutor)
} }


@ -77,22 +79,28 @@ internal class DefaultMembershipService @Inject constructor(private val roomId:


override fun invite(userId: String, callback: MatrixCallback<Unit>): Cancelable { override fun invite(userId: String, callback: MatrixCallback<Unit>): Cancelable {
val params = InviteTask.Params(roomId, userId) val params = InviteTask.Params(roomId, userId)
return inviteTask.configureWith(params) return inviteTask
.dispatchTo(callback) .configureWith(params) {
this.callback = callback
}
.executeBy(taskExecutor) .executeBy(taskExecutor)
} }


override fun join(viaServers: List<String>, callback: MatrixCallback<Unit>): Cancelable { override fun join(viaServers: List<String>, callback: MatrixCallback<Unit>): Cancelable {
val params = JoinRoomTask.Params(roomId, viaServers) val params = JoinRoomTask.Params(roomId, viaServers)
return joinTask.configureWith(params) return joinTask
.dispatchTo(callback) .configureWith(params) {
this.callback = callback
}
.executeBy(taskExecutor) .executeBy(taskExecutor)
} }


override fun leave(callback: MatrixCallback<Unit>): Cancelable { override fun leave(callback: MatrixCallback<Unit>): Cancelable {
val params = LeaveRoomTask.Params(roomId) val params = LeaveRoomTask.Params(roomId)
return leaveRoomTask.configureWith(params) return leaveRoomTask
.dispatchTo(callback) .configureWith(params) {
this.callback = callback
}
.executeBy(taskExecutor) .executeBy(taskExecutor)
} }
} }

View File

@ -37,17 +37,29 @@ internal class DefaultReadService @Inject constructor(private val roomId: String


override fun markAllAsRead(callback: MatrixCallback<Unit>) { override fun markAllAsRead(callback: MatrixCallback<Unit>) {
val params = SetReadMarkersTask.Params(roomId, markAllAsRead = true) val params = SetReadMarkersTask.Params(roomId, markAllAsRead = true)
setReadMarkersTask.configureWith(params).dispatchTo(callback).executeBy(taskExecutor) setReadMarkersTask
.configureWith(params) {
this.callback = callback
}
.executeBy(taskExecutor)
} }


override fun setReadReceipt(eventId: String, callback: MatrixCallback<Unit>) { override fun setReadReceipt(eventId: String, callback: MatrixCallback<Unit>) {
val params = SetReadMarkersTask.Params(roomId, fullyReadEventId = null, readReceiptEventId = eventId) val params = SetReadMarkersTask.Params(roomId, fullyReadEventId = null, readReceiptEventId = eventId)
setReadMarkersTask.configureWith(params).dispatchTo(callback).executeBy(taskExecutor) setReadMarkersTask
.configureWith(params) {
this.callback = callback
}
.executeBy(taskExecutor)
} }


override fun setReadMarker(fullyReadEventId: String, callback: MatrixCallback<Unit>) { override fun setReadMarker(fullyReadEventId: String, callback: MatrixCallback<Unit>) {
val params = SetReadMarkersTask.Params(roomId, fullyReadEventId = fullyReadEventId, readReceiptEventId = null) val params = SetReadMarkersTask.Params(roomId, fullyReadEventId = fullyReadEventId, readReceiptEventId = null)
setReadMarkersTask.configureWith(params).dispatchTo(callback).executeBy(taskExecutor) setReadMarkersTask
.configureWith(params) {
this.callback = callback
}
.executeBy(taskExecutor)
} }





View File

@ -80,9 +80,7 @@ internal class DefaultRelationService @Inject constructor(private val context: C
reaction, reaction,
myUserId myUserId
) )
findReactionEventForUndoTask.configureWith(params) val callback = object : MatrixCallback<FindReactionEventForUndoTask.Result> {
.enableRetry()
.dispatchTo(object : MatrixCallback<FindReactionEventForUndoTask.Result> {
override fun onSuccess(data: FindReactionEventForUndoTask.Result) { override fun onSuccess(data: FindReactionEventForUndoTask.Result) {
if (data.redactEventId == null) { if (data.redactEventId == null) {
Timber.w("Cannot find reaction to undo (not yet synced?)") Timber.w("Cannot find reaction to undo (not yet synced?)")
@ -99,9 +97,13 @@ internal class DefaultRelationService @Inject constructor(private val context: C


} }
} }
}) }
findReactionEventForUndoTask
.configureWith(params) {
this.retryCount = Int.MAX_VALUE
this.callback = callback
}
.executeBy(taskExecutor) .executeBy(taskExecutor)

} }


//TODO duplicate with send service? //TODO duplicate with send service?
@ -167,8 +169,10 @@ internal class DefaultRelationService @Inject constructor(private val context: C


override fun fetchEditHistory(eventId: String, callback: MatrixCallback<List<Event>>) { override fun fetchEditHistory(eventId: String, callback: MatrixCallback<List<Event>>) {
val params = FetchEditHistoryTask.Params(roomId, cryptoService.isRoomEncrypted(roomId), eventId) val params = FetchEditHistoryTask.Params(roomId, cryptoService.isRoomEncrypted(roomId), eventId)
fetchEditHistoryTask.configureWith(params) fetchEditHistoryTask
.dispatchTo(callback) .configureWith(params) {
this.callback = callback
}
.executeBy(taskExecutor) .executeBy(taskExecutor)
} }



View File

@ -51,8 +51,10 @@ internal class DefaultStateService @Inject constructor(private val roomId: Strin
)) ))




sendStateTask.configureWith(params) sendStateTask
.dispatchTo(callback) .configureWith(params) {
this.callback = callback
}
.executeBy(taskExecutor) .executeBy(taskExecutor)
} }



View File

@ -29,6 +29,7 @@ import im.vector.matrix.android.internal.database.query.findIncludingEvent
import im.vector.matrix.android.internal.database.query.findLastLiveChunkFromRoom import im.vector.matrix.android.internal.database.query.findLastLiveChunkFromRoom
import im.vector.matrix.android.internal.database.query.where import im.vector.matrix.android.internal.database.query.where
import im.vector.matrix.android.internal.database.query.whereInRoom import im.vector.matrix.android.internal.database.query.whereInRoom
import im.vector.matrix.android.internal.task.TaskConstraints
import im.vector.matrix.android.internal.task.TaskExecutor import im.vector.matrix.android.internal.task.TaskExecutor
import im.vector.matrix.android.internal.task.configureWith import im.vector.matrix.android.internal.task.configureWith
import im.vector.matrix.android.internal.util.Debouncer import im.vector.matrix.android.internal.util.Debouncer
@ -405,9 +406,11 @@ internal class DefaultTimeline(
limit = limit) limit = limit)


Timber.v("Should fetch $limit items $direction") Timber.v("Should fetch $limit items $direction")
cancelableBag += paginationTask.configureWith(params) cancelableBag += paginationTask
.enableRetry() .configureWith(params) {
.dispatchTo(object : MatrixCallback<TokenChunkEventPersistor.Result> { this.retryCount = Int.MAX_VALUE
this.constraints = TaskConstraints(connectedToNetwork = true)
this.callback = object : MatrixCallback<TokenChunkEventPersistor.Result> {
override fun onSuccess(data: TokenChunkEventPersistor.Result) { override fun onSuccess(data: TokenChunkEventPersistor.Result) {
if (data == TokenChunkEventPersistor.Result.SUCCESS) { if (data == TokenChunkEventPersistor.Result.SUCCESS) {
Timber.v("Success fetching $limit items $direction from pagination request") Timber.v("Success fetching $limit items $direction from pagination request")
@ -422,7 +425,8 @@ internal class DefaultTimeline(
override fun onFailure(failure: Throwable) { override fun onFailure(failure: Throwable) {
Timber.v("Failure fetching $limit items $direction from pagination request") Timber.v("Failure fetching $limit items $direction from pagination request")
} }
}) }
}
.executeBy(taskExecutor) .executeBy(taskExecutor)
} }



View File

@ -19,7 +19,7 @@ package im.vector.matrix.android.internal.session.signout
import im.vector.matrix.android.api.MatrixCallback import im.vector.matrix.android.api.MatrixCallback
import im.vector.matrix.android.api.session.signout.SignOutService import im.vector.matrix.android.api.session.signout.SignOutService
import im.vector.matrix.android.internal.task.TaskExecutor import im.vector.matrix.android.internal.task.TaskExecutor
import im.vector.matrix.android.internal.task.toConfigurableTask import im.vector.matrix.android.internal.task.configureWith
import javax.inject.Inject import javax.inject.Inject


internal class DefaultSignOutService @Inject constructor(private val signOutTask: SignOutTask, internal class DefaultSignOutService @Inject constructor(private val signOutTask: SignOutTask,
@ -27,8 +27,9 @@ internal class DefaultSignOutService @Inject constructor(private val signOutTask


override fun signOut(callback: MatrixCallback<Unit>) { override fun signOut(callback: MatrixCallback<Unit>) {
signOutTask signOutTask
.toConfigurableTask() .configureWith {
.dispatchTo(callback) this.callback = callback
}
.executeBy(taskExecutor) .executeBy(taskExecutor)
} }



View File

@ -104,10 +104,11 @@ open class SyncService : Service() {
} else { } else {
Timber.v("Execute sync request with timeout 0") Timber.v("Execute sync request with timeout 0")
val params = SyncTask.Params(TIME_OUT) val params = SyncTask.Params(TIME_OUT)
cancelableTask = syncTask.configureWith(params) cancelableTask = syncTask
.callbackOn(TaskThread.SYNC) .configureWith(params) {
.executeOn(TaskThread.SYNC) callbackThread = TaskThread.SYNC
.dispatchTo(object : MatrixCallback<Unit> { executionThread = TaskThread.SYNC
callback = object : MatrixCallback<Unit> {
override fun onSuccess(data: Unit) { override fun onSuccess(data: Unit) {
cancelableTask = null cancelableTask = null
if (!once) { if (!once) {
@ -150,12 +151,10 @@ open class SyncService : Service() {
// No token or invalid token, stop the thread // No token or invalid token, stop the thread
stopSelf() stopSelf()
} }

} }

}
}) }
.executeBy(taskExecutor) .executeBy(taskExecutor)

} }
} }



View File

@ -102,10 +102,12 @@ internal class SyncThread @Inject constructor(private val syncTask: SyncTask,
Timber.v("[$this] Execute sync request with timeout $DEFAULT_LONG_POOL_TIMEOUT") Timber.v("[$this] Execute sync request with timeout $DEFAULT_LONG_POOL_TIMEOUT")
val latch = CountDownLatch(1) val latch = CountDownLatch(1)
val params = SyncTask.Params(DEFAULT_LONG_POOL_TIMEOUT) val params = SyncTask.Params(DEFAULT_LONG_POOL_TIMEOUT)
cancelableTask = syncTask.configureWith(params)
.callbackOn(TaskThread.SYNC) cancelableTask = syncTask.configureWith(params) {
.executeOn(TaskThread.SYNC) this.callbackThread = TaskThread.SYNC
.dispatchTo(object : MatrixCallback<Unit> { this.executionThread = TaskThread.SYNC
this.callback = object : MatrixCallback<Unit> {

override fun onSuccess(data: Unit) { override fun onSuccess(data: Unit) {
latch.countDown() latch.countDown()
} }
@ -130,12 +132,12 @@ internal class SyncThread @Inject constructor(private val syncTask: SyncTask,
// No token or invalid token, stop the thread // No token or invalid token, stop the thread
updateStateTo(SyncState.KILLING) updateStateTo(SyncState.KILLING)
} }

latch.countDown() latch.countDown()
} }

}
}) }
.executeBy(taskExecutor) .executeBy(taskExecutor)

latch.await() latch.await()
if (state is SyncState.RUNNING) { if (state is SyncState.RUNNING) {
updateStateTo(SyncState.RUNNING(afterPause = false)) updateStateTo(SyncState.RUNNING(afterPause = false))

View File

@ -113,8 +113,9 @@ internal class DefaultUserService @Inject constructor(private val monarchy: Mona
callback: MatrixCallback<List<User>>): Cancelable { callback: MatrixCallback<List<User>>): Cancelable {
val params = SearchUserTask.Params(limit, search, excludedUserIds) val params = SearchUserTask.Params(limit, search, excludedUserIds)
return searchUserTask return searchUserTask
.configureWith(params) .configureWith(params) {
.dispatchTo(callback) this.callback = callback
}
.executeBy(taskExecutor) .executeBy(taskExecutor)
} }
} }

View File

@ -18,54 +18,63 @@ package im.vector.matrix.android.internal.task


import im.vector.matrix.android.api.MatrixCallback import im.vector.matrix.android.api.MatrixCallback
import im.vector.matrix.android.api.util.Cancelable import im.vector.matrix.android.api.util.Cancelable
import java.util.*


internal fun <PARAMS, RESULT> Task<PARAMS, RESULT>.configureWith(params: PARAMS): ConfigurableTask<PARAMS, RESULT> { internal fun <PARAMS, RESULT> Task<PARAMS, RESULT>.configureWith(params: PARAMS, init: (ConfigurableTask.Builder<PARAMS, RESULT>.() -> Unit) = {}): ConfigurableTask<PARAMS, RESULT> {
return ConfigurableTask(this, params) return ConfigurableTask.Builder(this, params).apply(init).build()
} }


/** internal fun <RESULT> Task<Unit, RESULT>.configureWith(init: (ConfigurableTask.Builder<Unit, RESULT>.() -> Unit) = {}): ConfigurableTask<Unit, RESULT> {
* Convert a Task to a ConfigurableTask without parameter return configureWith(Unit, init)
*/
internal fun <RESULT> Task<Unit, RESULT>.toConfigurableTask(): ConfigurableTask<Unit, RESULT> {
return ConfigurableTask(this, Unit)
} }


internal data class ConfigurableTask<PARAMS, RESULT>( internal data class ConfigurableTask<PARAMS, RESULT>(
val task: Task<PARAMS, RESULT>, val task: Task<PARAMS, RESULT>,
val params: PARAMS, val params: PARAMS,
val callbackThread: TaskThread = TaskThread.MAIN, val id: UUID,
val executionThread: TaskThread = TaskThread.IO, val callbackThread: TaskThread,
val retryCount: Int = 0, val executionThread: TaskThread,
val callback: MatrixCallback<RESULT> = object : MatrixCallback<RESULT> {} val constraints: TaskConstraints,
val retryCount: Int,
val callback: MatrixCallback<RESULT>

) : Task<PARAMS, RESULT> { ) : Task<PARAMS, RESULT> {




class Builder<PARAMS, RESULT>(
private val task: Task<PARAMS, RESULT>,
private val params: PARAMS,
var id: UUID = UUID.randomUUID(),
var callbackThread: TaskThread = TaskThread.MAIN,
var executionThread: TaskThread = TaskThread.IO,
var constraints: TaskConstraints = TaskConstraints(),
var retryCount: Int = 0,
var callback: MatrixCallback<RESULT> = object : MatrixCallback<RESULT> {}
) {

fun build() = ConfigurableTask(
task = task,
params = params,
id = id,
callbackThread = callbackThread,
executionThread = executionThread,
constraints = constraints,
retryCount = retryCount,
callback = callback
)
}


override suspend fun execute(params: PARAMS): RESULT { override suspend fun execute(params: PARAMS): RESULT {
return task.execute(params) return task.execute(params)
} }


fun callbackOn(thread: TaskThread): ConfigurableTask<PARAMS, RESULT> {
return copy(callbackThread = thread)
}

fun executeOn(thread: TaskThread): ConfigurableTask<PARAMS, RESULT> {
return copy(executionThread = thread)
}

fun dispatchTo(matrixCallback: MatrixCallback<RESULT>): ConfigurableTask<PARAMS, RESULT> {
return copy(callback = matrixCallback)
}

fun enableRetry(retryCount: Int = Int.MAX_VALUE): ConfigurableTask<PARAMS, RESULT> {
return copy(retryCount = retryCount)
}

fun executeBy(taskExecutor: TaskExecutor): Cancelable { fun executeBy(taskExecutor: TaskExecutor): Cancelable {
return taskExecutor.execute(this) return taskExecutor.execute(this)
} }


override fun toString(): String { override fun toString(): String {
return task.javaClass.name return "${task.javaClass.name} with ID: $id"
} }


} }

View File

@ -0,0 +1,22 @@
/*

* Copyright 2019 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.

*/
package im.vector.matrix.android.internal.task

data class TaskConstraints(
val connectedToNetwork: Boolean = false
)

View File

@ -21,6 +21,7 @@ import im.vector.matrix.android.api.util.Cancelable
import im.vector.matrix.android.api.util.CancelableBag import im.vector.matrix.android.api.util.CancelableBag
import im.vector.matrix.android.internal.di.MatrixScope import im.vector.matrix.android.internal.di.MatrixScope
import im.vector.matrix.android.internal.extensions.foldToCallback import im.vector.matrix.android.internal.extensions.foldToCallback
import im.vector.matrix.android.internal.network.NetworkConnectivityChecker
import im.vector.matrix.android.internal.util.CancelableCoroutine import im.vector.matrix.android.internal.util.CancelableCoroutine
import im.vector.matrix.android.internal.util.MatrixCoroutineDispatchers import im.vector.matrix.android.internal.util.MatrixCoroutineDispatchers
import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.GlobalScope
@ -32,7 +33,8 @@ import javax.inject.Inject
import kotlin.coroutines.EmptyCoroutineContext import kotlin.coroutines.EmptyCoroutineContext


@MatrixScope @MatrixScope
internal class TaskExecutor @Inject constructor(private val coroutineDispatchers: MatrixCoroutineDispatchers) { internal class TaskExecutor @Inject constructor(private val coroutineDispatchers: MatrixCoroutineDispatchers,
private val networkConnectivityChecker: NetworkConnectivityChecker) {


private val cancelableBag = CancelableBag() private val cancelableBag = CancelableBag()


@ -41,8 +43,13 @@ internal class TaskExecutor @Inject constructor(private val coroutineDispatchers
val job = GlobalScope.launch(task.callbackThread.toDispatcher()) { val job = GlobalScope.launch(task.callbackThread.toDispatcher()) {
val resultOrFailure = runCatching { val resultOrFailure = runCatching {
withContext(task.executionThread.toDispatcher()) { withContext(task.executionThread.toDispatcher()) {
Timber.v("Executing $task on ${Thread.currentThread().name}") Timber.v("Enqueue task $task")
retry(task.retryCount) { retry(task.retryCount) {
if (task.constraints.connectedToNetwork) {
Timber.v("Waiting network for $task")
networkConnectivityChecker.waitUntilConnected()
}
Timber.v("Execute task $task on ${Thread.currentThread().name}")
task.execute(task.params) task.execute(task.params)
} }
} }
@ -74,6 +81,7 @@ internal class TaskExecutor @Inject constructor(private val coroutineDispatchers
try { try {
return block() return block()
} catch (e: Exception) { } catch (e: Exception) {
Timber.v("Retry task after $currentDelay ms")
delay(currentDelay) delay(currentDelay)
currentDelay = (currentDelay * factor).toLong().coerceAtMost(maxDelay) currentDelay = (currentDelay * factor).toLong().coerceAtMost(maxDelay)
} }