Throw clear error when MatrixWorkerFactory is not set up on worker configuration

This commit is contained in:
ganfra 2021-11-29 19:13:38 +01:00
parent cfaa7268a8
commit 30fe564a2c
2 changed files with 61 additions and 3 deletions

View File

@ -17,24 +17,38 @@
package org.matrix.android.sdk.internal.di
import android.content.Context
import androidx.lifecycle.Observer
import androidx.work.Constraints
import androidx.work.ListenableWorker
import androidx.work.NetworkType
import androidx.work.OneTimeWorkRequestBuilder
import androidx.work.PeriodicWorkRequestBuilder
import androidx.work.WorkInfo
import androidx.work.WorkManager
import androidx.work.WorkRequest
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
import org.matrix.android.sdk.api.MatrixCoroutineDispatchers
import org.matrix.android.sdk.internal.session.SessionScope
import org.matrix.android.sdk.internal.worker.MatrixWorkerFactory
import java.util.concurrent.TimeUnit
import javax.inject.Inject
@SessionScope
internal class WorkManagerProvider @Inject constructor(
context: Context,
@SessionId private val sessionId: String
@SessionId private val sessionId: String,
private val coroutineDispatchers: MatrixCoroutineDispatchers,
private val sessionScope: CoroutineScope
) {
private val tag = MATRIX_SDK_TAG_PREFIX + sessionId
val workManager = WorkManager.getInstance(context)
init {
checkIfWorkerFactoryIsSetup()
}
/**
* Create a OneTimeWorkRequestBuilder, with the Matrix SDK tag
*/
@ -60,6 +74,27 @@ internal class WorkManagerProvider @Inject constructor(
}
}
private fun checkIfWorkerFactoryIsSetup() {
sessionScope.launch(coroutineDispatchers.main) {
val checkWorkerRequest = OneTimeWorkRequestBuilder<MatrixWorkerFactory.CheckFactoryWorker>().build()
workManager.enqueue(checkWorkerRequest)
val checkWorkerLiveState = workManager.getWorkInfoByIdLiveData(checkWorkerRequest.id)
val observer = object : Observer<WorkInfo> {
override fun onChanged(workInfo: WorkInfo) {
if (workInfo.state.isFinished) {
checkWorkerLiveState.removeObserver(this)
if (workInfo.state == WorkInfo.State.FAILED) {
throw RuntimeException("MatrixWorkerFactory is not being set on your worker configuration.\n" +
"Makes sure to add it to a DelegatingWorkerFactory if you have your own factory or use it directly.\n" +
"You can grab the instance through the Matrix class.")
}
}
}
}
checkWorkerLiveState.observeForever(observer)
}
}
companion object {
private const val MATRIX_SDK_TAG_PREFIX = "MatrixSDK-"

View File

@ -17,6 +17,7 @@
package org.matrix.android.sdk.internal.worker
import android.content.Context
import androidx.work.CoroutineWorker
import androidx.work.ListenableWorker
import androidx.work.WorkerFactory
import androidx.work.WorkerParameters
@ -51,7 +52,9 @@ internal class MatrixWorkerFactory @Inject constructor(private val sessionManage
): ListenableWorker? {
Timber.d("MatrixWorkerFactory.createWorker for $workerClassName")
return when (workerClassName) {
AddPusherWorker::class.java.name ->
CheckFactoryWorker::class.java.name ->
CheckFactoryWorker(appContext, workerParameters, true)
AddPusherWorker::class.java.name ->
AddPusherWorker(appContext, workerParameters, sessionManager)
CancelGossipRequestWorker::class.java.name ->
CancelGossipRequestWorker(appContext, workerParameters, sessionManager)
@ -75,9 +78,29 @@ internal class MatrixWorkerFactory @Inject constructor(private val sessionManage
UpdateTrustWorker(appContext, workerParameters, sessionManager)
UploadContentWorker::class.java.name ->
UploadContentWorker(appContext, workerParameters, sessionManager)
else ->
else -> {
Timber.w("No worker defined on MatrixWorkerFactory for $workerClassName will delegate to default.")
// Return null to delegate to the default WorkerFactory.
null
}
}
}
/**
* This worker is launched by the factory with the isCreatedByMatrixWorkerFactory flag to true.
* If the MatrixWorkerFactory is not set up, it will default to the other constructor and it will throw
*/
class CheckFactoryWorker(context: Context, workerParameters: WorkerParameters, private val isCreatedByMatrixWorkerFactory: Boolean) : CoroutineWorker(context, workerParameters) {
// Called by WorkManager if there is no MatrixWorkerFactory
constructor(context: Context, workerParameters: WorkerParameters) : this(context, workerParameters, isCreatedByMatrixWorkerFactory = false)
override suspend fun doWork(): Result {
return if (!isCreatedByMatrixWorkerFactory) {
Result.failure()
} else {
Result.success()
}
}
}
}