From 81d88b51fc064404f06011d6d2a62f9e12709acf Mon Sep 17 00:00:00 2001 From: Adam Brown Date: Mon, 4 Apr 2022 20:47:05 +0100 Subject: [PATCH] setting push token via background scheduler which will automatically retry --- .../kotlin/app/dapk/st/graph/AppModule.kt | 51 +++++++++++++++++-- .../dapk/st/home/BetaVersionUpgradeUseCase.kt | 4 +- features/notifications/build.gradle | 1 + .../st/notifications/NotificationsModule.kt | 4 ++ .../st/notifications/PushAndroidService.kt | 12 +++-- 5 files changed, 60 insertions(+), 12 deletions(-) diff --git a/app/src/main/kotlin/app/dapk/st/graph/AppModule.kt b/app/src/main/kotlin/app/dapk/st/graph/AppModule.kt index d4c69ac..9473221 100644 --- a/app/src/main/kotlin/app/dapk/st/graph/AppModule.kt +++ b/app/src/main/kotlin/app/dapk/st/graph/AppModule.kt @@ -32,6 +32,7 @@ import app.dapk.st.matrix.device.internal.ApiMessage import app.dapk.st.matrix.http.MatrixHttpClient import app.dapk.st.matrix.http.ktor.KtorMatrixHttpClientFactory import app.dapk.st.matrix.message.* +import app.dapk.st.matrix.push.PushService import app.dapk.st.matrix.push.installPushService import app.dapk.st.matrix.push.pushService import app.dapk.st.matrix.room.* @@ -54,6 +55,7 @@ import app.dapk.st.work.TaskRunnerModule import app.dapk.st.work.WorkModule import app.dapk.st.work.WorkScheduler import com.squareup.sqldelight.android.AndroidSqliteDriver +import io.ktor.client.features.* import kotlinx.coroutines.Dispatchers import java.time.Clock @@ -118,6 +120,7 @@ internal class AppModule(context: Application, logger: MatrixLogger) { matrixModules, domainModules, trackingModule, + workModule, imageLoaderModule, context, buildMeta, @@ -131,6 +134,7 @@ internal class FeatureModules internal constructor( private val matrixModules: MatrixModules, private val domainModules: DomainModules, private val trackingModule: TrackingModule, + private val workModule: WorkModule, imageLoaderModule: ImageLoaderModule, context: Context, buildMeta: BuildMeta, @@ -187,6 +191,7 @@ internal class FeatureModules internal constructor( imageLoaderModule.iconLoader(), storeModule.value.roomStore(), context, + workModule.workScheduler(), ) } @@ -395,7 +400,7 @@ internal class DomainModules( ) { val pushModule by unsafeLazy { PushModule(matrixModules.push, errorTracker) } - val taskRunnerModule by unsafeLazy { TaskRunnerModule(TaskRunnerAdapter(matrixModules.matrix::run)) } + val taskRunnerModule by unsafeLazy { TaskRunnerModule(TaskRunnerAdapter(matrixModules.matrix::run, AppTaskRunner(matrixModules.push))) } } class BackgroundWorkAdapter(private val workScheduler: WorkScheduler) : BackgroundScheduler { @@ -410,14 +415,50 @@ class BackgroundWorkAdapter(private val workScheduler: WorkScheduler) : Backgrou } } -class TaskRunnerAdapter(private val matrixTaskRunner: suspend (MatrixTask) -> MatrixTaskRunner.TaskResult) : TaskRunner { +class TaskRunnerAdapter( + private val matrixTaskRunner: suspend (MatrixTask) -> MatrixTaskRunner.TaskResult, + private val appTaskRunner: AppTaskRunner, +) : TaskRunner { override suspend fun run(tasks: List): List { return tasks.map { - when (val result = matrixTaskRunner(MatrixTask(it.task.type, it.task.jsonPayload))) { - is MatrixTaskRunner.TaskResult.Failure -> TaskRunner.TaskResult.Failure(it.source, canRetry = result.canRetry) - MatrixTaskRunner.TaskResult.Success -> TaskRunner.TaskResult.Success(it.source) + when { + it.task.type.startsWith("matrix") -> { + when (val result = matrixTaskRunner(MatrixTask(it.task.type, it.task.jsonPayload))) { + is MatrixTaskRunner.TaskResult.Failure -> TaskRunner.TaskResult.Failure(it.source, canRetry = result.canRetry) + MatrixTaskRunner.TaskResult.Success -> TaskRunner.TaskResult.Success(it.source) + } + } + else -> appTaskRunner.run(it) } } } } + +class AppTaskRunner( + private val pushService: PushService, +) { + + suspend fun run(workTask: TaskRunner.RunnableWorkTask): TaskRunner.TaskResult { + return when (val type = workTask.task.type) { + "push_token" -> { + runCatching { + pushService.registerPush(workTask.task.jsonPayload) + }.fold( + onSuccess = { TaskRunner.TaskResult.Success(workTask.source) }, + onFailure = { + val canRetry = if (it is ClientRequestException) { + it.response.status.value !in (400 until 500) + } else { + true + } + TaskRunner.TaskResult.Failure(workTask.source, canRetry = canRetry) + } + ) + } + else -> throw IllegalArgumentException("Unknown work type: $type") + } + + } + +} \ No newline at end of file diff --git a/features/home/src/main/kotlin/app/dapk/st/home/BetaVersionUpgradeUseCase.kt b/features/home/src/main/kotlin/app/dapk/st/home/BetaVersionUpgradeUseCase.kt index fcb2d2b..7897223 100644 --- a/features/home/src/main/kotlin/app/dapk/st/home/BetaVersionUpgradeUseCase.kt +++ b/features/home/src/main/kotlin/app/dapk/st/home/BetaVersionUpgradeUseCase.kt @@ -5,8 +5,6 @@ import app.dapk.st.domain.ApplicationPreferences import app.dapk.st.domain.ApplicationVersion import kotlinx.coroutines.runBlocking -private const val FIRST_VERSION_TO_START_COUNTING_FROM = 3 - class BetaVersionUpgradeUseCase( private val applicationPreferences: ApplicationPreferences, private val buildMeta: BuildMeta, @@ -17,7 +15,7 @@ class BetaVersionUpgradeUseCase( val previousVersion = applicationPreferences.readVersion()?.value val currentVersion = buildMeta.versionCode when (previousVersion) { - null -> currentVersion == FIRST_VERSION_TO_START_COUNTING_FROM + null -> false else -> currentVersion > previousVersion }.also { applicationPreferences.setVersion(ApplicationVersion(currentVersion)) diff --git a/features/notifications/build.gradle b/features/notifications/build.gradle index 6ccaa59..21b4bf9 100644 --- a/features/notifications/build.gradle +++ b/features/notifications/build.gradle @@ -4,6 +4,7 @@ dependencies { implementation project(":matrix:services:push") implementation project(":matrix:services:sync") implementation project(':domains:store') + implementation project(":domains:android:work") implementation project(':domains:android:push') implementation project(":domains:android:core") implementation project(":core") diff --git a/features/notifications/src/main/kotlin/app/dapk/st/notifications/NotificationsModule.kt b/features/notifications/src/main/kotlin/app/dapk/st/notifications/NotificationsModule.kt index a0561c6..e2d166a 100644 --- a/features/notifications/src/main/kotlin/app/dapk/st/notifications/NotificationsModule.kt +++ b/features/notifications/src/main/kotlin/app/dapk/st/notifications/NotificationsModule.kt @@ -9,6 +9,7 @@ import app.dapk.st.matrix.push.PushService import app.dapk.st.matrix.sync.RoomStore import app.dapk.st.matrix.sync.SyncService import app.dapk.st.push.RegisterFirebasePushTokenUseCase +import app.dapk.st.work.WorkScheduler class NotificationsModule( private val pushService: PushService, @@ -18,6 +19,7 @@ class NotificationsModule( private val iconLoader: IconLoader, private val roomStore: RoomStore, private val context: Context, + private val workScheduler: WorkScheduler, ) : ProvidableModule { fun pushUseCase() = pushService @@ -31,4 +33,6 @@ class NotificationsModule( ) private fun notificationManager() = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager + + fun workScheduler() = workScheduler } diff --git a/features/notifications/src/main/kotlin/app/dapk/st/notifications/PushAndroidService.kt b/features/notifications/src/main/kotlin/app/dapk/st/notifications/PushAndroidService.kt index 5c6a0c9..8fc6945 100644 --- a/features/notifications/src/main/kotlin/app/dapk/st/notifications/PushAndroidService.kt +++ b/features/notifications/src/main/kotlin/app/dapk/st/notifications/PushAndroidService.kt @@ -7,6 +7,7 @@ import app.dapk.st.core.log import app.dapk.st.core.module import app.dapk.st.matrix.common.EventId import app.dapk.st.matrix.common.RoomId +import app.dapk.st.work.WorkScheduler import com.google.firebase.messaging.FirebaseMessagingService import com.google.firebase.messaging.RemoteMessage import kotlinx.coroutines.* @@ -29,10 +30,13 @@ class PushAndroidService : FirebaseMessagingService() { override fun onNewToken(token: String) { log(PUSH, "new push token received") - GlobalScope.launch { - module.pushUseCase().registerPush(token) - log(PUSH, "token registered") - } + module.workScheduler().schedule( + WorkScheduler.WorkTask( + type = "push_token", + jobId = 2, + jsonPayload = token + ) + ) } override fun onMessageReceived(message: RemoteMessage) {