mirror of
https://github.com/Novaloop-AG/element-x-android.git
synced 2026-11-02 20:38:40 +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 androidx.core.content.getSystemService
|
||||||
import dev.zacsweers.metro.AppScope
|
import dev.zacsweers.metro.AppScope
|
||||||
import dev.zacsweers.metro.ContributesBinding
|
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.core.extensions.runCatchingExceptions
|
||||||
import io.element.android.libraries.di.annotations.ApplicationContext
|
import io.element.android.libraries.di.annotations.ApplicationContext
|
||||||
import io.element.android.libraries.matrix.api.core.EventId
|
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.PushHistory
|
||||||
import io.element.android.libraries.push.impl.db.PushRequest
|
import io.element.android.libraries.push.impl.db.PushRequest
|
||||||
import io.element.android.services.toolbox.api.systemclock.SystemClock
|
import io.element.android.services.toolbox.api.systemclock.SystemClock
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
import kotlin.time.Instant
|
import kotlin.time.Instant
|
||||||
|
|
||||||
@ContributesBinding(AppScope::class)
|
@ContributesBinding(AppScope::class)
|
||||||
class DefaultPushHistoryService(
|
class DefaultPushHistoryService(
|
||||||
private val pushDatabase: PushDatabase,
|
private val pushDatabase: PushDatabase,
|
||||||
private val systemClock: SystemClock,
|
private val systemClock: SystemClock,
|
||||||
|
private val dispatchers: CoroutineDispatchers,
|
||||||
@ApplicationContext context: Context,
|
@ApplicationContext context: Context,
|
||||||
) : PushHistoryService {
|
) : PushHistoryService {
|
||||||
private val powerManager = context.getSystemService<PowerManager>()
|
private val powerManager = context.getSystemService<PowerManager>()
|
||||||
private val packageName = context.packageName
|
private val packageName = context.packageName
|
||||||
|
|
||||||
override suspend fun insertOrUpdatePushRequest(pushRequest: PushRequest): Result<Unit> {
|
override suspend fun insertOrUpdatePushRequest(pushRequest: PushRequest): Result<Unit> = withContext(dispatchers.io) {
|
||||||
return runCatchingExceptions { pushDatabase.pushRequestQueries.insertPushRequest(pushRequest).await() }
|
runCatchingExceptions<Unit> { pushDatabase.pushRequestQueries.insertPushRequest(pushRequest).await() }
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun insertOrUpdatePushRequests(pushRequests: List<PushRequest>): Result<Unit> {
|
override suspend fun insertOrUpdatePushRequests(pushRequests: List<PushRequest>): Result<Unit> = withContext(dispatchers.io) {
|
||||||
return runCatchingExceptions {
|
runCatchingExceptions {
|
||||||
pushDatabase.transaction {
|
pushDatabase.transaction {
|
||||||
for (request in pushRequests) {
|
for (request in pushRequests) {
|
||||||
pushDatabase.pushRequestQueries.insertPushRequest(request)
|
pushDatabase.pushRequestQueries.insertPushRequest(request)
|
||||||
@@ -48,8 +51,8 @@ class DefaultPushHistoryService(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun getPendingPushRequests(sessionId: SessionId, since: Instant?): Result<List<PushRequest>> {
|
override suspend fun getPendingPushRequests(sessionId: SessionId, since: Instant?): Result<List<PushRequest>> = withContext(dispatchers.io) {
|
||||||
return runCatchingExceptions {
|
runCatchingExceptions {
|
||||||
pushDatabase.transactionWithResult {
|
pushDatabase.transactionWithResult {
|
||||||
val sinceTimeMillis = since?.toEpochMilliseconds() ?: 0
|
val sinceTimeMillis = since?.toEpochMilliseconds() ?: 0
|
||||||
pushDatabase.pushRequestQueries.selectAllPendingForSession(sessionId.value, sinceTimeMillis).executeAsList()
|
pushDatabase.pushRequestQueries.selectAllPendingForSession(sessionId.value, sinceTimeMillis).executeAsList()
|
||||||
@@ -57,14 +60,14 @@ class DefaultPushHistoryService(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun removeOldPushRequests(sessionId: SessionId): Result<Unit> {
|
override suspend fun removeOldPushRequests(sessionId: SessionId): Result<Unit> = withContext(dispatchers.io) {
|
||||||
return runCatchingExceptions {
|
runCatchingExceptions<Unit> {
|
||||||
val keepAmount = 100L
|
val keepAmount = 100L
|
||||||
pushDatabase.pushRequestQueries.removeOldest(keepAmount)
|
pushDatabase.pushRequestQueries.removeOldest(keepAmount)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onPushResult(
|
override suspend fun onPushResult(
|
||||||
providerInfo: String,
|
providerInfo: String,
|
||||||
eventId: EventId?,
|
eventId: EventId?,
|
||||||
roomId: RoomId?,
|
roomId: RoomId?,
|
||||||
@@ -91,19 +94,21 @@ class DefaultPushHistoryService(
|
|||||||
}
|
}
|
||||||
}.takeIf { it.isNotEmpty() }
|
}.takeIf { it.isNotEmpty() }
|
||||||
|
|
||||||
pushDatabase.pushHistoryQueries.insertPushHistory(
|
withContext(dispatchers.io) {
|
||||||
PushHistory(
|
pushDatabase.pushHistoryQueries.insertPushHistory(
|
||||||
pushDate = systemClock.epochMillis(),
|
PushHistory(
|
||||||
providerInfo = providerInfo,
|
pushDate = systemClock.epochMillis(),
|
||||||
eventId = eventId?.value,
|
providerInfo = providerInfo,
|
||||||
roomId = roomId?.value,
|
eventId = eventId?.value,
|
||||||
sessionId = sessionId?.value,
|
roomId = roomId?.value,
|
||||||
hasBeenResolved = if (hasBeenResolved) 1 else 0,
|
sessionId = sessionId?.value,
|
||||||
comment = finalComment,
|
hasBeenResolved = if (hasBeenResolved) 1 else 0,
|
||||||
|
comment = finalComment,
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
|
||||||
|
|
||||||
// Keep only the last 1_000 events
|
// Keep only the last 1_000 events
|
||||||
pushDatabase.pushHistoryQueries.removeOldest(1_000)
|
pushDatabase.pushHistoryQueries.removeOldest(1_000)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-6
@@ -20,7 +20,7 @@ interface PushHistoryService {
|
|||||||
* Create a new push history entry.
|
* Create a new push history entry.
|
||||||
* Do not use directly, prefer using the extension functions.
|
* Do not use directly, prefer using the extension functions.
|
||||||
*/
|
*/
|
||||||
fun onPushResult(
|
suspend fun onPushResult(
|
||||||
providerInfo: String,
|
providerInfo: String,
|
||||||
eventId: EventId?,
|
eventId: EventId?,
|
||||||
roomId: RoomId?,
|
roomId: RoomId?,
|
||||||
@@ -52,7 +52,7 @@ interface PushHistoryService {
|
|||||||
suspend fun removeOldPushRequests(sessionId: SessionId): Result<Unit>
|
suspend fun removeOldPushRequests(sessionId: SessionId): Result<Unit>
|
||||||
}
|
}
|
||||||
|
|
||||||
fun PushHistoryService.onInvalidPushReceived(
|
suspend fun PushHistoryService.onInvalidPushReceived(
|
||||||
providerInfo: String,
|
providerInfo: String,
|
||||||
data: String,
|
data: String,
|
||||||
) = onPushResult(
|
) = onPushResult(
|
||||||
@@ -65,7 +65,7 @@ fun PushHistoryService.onInvalidPushReceived(
|
|||||||
comment = "Invalid or ignored push data:\n$data",
|
comment = "Invalid or ignored push data:\n$data",
|
||||||
)
|
)
|
||||||
|
|
||||||
fun PushHistoryService.onUnableToRetrieveSession(
|
suspend fun PushHistoryService.onUnableToRetrieveSession(
|
||||||
providerInfo: String,
|
providerInfo: String,
|
||||||
eventId: EventId,
|
eventId: EventId,
|
||||||
roomId: RoomId,
|
roomId: RoomId,
|
||||||
@@ -80,7 +80,7 @@ fun PushHistoryService.onUnableToRetrieveSession(
|
|||||||
comment = "Unable to retrieve session: $reason",
|
comment = "Unable to retrieve session: $reason",
|
||||||
)
|
)
|
||||||
|
|
||||||
fun PushHistoryService.onUnableToResolveEvent(
|
suspend fun PushHistoryService.onUnableToResolveEvent(
|
||||||
providerInfo: String,
|
providerInfo: String,
|
||||||
eventId: EventId,
|
eventId: EventId,
|
||||||
roomId: RoomId,
|
roomId: RoomId,
|
||||||
@@ -96,7 +96,7 @@ fun PushHistoryService.onUnableToResolveEvent(
|
|||||||
comment = "Unable to resolve event: $reason",
|
comment = "Unable to resolve event: $reason",
|
||||||
)
|
)
|
||||||
|
|
||||||
fun PushHistoryService.onSuccess(
|
suspend fun PushHistoryService.onSuccess(
|
||||||
providerInfo: String,
|
providerInfo: String,
|
||||||
eventId: EventId,
|
eventId: EventId,
|
||||||
roomId: RoomId,
|
roomId: RoomId,
|
||||||
@@ -117,7 +117,7 @@ fun PushHistoryService.onSuccess(
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
fun PushHistoryService.onDiagnosticPush(
|
suspend fun PushHistoryService.onDiagnosticPush(
|
||||||
providerInfo: String,
|
providerInfo: String,
|
||||||
) = onPushResult(
|
) = onPushResult(
|
||||||
providerInfo = providerInfo,
|
providerInfo = providerInfo,
|
||||||
|
|||||||
+1
-1
@@ -30,7 +30,7 @@ class FakePushHistoryService(
|
|||||||
private val getPendingPushRequests: (SessionId, Instant?) -> Result<List<PushRequest>> = { _, _ -> lambdaError() },
|
private val getPendingPushRequests: (SessionId, Instant?) -> Result<List<PushRequest>> = { _, _ -> lambdaError() },
|
||||||
private val removeOldPushRequests: (SessionId) -> Result<Unit> = { lambdaError() },
|
private val removeOldPushRequests: (SessionId) -> Result<Unit> = { lambdaError() },
|
||||||
) : PushHistoryService {
|
) : PushHistoryService {
|
||||||
override fun onPushResult(
|
override suspend fun onPushResult(
|
||||||
providerInfo: String,
|
providerInfo: String,
|
||||||
eventId: EventId?,
|
eventId: EventId?,
|
||||||
roomId: RoomId?,
|
roomId: RoomId?,
|
||||||
|
|||||||
Reference in New Issue
Block a user