Don't re-schedule notification fetches if the cause of the failure is SessionRestorationException, since that means it'll most likely fail again

This commit is contained in:
Jorge Martín 2025-12-04 11:06:14 +01:00 committed by Jorge Martin Espinosa
parent 10224d8e01
commit 9c7ba58114
3 changed files with 17 additions and 6 deletions

View file

@ -10,7 +10,11 @@ package io.element.android.libraries.matrix.api.exception
sealed class ClientException(message: String, val details: String?, cause: Throwable? = null) : Exception(message, cause) {
class Generic(message: String, details: String?, cause: Throwable? = null) : ClientException(message, details, cause)
class MatrixApi(val kind: ErrorKind, val code: String, message: String, details: String?, cause: Throwable? = null) : ClientException(message, details, cause)
class MatrixApi(val kind: ErrorKind, val code: String, message: String, details: String?, cause: Throwable? = null) : ClientException(
message = message,
details = details,
cause = cause
)
class Other(message: String, cause: Throwable? = null) : ClientException(message, null, cause)
}

View file

@ -99,7 +99,7 @@ class DefaultNotifiableEventResolver(
): ResolvePushEventsResult {
Timber.d("Queueing notifications: $notificationEventRequests")
val client = matrixClientProvider.getOrRestore(sessionId).getOrElse {
return Result.failure(IllegalStateException("Couldn't get or restore client for session $sessionId"))
return Result.failure(it)
}
val ids = notificationEventRequests.groupBy { it.roomId }
.mapValues { (_, requests) ->

View file

@ -22,6 +22,7 @@ import io.element.android.features.networkmonitor.api.NetworkStatus
import io.element.android.libraries.core.coroutine.CoroutineDispatchers
import io.element.android.libraries.core.extensions.runCatchingExceptions
import io.element.android.libraries.di.annotations.ApplicationContext
import io.element.android.libraries.matrix.api.auth.SessionRestorationException
import io.element.android.libraries.matrix.api.core.SessionId
import io.element.android.libraries.push.api.push.NotificationEventRequest
import io.element.android.libraries.push.api.push.SyncOnNotifiableEvent
@ -63,9 +64,9 @@ class FetchNotificationsWorker(
return@withContext Result.retry()
}
val failedSyncForSessions = mutableSetOf<SessionId>()
val failedSyncForSessions = mutableMapOf<SessionId, Throwable>()
val groupedRequests = requests.groupBy { it.sessionId }
val groupedRequests = requests.groupBy { it.sessionId }.toMutableMap()
for ((sessionId, notificationRequests) in groupedRequests) {
Timber.d("Processing notification requests for session $sessionId")
eventResolver.resolveEvents(sessionId, notificationRequests)
@ -75,7 +76,7 @@ class FetchNotificationsWorker(
(queue.results as MutableSharedFlow).emit(requests to result)
},
onFailure = {
failedSyncForSessions += sessionId
failedSyncForSessions[sessionId] = it
Timber.e(it, "Failed to resolve notification events for session $sessionId")
}
)
@ -83,7 +84,13 @@ class FetchNotificationsWorker(
// If there were failures for whole sessions, we retry all their requests
if (failedSyncForSessions.isNotEmpty()) {
for (failedSessionId in failedSyncForSessions) {
@Suppress("LoopWithTooManyJumpStatements")
for ((failedSessionId, exception) in failedSyncForSessions) {
if (exception.cause is SessionRestorationException) {
Timber.e(exception, "Session $failedSessionId could not be restored, not retrying notification fetching")
groupedRequests.remove(failedSessionId)
continue
}
val requestsToRetry = groupedRequests[failedSessionId] ?: continue
Timber.d("Re-scheduling ${requestsToRetry.size} failed notification requests for session $failedSessionId")
workManagerScheduler.submit(