mirror of
https://github.com/SchildiChat/SchildiChat-android.git
synced 2024-11-23 01:45:52 +03:00
Merge pull request #1116 from vector-im/feature/worker_manager
Add some documentation on Workers
This commit is contained in:
commit
cc94b6cf7d
15 changed files with 91 additions and 25 deletions
|
@ -30,6 +30,10 @@ import im.vector.matrix.android.internal.worker.getSessionComponent
|
|||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
||||
/**
|
||||
* Possible previous worker: None
|
||||
* Possible next worker : None
|
||||
*/
|
||||
internal class SendVerificationMessageWorker(context: Context,
|
||||
params: WorkerParameters)
|
||||
: CoroutineWorker(context, params) {
|
||||
|
@ -48,7 +52,7 @@ internal class SendVerificationMessageWorker(context: Context,
|
|||
lateinit var cryptoService: CryptoService
|
||||
|
||||
override suspend fun doWork(): Result {
|
||||
val errorOutputData = Data.Builder().putBoolean("failed", true).build()
|
||||
val errorOutputData = Data.Builder().putBoolean(OUTPUT_KEY_FAILED, true).build()
|
||||
val params = WorkerParamsFactory.fromData<Params>(inputData)
|
||||
?: return Result.success(errorOutputData)
|
||||
|
||||
|
@ -76,4 +80,12 @@ internal class SendVerificationMessageWorker(context: Context,
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val OUTPUT_KEY_FAILED = "failed"
|
||||
|
||||
fun hasFailed(outputData: Data): Boolean {
|
||||
return outputData.getBoolean(SendVerificationMessageWorker.OUTPUT_KEY_FAILED, false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,6 +34,9 @@ internal interface VerificationTransport {
|
|||
onErrorReason: CancelCode,
|
||||
onDone: (() -> Unit)?)
|
||||
|
||||
/**
|
||||
* @param callback will be called with eventId and ValidVerificationInfoRequest in case of success
|
||||
*/
|
||||
fun sendVerificationRequest(supportedMethods: List<String>,
|
||||
localId: String,
|
||||
otherUserId: String,
|
||||
|
|
|
@ -115,7 +115,7 @@ internal class VerificationTransportRoomMessage(
|
|||
?.filter { it.state == WorkInfo.State.SUCCEEDED }
|
||||
?.firstOrNull { it.id == enqueueInfo.second }
|
||||
?.let { wInfo ->
|
||||
if (wInfo.outputData.getBoolean("failed", false)) {
|
||||
if (SendVerificationMessageWorker.hasFailed(wInfo.outputData)) {
|
||||
Timber.e("## SAS verification [${tx?.transactionId}] failed to send verification message in state : ${tx?.state}")
|
||||
tx?.cancel(onErrorReason)
|
||||
} else {
|
||||
|
@ -196,12 +196,15 @@ internal class VerificationTransportRoomMessage(
|
|||
?.filter { it.state == WorkInfo.State.SUCCEEDED }
|
||||
?.firstOrNull { it.id == workRequest.id }
|
||||
?.let { wInfo ->
|
||||
if (wInfo.outputData.getBoolean("failed", false)) {
|
||||
if (SendVerificationMessageWorker.hasFailed(wInfo.outputData)) {
|
||||
callback(null, null)
|
||||
} else if (wInfo.outputData.getString(localId) != null) {
|
||||
callback(wInfo.outputData.getString(localId), validInfo)
|
||||
} else {
|
||||
callback(null, null)
|
||||
val eventId = wInfo.outputData.getString(localId)
|
||||
if (eventId != null) {
|
||||
callback(eventId, validInfo)
|
||||
} else {
|
||||
callback(null, null)
|
||||
}
|
||||
}
|
||||
workLiveData.removeObserver(this)
|
||||
}
|
||||
|
|
|
@ -46,6 +46,10 @@ private data class NewImageAttributes(
|
|||
val newFileSize: Int
|
||||
)
|
||||
|
||||
/**
|
||||
* Possible previous worker: None
|
||||
* Possible next worker : Always [MultipleEventSendingDispatcherWorker]
|
||||
*/
|
||||
internal class UploadContentWorker(val context: Context, params: WorkerParameters) : CoroutineWorker(context, params) {
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
|
@ -64,12 +68,14 @@ internal class UploadContentWorker(val context: Context, params: WorkerParameter
|
|||
override suspend fun doWork(): Result {
|
||||
val params = WorkerParamsFactory.fromData<Params>(inputData)
|
||||
?: return Result.success()
|
||||
.also { Timber.e("Unable to parse work parameters") }
|
||||
|
||||
Timber.v("Starting upload media work with params $params")
|
||||
|
||||
if (params.lastFailureMessage != null) {
|
||||
// Transmit the error
|
||||
Timber.v("Stop upload media work due to input failure")
|
||||
return Result.success(inputData)
|
||||
.also { Timber.e("Work cancelled due to input error from parent") }
|
||||
}
|
||||
|
||||
// Just defensive code to ensure that we never have an uncaught exception that could break the queue
|
||||
|
|
|
@ -23,8 +23,13 @@ import com.squareup.moshi.JsonClass
|
|||
import im.vector.matrix.android.internal.worker.SessionWorkerParams
|
||||
import im.vector.matrix.android.internal.worker.WorkerParamsFactory
|
||||
import im.vector.matrix.android.internal.worker.getSessionComponent
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
||||
/**
|
||||
* Possible previous worker: None
|
||||
* Possible next worker : None
|
||||
*/
|
||||
internal class GetGroupDataWorker(context: Context, params: WorkerParameters) : CoroutineWorker(context, params) {
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
|
@ -39,6 +44,7 @@ internal class GetGroupDataWorker(context: Context, params: WorkerParameters) :
|
|||
override suspend fun doWork(): Result {
|
||||
val params = WorkerParamsFactory.fromData<Params>(inputData)
|
||||
?: return Result.failure()
|
||||
.also { Timber.e("Unable to parse work parameters") }
|
||||
|
||||
val sessionComponent = getSessionComponent(params.sessionId) ?: return Result.success()
|
||||
sessionComponent.inject(this)
|
||||
|
|
|
@ -69,13 +69,13 @@ internal class GroupSummaryUpdater @Inject constructor(
|
|||
|
||||
val workData = WorkerParamsFactory.toData(getGroupDataWorkerParams)
|
||||
|
||||
val sendWork = workManagerProvider.matrixOneTimeWorkRequestBuilder<GetGroupDataWorker>()
|
||||
val getGroupWork = workManagerProvider.matrixOneTimeWorkRequestBuilder<GetGroupDataWorker>()
|
||||
.setInputData(workData)
|
||||
.setConstraints(WorkManagerProvider.workConstraints)
|
||||
.build()
|
||||
|
||||
workManagerProvider.workManager
|
||||
.beginUniqueWork(GET_GROUP_DATA_WORKER, ExistingWorkPolicy.APPEND, sendWork)
|
||||
.beginUniqueWork(GET_GROUP_DATA_WORKER, ExistingWorkPolicy.APPEND, getGroupWork)
|
||||
.enqueue()
|
||||
}
|
||||
|
||||
|
|
|
@ -31,6 +31,7 @@ import im.vector.matrix.android.internal.worker.SessionWorkerParams
|
|||
import im.vector.matrix.android.internal.worker.WorkerParamsFactory
|
||||
import im.vector.matrix.android.internal.worker.getSessionComponent
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
||||
internal class AddHttpPusherWorker(context: Context, params: WorkerParameters)
|
||||
|
@ -50,6 +51,7 @@ internal class AddHttpPusherWorker(context: Context, params: WorkerParameters)
|
|||
override suspend fun doWork(): Result {
|
||||
val params = WorkerParamsFactory.fromData<Params>(inputData)
|
||||
?: return Result.failure()
|
||||
.also { Timber.e("Unable to parse work parameters") }
|
||||
|
||||
val sessionComponent = getSessionComponent(params.sessionId) ?: return Result.success()
|
||||
sessionComponent.inject(this)
|
||||
|
|
|
@ -31,6 +31,7 @@ import im.vector.matrix.android.internal.worker.SessionWorkerParams
|
|||
import im.vector.matrix.android.internal.worker.WorkerParamsFactory
|
||||
import im.vector.matrix.android.internal.worker.getSessionComponent
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
||||
// TODO This is not used. Delete?
|
||||
|
@ -51,10 +52,12 @@ internal class SendRelationWorker(context: Context, params: WorkerParameters) :
|
|||
override suspend fun doWork(): Result {
|
||||
val params = WorkerParamsFactory.fromData<Params>(inputData)
|
||||
?: return Result.failure()
|
||||
.also { Timber.e("Unable to parse work parameters") }
|
||||
|
||||
if (params.lastFailureMessage != null) {
|
||||
// Transmit the error
|
||||
return Result.success(inputData)
|
||||
.also { Timber.e("Work cancelled due to input error from parent") }
|
||||
}
|
||||
|
||||
val sessionComponent = getSessionComponent(params.sessionId) ?: return Result.success()
|
||||
|
|
|
@ -228,7 +228,7 @@ internal class DefaultSendService @AssistedInject constructor(
|
|||
keys.forEach { isRoomEncrypted ->
|
||||
// Should never be empty
|
||||
val localEchoes = get(isRoomEncrypted).orEmpty()
|
||||
val uploadWork = createUploadMediaWork(localEchoes, attachment, isRoomEncrypted, compressBeforeSending, startChain = true)
|
||||
val uploadWork = createUploadMediaWork(localEchoes, attachment, isRoomEncrypted, compressBeforeSending)
|
||||
|
||||
val dispatcherWork = createMultipleEventDispatcherWork(isRoomEncrypted)
|
||||
|
||||
|
@ -293,14 +293,13 @@ internal class DefaultSendService @AssistedInject constructor(
|
|||
private fun createUploadMediaWork(allLocalEchos: List<Event>,
|
||||
attachment: ContentAttachmentData,
|
||||
isRoomEncrypted: Boolean,
|
||||
compressBeforeSending: Boolean,
|
||||
startChain: Boolean): OneTimeWorkRequest {
|
||||
compressBeforeSending: Boolean): OneTimeWorkRequest {
|
||||
val uploadMediaWorkerParams = UploadContentWorker.Params(sessionId, allLocalEchos, attachment, isRoomEncrypted, compressBeforeSending)
|
||||
val uploadWorkData = WorkerParamsFactory.toData(uploadMediaWorkerParams)
|
||||
|
||||
return workManagerProvider.matrixOneTimeWorkRequestBuilder<UploadContentWorker>()
|
||||
.setConstraints(WorkManagerProvider.workConstraints)
|
||||
.startChain(startChain)
|
||||
.startChain(true)
|
||||
.setInputData(uploadWorkData)
|
||||
.setBackoffCriteria(BackoffPolicy.LINEAR, WorkManagerProvider.BACKOFF_DELAY, TimeUnit.MILLISECONDS)
|
||||
.build()
|
||||
|
|
|
@ -35,6 +35,10 @@ import im.vector.matrix.android.internal.worker.getSessionComponent
|
|||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
||||
/**
|
||||
* Possible previous worker: None
|
||||
* Possible next worker : Always [SendEventWorker]
|
||||
*/
|
||||
internal class EncryptEventWorker(context: Context, params: WorkerParameters)
|
||||
: CoroutineWorker(context, params) {
|
||||
|
||||
|
@ -53,14 +57,14 @@ internal class EncryptEventWorker(context: Context, params: WorkerParameters)
|
|||
override suspend fun doWork(): Result {
|
||||
Timber.v("Start Encrypt work")
|
||||
val params = WorkerParamsFactory.fromData<Params>(inputData)
|
||||
?: return Result.success().also {
|
||||
Timber.e("Work cancelled due to input error from parent")
|
||||
}
|
||||
?: return Result.success()
|
||||
.also { Timber.e("Unable to parse work parameters") }
|
||||
|
||||
Timber.v("Start Encrypt work for event ${params.event.eventId}")
|
||||
if (params.lastFailureMessage != null) {
|
||||
// Transmit the error
|
||||
return Result.success(inputData)
|
||||
.also { Timber.e("Work cancelled due to input error from parent") }
|
||||
}
|
||||
|
||||
val sessionComponent = getSessionComponent(params.sessionId) ?: return Result.success()
|
||||
|
|
|
@ -25,6 +25,7 @@ import com.squareup.moshi.JsonClass
|
|||
import im.vector.matrix.android.api.session.events.model.Event
|
||||
import im.vector.matrix.android.api.session.room.send.SendState
|
||||
import im.vector.matrix.android.internal.di.WorkManagerProvider
|
||||
import im.vector.matrix.android.internal.session.content.UploadContentWorker
|
||||
import im.vector.matrix.android.internal.session.room.timeline.TimelineSendEventWorkCommon
|
||||
import im.vector.matrix.android.internal.worker.SessionWorkerParams
|
||||
import im.vector.matrix.android.internal.worker.WorkerParamsFactory
|
||||
|
@ -36,6 +37,9 @@ import javax.inject.Inject
|
|||
|
||||
/**
|
||||
* This worker creates a new work for each events passed in parameter
|
||||
*
|
||||
* Possible previous worker: Always [UploadContentWorker]
|
||||
* Possible next worker : None, but it will post new work to send events, encrypted or not
|
||||
*/
|
||||
internal class MultipleEventSendingDispatcherWorker(context: Context, params: WorkerParameters)
|
||||
: CoroutineWorker(context, params) {
|
||||
|
@ -55,9 +59,8 @@ internal class MultipleEventSendingDispatcherWorker(context: Context, params: Wo
|
|||
override suspend fun doWork(): Result {
|
||||
Timber.v("Start dispatch sending multiple event work")
|
||||
val params = WorkerParamsFactory.fromData<Params>(inputData)
|
||||
?: return Result.success().also {
|
||||
Timber.e("Work cancelled due to input error from parent")
|
||||
}
|
||||
?: return Result.success()
|
||||
.also { Timber.e("Unable to parse work parameters") }
|
||||
|
||||
val sessionComponent = getSessionComponent(params.sessionId) ?: return Result.success()
|
||||
sessionComponent.inject(this)
|
||||
|
@ -68,6 +71,7 @@ internal class MultipleEventSendingDispatcherWorker(context: Context, params: Wo
|
|||
}
|
||||
// Transmit the error if needed?
|
||||
return Result.success(inputData)
|
||||
.also { Timber.e("Work cancelled due to input error from parent") }
|
||||
}
|
||||
|
||||
// Create a work for every event
|
||||
|
|
|
@ -26,8 +26,13 @@ import im.vector.matrix.android.internal.worker.SessionWorkerParams
|
|||
import im.vector.matrix.android.internal.worker.WorkerParamsFactory
|
||||
import im.vector.matrix.android.internal.worker.getSessionComponent
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
||||
/**
|
||||
* Possible previous worker: None
|
||||
* Possible next worker : None
|
||||
*/
|
||||
internal class RedactEventWorker(context: Context, params: WorkerParameters) : CoroutineWorker(context, params) {
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
|
@ -46,10 +51,12 @@ internal class RedactEventWorker(context: Context, params: WorkerParameters) : C
|
|||
override suspend fun doWork(): Result {
|
||||
val params = WorkerParamsFactory.fromData<Params>(inputData)
|
||||
?: return Result.failure()
|
||||
.also { Timber.e("Unable to parse work parameters") }
|
||||
|
||||
if (params.lastFailureMessage != null) {
|
||||
// Transmit the error
|
||||
return Result.success(inputData)
|
||||
.also { Timber.e("Work cancelled due to input error from parent") }
|
||||
}
|
||||
|
||||
val sessionComponent = getSessionComponent(params.sessionId) ?: return Result.success()
|
||||
|
|
|
@ -32,6 +32,10 @@ import org.greenrobot.eventbus.EventBus
|
|||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
||||
/**
|
||||
* Possible previous worker: [EncryptEventWorker] or first worker
|
||||
* Possible next worker : None
|
||||
*/
|
||||
internal class SendEventWorker(context: Context,
|
||||
params: WorkerParameters)
|
||||
: CoroutineWorker(context, params) {
|
||||
|
@ -49,9 +53,8 @@ internal class SendEventWorker(context: Context,
|
|||
|
||||
override suspend fun doWork(): Result {
|
||||
val params = WorkerParamsFactory.fromData<Params>(inputData)
|
||||
?: return Result.success().also {
|
||||
Timber.e("Work cancelled due to input error from parent")
|
||||
}
|
||||
?: return Result.success()
|
||||
.also { Timber.e("Unable to parse work parameters") }
|
||||
|
||||
val sessionComponent = getSessionComponent(params.sessionId) ?: return Result.success()
|
||||
sessionComponent.inject(this)
|
||||
|
@ -65,6 +68,7 @@ internal class SendEventWorker(context: Context,
|
|||
localEchoUpdater.updateSendState(event.eventId, SendState.UNDELIVERED)
|
||||
// Transmit the error
|
||||
return Result.success(inputData)
|
||||
.also { Timber.e("Work cancelled due to input error from parent") }
|
||||
}
|
||||
return try {
|
||||
sendEvent(event)
|
||||
|
|
|
@ -35,6 +35,10 @@ import javax.inject.Inject
|
|||
|
||||
private const val DEFAULT_LONG_POOL_TIMEOUT = 0L
|
||||
|
||||
/**
|
||||
* Possible previous worker: None
|
||||
* Possible next worker : None
|
||||
*/
|
||||
internal class SyncWorker(context: Context,
|
||||
workerParameters: WorkerParameters
|
||||
) : CoroutineWorker(context, workerParameters) {
|
||||
|
@ -53,7 +57,10 @@ internal class SyncWorker(context: Context,
|
|||
|
||||
override suspend fun doWork(): Result {
|
||||
Timber.i("Sync work starting")
|
||||
val params = WorkerParamsFactory.fromData<Params>(inputData) ?: return Result.success()
|
||||
val params = WorkerParamsFactory.fromData<Params>(inputData)
|
||||
?: return Result.success()
|
||||
.also { Timber.e("Unable to parse work parameters") }
|
||||
|
||||
val sessionComponent = getSessionComponent(params.sessionId) ?: return Result.success()
|
||||
sessionComponent.inject(this)
|
||||
return runCatching {
|
||||
|
@ -76,7 +83,6 @@ internal class SyncWorker(context: Context,
|
|||
}
|
||||
|
||||
companion object {
|
||||
|
||||
private const val BG_SYNC_WORK_NAME = "BG_SYNCP"
|
||||
|
||||
fun requireBackgroundSync(workManagerProvider: WorkManagerProvider, sessionId: String, serverTimeout: Long = 0) {
|
||||
|
|
|
@ -16,9 +16,16 @@
|
|||
|
||||
package im.vector.matrix.android.internal.worker
|
||||
|
||||
/**
|
||||
* Note about the Worker usage:
|
||||
* The workers we chain, or when using the append strategy, should never return Result.Failure(), else the chain will be broken forever
|
||||
*/
|
||||
interface SessionWorkerParams {
|
||||
val sessionId: String
|
||||
|
||||
// Null is no error occurs. When chaining Workers, first step is to check that there is no lastFailureMessage from the previous workers
|
||||
/**
|
||||
* Null when no error occurs. When chaining Workers, first step is to check that there is no lastFailureMessage from the previous workers
|
||||
* If it is the case, the worker should just transmit the error and shouldn't do anything else
|
||||
*/
|
||||
val lastFailureMessage: String?
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue