make sure all timeline database operations run on a background thread (#3391)

This commit is contained in:
Konrad Pozniak 2023-03-01 20:00:19 +01:00 committed by GitHub
parent b8c77a795c
commit 816dc0cbbc
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 44 additions and 37 deletions

View file

@ -3,45 +3,52 @@ package com.keylesspalace.tusky.appstore
import com.google.gson.Gson
import com.keylesspalace.tusky.db.AccountManager
import com.keylesspalace.tusky.db.AppDatabase
import io.reactivex.rxjava3.disposables.Disposable
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.cancel
import kotlinx.coroutines.launch
import kotlinx.coroutines.rx3.asFlow
import javax.inject.Inject
class CacheUpdater @Inject constructor(
eventHub: EventHub,
private val accountManager: AccountManager,
accountManager: AccountManager,
appDatabase: AppDatabase,
gson: Gson
) {
private val disposable: Disposable
private val scope = CoroutineScope(Dispatchers.IO + SupervisorJob())
init {
val timelineDao = appDatabase.timelineDao()
disposable = eventHub.events.subscribe { event ->
val accountId = accountManager.activeAccount?.id ?: return@subscribe
when (event) {
is FavoriteEvent ->
timelineDao.setFavourited(accountId, event.statusId, event.favourite)
is ReblogEvent ->
timelineDao.setReblogged(accountId, event.statusId, event.reblog)
is BookmarkEvent ->
timelineDao.setBookmarked(accountId, event.statusId, event.bookmark)
is UnfollowEvent ->
timelineDao.removeAllByUser(accountId, event.accountId)
is StatusDeletedEvent ->
timelineDao.delete(accountId, event.statusId)
is PollVoteEvent -> {
val pollString = gson.toJson(event.poll)
timelineDao.setVoted(accountId, event.statusId, pollString)
scope.launch {
eventHub.events.asFlow().collect { event ->
val accountId = accountManager.activeAccount?.id ?: return@collect
when (event) {
is FavoriteEvent ->
timelineDao.setFavourited(accountId, event.statusId, event.favourite)
is ReblogEvent ->
timelineDao.setReblogged(accountId, event.statusId, event.reblog)
is BookmarkEvent ->
timelineDao.setBookmarked(accountId, event.statusId, event.bookmark)
is UnfollowEvent ->
timelineDao.removeAllByUser(accountId, event.accountId)
is StatusDeletedEvent ->
timelineDao.delete(accountId, event.statusId)
is PollVoteEvent -> {
val pollString = gson.toJson(event.poll)
timelineDao.setVoted(accountId, event.statusId, pollString)
}
is PinEvent ->
timelineDao.setPinned(accountId, event.statusId, event.pinned)
}
is PinEvent ->
timelineDao.setPinned(accountId, event.statusId, event.pinned)
}
}
}
fun stop() {
this.disposable.dispose()
this.scope.cancel()
}
}

View file

@ -36,7 +36,7 @@ SELECT s.serverId, s.url, s.timelineUserId,
s.authorServerId, s.inReplyToId, s.inReplyToAccountId, s.createdAt, s.editedAt,
s.emojis, s.reblogsCount, s.favouritesCount, s.repliesCount, s.reblogged, s.favourited, s.bookmarked, s.sensitive,
s.spoilerText, s.visibility, s.mentions, s.tags, s.application, s.reblogServerId,s.reblogAccountId,
s.content, s.attachments, s.poll, s.card, s.muted, s.expanded, s.contentShowing, s.contentCollapsed, s.pinned, s.language,
s.content, s.attachments, s.poll, s.card, s.muted, s.expanded, s.contentShowing, s.contentCollapsed, s.pinned, s.language,
a.serverId as 'a_serverId', a.timelineUserId as 'a_timelineUserId',
a.localUsername as 'a_localUsername', a.username as 'a_username',
a.displayName as 'a_displayName', a.url as 'a_url', a.avatar as 'a_avatar',
@ -59,7 +59,7 @@ SELECT s.serverId, s.url, s.timelineUserId,
s.authorServerId, s.inReplyToId, s.inReplyToAccountId, s.createdAt, s.editedAt,
s.emojis, s.reblogsCount, s.favouritesCount, s.repliesCount, s.reblogged, s.favourited, s.bookmarked, s.sensitive,
s.spoilerText, s.visibility, s.mentions, s.tags, s.application, s.reblogServerId,s.reblogAccountId,
s.content, s.attachments, s.poll, s.card, s.muted, s.expanded, s.contentShowing, s.contentCollapsed, s.pinned, s.language,
s.content, s.attachments, s.poll, s.card, s.muted, s.expanded, s.contentShowing, s.contentCollapsed, s.pinned, s.language,
a.serverId as 'a_serverId', a.timelineUserId as 'a_timelineUserId',
a.localUsername as 'a_localUsername', a.username as 'a_username',
a.displayName as 'a_displayName', a.url as 'a_url', a.avatar as 'a_avatar',
@ -71,7 +71,7 @@ rb.emojis as 'rb_emojis', rb.bot as 'rb_bot'
FROM TimelineStatusEntity s
LEFT JOIN TimelineAccountEntity a ON (s.timelineUserId = a.timelineUserId AND s.authorServerId = a.serverId)
LEFT JOIN TimelineAccountEntity rb ON (s.timelineUserId = rb.timelineUserId AND s.reblogAccountId = rb.serverId)
WHERE (s.serverId = :statusId OR s.reblogServerId = :statusId)
WHERE (s.serverId = :statusId OR s.reblogServerId = :statusId)
AND s.authorServerId IS NOT NULL"""
)
abstract suspend fun getStatus(statusId: String): TimelineStatusWithAccount?
@ -89,25 +89,25 @@ AND
"""UPDATE TimelineStatusEntity SET favourited = :favourited
WHERE timelineUserId = :accountId AND (serverId = :statusId OR reblogServerId = :statusId)"""
)
abstract fun setFavourited(accountId: Long, statusId: String, favourited: Boolean)
abstract suspend fun setFavourited(accountId: Long, statusId: String, favourited: Boolean)
@Query(
"""UPDATE TimelineStatusEntity SET bookmarked = :bookmarked
WHERE timelineUserId = :accountId AND (serverId = :statusId OR reblogServerId = :statusId)"""
)
abstract fun setBookmarked(accountId: Long, statusId: String, bookmarked: Boolean)
abstract suspend fun setBookmarked(accountId: Long, statusId: String, bookmarked: Boolean)
@Query(
"""UPDATE TimelineStatusEntity SET reblogged = :reblogged
WHERE timelineUserId = :accountId AND (serverId = :statusId OR reblogServerId = :statusId)"""
)
abstract fun setReblogged(accountId: Long, statusId: String, reblogged: Boolean)
abstract suspend fun setReblogged(accountId: Long, statusId: String, reblogged: Boolean)
@Query(
"""DELETE FROM TimelineStatusEntity WHERE timelineUserId = :accountId AND
(authorServerId = :userId OR reblogAccountId = :userId)"""
)
abstract fun removeAllByUser(accountId: Long, userId: String)
abstract suspend fun removeAllByUser(accountId: Long, userId: String)
/**
* Removes everything in the TimelineStatusEntity and TimelineAccountEntity tables for one user account
@ -128,7 +128,7 @@ WHERE timelineUserId = :accountId AND (serverId = :statusId OR reblogServerId =
"""DELETE FROM TimelineStatusEntity WHERE timelineUserId = :accountId
AND serverId = :statusId"""
)
abstract fun delete(accountId: Long, statusId: String)
abstract suspend fun delete(accountId: Long, statusId: String)
/**
* Cleans the TimelineStatusEntity and TimelineAccountEntity tables from old entries.
@ -158,8 +158,8 @@ AND serverId = :statusId"""
*/
@Query(
"""DELETE FROM TimelineAccountEntity WHERE timelineUserId = :accountId AND serverId NOT IN
(SELECT authorServerId FROM TimelineStatusEntity WHERE timelineUserId = :accountId)
AND serverId NOT IN
(SELECT authorServerId FROM TimelineStatusEntity WHERE timelineUserId = :accountId)
AND serverId NOT IN
(SELECT reblogAccountId FROM TimelineStatusEntity WHERE timelineUserId = :accountId AND reblogAccountId IS NOT NULL)"""
)
abstract suspend fun cleanupAccounts(accountId: Long)
@ -168,31 +168,31 @@ AND serverId = :statusId"""
"""UPDATE TimelineStatusEntity SET poll = :poll
WHERE timelineUserId = :accountId AND (serverId = :statusId OR reblogServerId = :statusId)"""
)
abstract fun setVoted(accountId: Long, statusId: String, poll: String)
abstract suspend fun setVoted(accountId: Long, statusId: String, poll: String)
@Query(
"""UPDATE TimelineStatusEntity SET expanded = :expanded
WHERE timelineUserId = :accountId AND (serverId = :statusId OR reblogServerId = :statusId)"""
)
abstract fun setExpanded(accountId: Long, statusId: String, expanded: Boolean)
abstract suspend fun setExpanded(accountId: Long, statusId: String, expanded: Boolean)
@Query(
"""UPDATE TimelineStatusEntity SET contentShowing = :contentShowing
WHERE timelineUserId = :accountId AND (serverId = :statusId OR reblogServerId = :statusId)"""
)
abstract fun setContentShowing(accountId: Long, statusId: String, contentShowing: Boolean)
abstract suspend fun setContentShowing(accountId: Long, statusId: String, contentShowing: Boolean)
@Query(
"""UPDATE TimelineStatusEntity SET contentCollapsed = :contentCollapsed
WHERE timelineUserId = :accountId AND (serverId = :statusId OR reblogServerId = :statusId)"""
)
abstract fun setContentCollapsed(accountId: Long, statusId: String, contentCollapsed: Boolean)
abstract suspend fun setContentCollapsed(accountId: Long, statusId: String, contentCollapsed: Boolean)
@Query(
"""UPDATE TimelineStatusEntity SET pinned = :pinned
WHERE timelineUserId = :accountId AND (serverId = :statusId OR reblogServerId = :statusId)"""
)
abstract fun setPinned(accountId: Long, statusId: String, pinned: Boolean)
abstract suspend fun setPinned(accountId: Long, statusId: String, pinned: Boolean)
@Query(
"""DELETE FROM TimelineStatusEntity