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 package org.matrix.android.sdk.internal.di
import android.content.Context import android.content.Context
import androidx.lifecycle.Observer
import androidx.work.Constraints import androidx.work.Constraints
import androidx.work.ListenableWorker import androidx.work.ListenableWorker
import androidx.work.NetworkType import androidx.work.NetworkType
import androidx.work.OneTimeWorkRequestBuilder import androidx.work.OneTimeWorkRequestBuilder
import androidx.work.PeriodicWorkRequestBuilder import androidx.work.PeriodicWorkRequestBuilder
import androidx.work.WorkInfo
import androidx.work.WorkManager import androidx.work.WorkManager
import androidx.work.WorkRequest 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 java.util.concurrent.TimeUnit
import javax.inject.Inject import javax.inject.Inject
@SessionScope
internal class WorkManagerProvider @Inject constructor( internal class WorkManagerProvider @Inject constructor(
context: Context, 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 private val tag = MATRIX_SDK_TAG_PREFIX + sessionId
val workManager = WorkManager.getInstance(context) val workManager = WorkManager.getInstance(context)
init {
checkIfWorkerFactoryIsSetup()
}
/** /**
* Create a OneTimeWorkRequestBuilder, with the Matrix SDK tag * 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 { companion object {
private const val MATRIX_SDK_TAG_PREFIX = "MatrixSDK-" private const val MATRIX_SDK_TAG_PREFIX = "MatrixSDK-"

View File

@ -17,6 +17,7 @@
package org.matrix.android.sdk.internal.worker package org.matrix.android.sdk.internal.worker
import android.content.Context import android.content.Context
import androidx.work.CoroutineWorker
import androidx.work.ListenableWorker import androidx.work.ListenableWorker
import androidx.work.WorkerFactory import androidx.work.WorkerFactory
import androidx.work.WorkerParameters import androidx.work.WorkerParameters
@ -51,6 +52,8 @@ internal class MatrixWorkerFactory @Inject constructor(private val sessionManage
): ListenableWorker? { ): ListenableWorker? {
Timber.d("MatrixWorkerFactory.createWorker for $workerClassName") Timber.d("MatrixWorkerFactory.createWorker for $workerClassName")
return when (workerClassName) { return when (workerClassName) {
CheckFactoryWorker::class.java.name ->
CheckFactoryWorker(appContext, workerParameters, true)
AddPusherWorker::class.java.name -> AddPusherWorker::class.java.name ->
AddPusherWorker(appContext, workerParameters, sessionManager) AddPusherWorker(appContext, workerParameters, sessionManager)
CancelGossipRequestWorker::class.java.name -> CancelGossipRequestWorker::class.java.name ->
@ -75,9 +78,29 @@ internal class MatrixWorkerFactory @Inject constructor(private val sessionManage
UpdateTrustWorker(appContext, workerParameters, sessionManager) UpdateTrustWorker(appContext, workerParameters, sessionManager)
UploadContentWorker::class.java.name -> UploadContentWorker::class.java.name ->
UploadContentWorker(appContext, workerParameters, sessionManager) 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. // Return null to delegate to the default WorkerFactory.
null 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()
}
}
}
} }