mirror of
https://github.com/Novaloop-AG/element-x-android.git
synced 2026-10-31 16:22:49 +00:00
Write the push history off the main thread
The push history was written to the database synchronously, from the app coroutine scope which runs on the main thread, for every received push. Make PushHistoryService.onPushResult suspend and run all the database queries on the IO dispatcher. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
+26
-21
@@ -14,6 +14,7 @@ import android.os.PowerManager
|
||||
import androidx.core.content.getSystemService
|
||||
import dev.zacsweers.metro.AppScope
|
||||
import dev.zacsweers.metro.ContributesBinding
|
||||
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.core.EventId
|
||||
@@ -23,23 +24,25 @@ import io.element.android.libraries.push.impl.PushDatabase
|
||||
import io.element.android.libraries.push.impl.db.PushHistory
|
||||
import io.element.android.libraries.push.impl.db.PushRequest
|
||||
import io.element.android.services.toolbox.api.systemclock.SystemClock
|
||||
import kotlinx.coroutines.withContext
|
||||
import kotlin.time.Instant
|
||||
|
||||
@ContributesBinding(AppScope::class)
|
||||
class DefaultPushHistoryService(
|
||||
private val pushDatabase: PushDatabase,
|
||||
private val systemClock: SystemClock,
|
||||
private val dispatchers: CoroutineDispatchers,
|
||||
@ApplicationContext context: Context,
|
||||
) : PushHistoryService {
|
||||
private val powerManager = context.getSystemService<PowerManager>()
|
||||
private val packageName = context.packageName
|
||||
|
||||
override suspend fun insertOrUpdatePushRequest(pushRequest: PushRequest): Result<Unit> {
|
||||
return runCatchingExceptions { pushDatabase.pushRequestQueries.insertPushRequest(pushRequest).await() }
|
||||
override suspend fun insertOrUpdatePushRequest(pushRequest: PushRequest): Result<Unit> = withContext(dispatchers.io) {
|
||||
runCatchingExceptions<Unit> { pushDatabase.pushRequestQueries.insertPushRequest(pushRequest).await() }
|
||||
}
|
||||
|
||||
override suspend fun insertOrUpdatePushRequests(pushRequests: List<PushRequest>): Result<Unit> {
|
||||
return runCatchingExceptions {
|
||||
override suspend fun insertOrUpdatePushRequests(pushRequests: List<PushRequest>): Result<Unit> = withContext(dispatchers.io) {
|
||||
runCatchingExceptions {
|
||||
pushDatabase.transaction {
|
||||
for (request in pushRequests) {
|
||||
pushDatabase.pushRequestQueries.insertPushRequest(request)
|
||||
@@ -48,8 +51,8 @@ class DefaultPushHistoryService(
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun getPendingPushRequests(sessionId: SessionId, since: Instant?): Result<List<PushRequest>> {
|
||||
return runCatchingExceptions {
|
||||
override suspend fun getPendingPushRequests(sessionId: SessionId, since: Instant?): Result<List<PushRequest>> = withContext(dispatchers.io) {
|
||||
runCatchingExceptions {
|
||||
pushDatabase.transactionWithResult {
|
||||
val sinceTimeMillis = since?.toEpochMilliseconds() ?: 0
|
||||
pushDatabase.pushRequestQueries.selectAllPendingForSession(sessionId.value, sinceTimeMillis).executeAsList()
|
||||
@@ -57,14 +60,14 @@ class DefaultPushHistoryService(
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun removeOldPushRequests(sessionId: SessionId): Result<Unit> {
|
||||
return runCatchingExceptions {
|
||||
override suspend fun removeOldPushRequests(sessionId: SessionId): Result<Unit> = withContext(dispatchers.io) {
|
||||
runCatchingExceptions<Unit> {
|
||||
val keepAmount = 100L
|
||||
pushDatabase.pushRequestQueries.removeOldest(keepAmount)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onPushResult(
|
||||
override suspend fun onPushResult(
|
||||
providerInfo: String,
|
||||
eventId: EventId?,
|
||||
roomId: RoomId?,
|
||||
@@ -91,19 +94,21 @@ class DefaultPushHistoryService(
|
||||
}
|
||||
}.takeIf { it.isNotEmpty() }
|
||||
|
||||
pushDatabase.pushHistoryQueries.insertPushHistory(
|
||||
PushHistory(
|
||||
pushDate = systemClock.epochMillis(),
|
||||
providerInfo = providerInfo,
|
||||
eventId = eventId?.value,
|
||||
roomId = roomId?.value,
|
||||
sessionId = sessionId?.value,
|
||||
hasBeenResolved = if (hasBeenResolved) 1 else 0,
|
||||
comment = finalComment,
|
||||
withContext(dispatchers.io) {
|
||||
pushDatabase.pushHistoryQueries.insertPushHistory(
|
||||
PushHistory(
|
||||
pushDate = systemClock.epochMillis(),
|
||||
providerInfo = providerInfo,
|
||||
eventId = eventId?.value,
|
||||
roomId = roomId?.value,
|
||||
sessionId = sessionId?.value,
|
||||
hasBeenResolved = if (hasBeenResolved) 1 else 0,
|
||||
comment = finalComment,
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
// Keep only the last 1_000 events
|
||||
pushDatabase.pushHistoryQueries.removeOldest(1_000)
|
||||
// Keep only the last 1_000 events
|
||||
pushDatabase.pushHistoryQueries.removeOldest(1_000)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+6
-6
@@ -20,7 +20,7 @@ interface PushHistoryService {
|
||||
* Create a new push history entry.
|
||||
* Do not use directly, prefer using the extension functions.
|
||||
*/
|
||||
fun onPushResult(
|
||||
suspend fun onPushResult(
|
||||
providerInfo: String,
|
||||
eventId: EventId?,
|
||||
roomId: RoomId?,
|
||||
@@ -52,7 +52,7 @@ interface PushHistoryService {
|
||||
suspend fun removeOldPushRequests(sessionId: SessionId): Result<Unit>
|
||||
}
|
||||
|
||||
fun PushHistoryService.onInvalidPushReceived(
|
||||
suspend fun PushHistoryService.onInvalidPushReceived(
|
||||
providerInfo: String,
|
||||
data: String,
|
||||
) = onPushResult(
|
||||
@@ -65,7 +65,7 @@ fun PushHistoryService.onInvalidPushReceived(
|
||||
comment = "Invalid or ignored push data:\n$data",
|
||||
)
|
||||
|
||||
fun PushHistoryService.onUnableToRetrieveSession(
|
||||
suspend fun PushHistoryService.onUnableToRetrieveSession(
|
||||
providerInfo: String,
|
||||
eventId: EventId,
|
||||
roomId: RoomId,
|
||||
@@ -80,7 +80,7 @@ fun PushHistoryService.onUnableToRetrieveSession(
|
||||
comment = "Unable to retrieve session: $reason",
|
||||
)
|
||||
|
||||
fun PushHistoryService.onUnableToResolveEvent(
|
||||
suspend fun PushHistoryService.onUnableToResolveEvent(
|
||||
providerInfo: String,
|
||||
eventId: EventId,
|
||||
roomId: RoomId,
|
||||
@@ -96,7 +96,7 @@ fun PushHistoryService.onUnableToResolveEvent(
|
||||
comment = "Unable to resolve event: $reason",
|
||||
)
|
||||
|
||||
fun PushHistoryService.onSuccess(
|
||||
suspend fun PushHistoryService.onSuccess(
|
||||
providerInfo: String,
|
||||
eventId: EventId,
|
||||
roomId: RoomId,
|
||||
@@ -117,7 +117,7 @@ fun PushHistoryService.onSuccess(
|
||||
},
|
||||
)
|
||||
|
||||
fun PushHistoryService.onDiagnosticPush(
|
||||
suspend fun PushHistoryService.onDiagnosticPush(
|
||||
providerInfo: String,
|
||||
) = onPushResult(
|
||||
providerInfo = providerInfo,
|
||||
|
||||
+1
-1
@@ -30,7 +30,7 @@ class FakePushHistoryService(
|
||||
private val getPendingPushRequests: (SessionId, Instant?) -> Result<List<PushRequest>> = { _, _ -> lambdaError() },
|
||||
private val removeOldPushRequests: (SessionId) -> Result<Unit> = { lambdaError() },
|
||||
) : PushHistoryService {
|
||||
override fun onPushResult(
|
||||
override suspend fun onPushResult(
|
||||
providerInfo: String,
|
||||
eventId: EventId?,
|
||||
roomId: RoomId?,
|
||||
|
||||
Reference in New Issue
Block a user