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.google.gson.Gson
import com.keylesspalace.tusky.db.AccountManager import com.keylesspalace.tusky.db.AccountManager
import com.keylesspalace.tusky.db.AppDatabase 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 import javax.inject.Inject
class CacheUpdater @Inject constructor( class CacheUpdater @Inject constructor(
eventHub: EventHub, eventHub: EventHub,
private val accountManager: AccountManager, accountManager: AccountManager,
appDatabase: AppDatabase, appDatabase: AppDatabase,
gson: Gson gson: Gson
) { ) {
private val disposable: Disposable private val scope = CoroutineScope(Dispatchers.IO + SupervisorJob())
init { init {
val timelineDao = appDatabase.timelineDao() val timelineDao = appDatabase.timelineDao()
disposable = eventHub.events.subscribe { event -> scope.launch {
val accountId = accountManager.activeAccount?.id ?: return@subscribe eventHub.events.asFlow().collect { event ->
when (event) { val accountId = accountManager.activeAccount?.id ?: return@collect
is FavoriteEvent -> when (event) {
timelineDao.setFavourited(accountId, event.statusId, event.favourite) is FavoriteEvent ->
is ReblogEvent -> timelineDao.setFavourited(accountId, event.statusId, event.favourite)
timelineDao.setReblogged(accountId, event.statusId, event.reblog) is ReblogEvent ->
is BookmarkEvent -> timelineDao.setReblogged(accountId, event.statusId, event.reblog)
timelineDao.setBookmarked(accountId, event.statusId, event.bookmark) is BookmarkEvent ->
is UnfollowEvent -> timelineDao.setBookmarked(accountId, event.statusId, event.bookmark)
timelineDao.removeAllByUser(accountId, event.accountId) is UnfollowEvent ->
is StatusDeletedEvent -> timelineDao.removeAllByUser(accountId, event.accountId)
timelineDao.delete(accountId, event.statusId) is StatusDeletedEvent ->
is PollVoteEvent -> { timelineDao.delete(accountId, event.statusId)
val pollString = gson.toJson(event.poll) is PollVoteEvent -> {
timelineDao.setVoted(accountId, event.statusId, pollString) 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() { 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.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.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.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.serverId as 'a_serverId', a.timelineUserId as 'a_timelineUserId',
a.localUsername as 'a_localUsername', a.username as 'a_username', 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', 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.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.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.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.serverId as 'a_serverId', a.timelineUserId as 'a_timelineUserId',
a.localUsername as 'a_localUsername', a.username as 'a_username', 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', 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 FROM TimelineStatusEntity s
LEFT JOIN TimelineAccountEntity a ON (s.timelineUserId = a.timelineUserId AND s.authorServerId = a.serverId) 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) 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""" AND s.authorServerId IS NOT NULL"""
) )
abstract suspend fun getStatus(statusId: String): TimelineStatusWithAccount? abstract suspend fun getStatus(statusId: String): TimelineStatusWithAccount?
@ -89,25 +89,25 @@ AND
"""UPDATE TimelineStatusEntity SET favourited = :favourited """UPDATE TimelineStatusEntity SET favourited = :favourited
WHERE timelineUserId = :accountId AND (serverId = :statusId OR reblogServerId = :statusId)""" 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( @Query(
"""UPDATE TimelineStatusEntity SET bookmarked = :bookmarked """UPDATE TimelineStatusEntity SET bookmarked = :bookmarked
WHERE timelineUserId = :accountId AND (serverId = :statusId OR reblogServerId = :statusId)""" 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( @Query(
"""UPDATE TimelineStatusEntity SET reblogged = :reblogged """UPDATE TimelineStatusEntity SET reblogged = :reblogged
WHERE timelineUserId = :accountId AND (serverId = :statusId OR reblogServerId = :statusId)""" 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( @Query(
"""DELETE FROM TimelineStatusEntity WHERE timelineUserId = :accountId AND """DELETE FROM TimelineStatusEntity WHERE timelineUserId = :accountId AND
(authorServerId = :userId OR reblogAccountId = :userId)""" (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 * 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 """DELETE FROM TimelineStatusEntity WHERE timelineUserId = :accountId
AND serverId = :statusId""" 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. * Cleans the TimelineStatusEntity and TimelineAccountEntity tables from old entries.
@ -158,8 +158,8 @@ AND serverId = :statusId"""
*/ */
@Query( @Query(
"""DELETE FROM TimelineAccountEntity WHERE timelineUserId = :accountId AND serverId NOT IN """DELETE FROM TimelineAccountEntity WHERE timelineUserId = :accountId AND serverId NOT IN
(SELECT authorServerId FROM TimelineStatusEntity WHERE timelineUserId = :accountId) (SELECT authorServerId FROM TimelineStatusEntity WHERE timelineUserId = :accountId)
AND serverId NOT IN AND serverId NOT IN
(SELECT reblogAccountId FROM TimelineStatusEntity WHERE timelineUserId = :accountId AND reblogAccountId IS NOT NULL)""" (SELECT reblogAccountId FROM TimelineStatusEntity WHERE timelineUserId = :accountId AND reblogAccountId IS NOT NULL)"""
) )
abstract suspend fun cleanupAccounts(accountId: Long) abstract suspend fun cleanupAccounts(accountId: Long)
@ -168,31 +168,31 @@ AND serverId = :statusId"""
"""UPDATE TimelineStatusEntity SET poll = :poll """UPDATE TimelineStatusEntity SET poll = :poll
WHERE timelineUserId = :accountId AND (serverId = :statusId OR reblogServerId = :statusId)""" 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( @Query(
"""UPDATE TimelineStatusEntity SET expanded = :expanded """UPDATE TimelineStatusEntity SET expanded = :expanded
WHERE timelineUserId = :accountId AND (serverId = :statusId OR reblogServerId = :statusId)""" 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( @Query(
"""UPDATE TimelineStatusEntity SET contentShowing = :contentShowing """UPDATE TimelineStatusEntity SET contentShowing = :contentShowing
WHERE timelineUserId = :accountId AND (serverId = :statusId OR reblogServerId = :statusId)""" 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( @Query(
"""UPDATE TimelineStatusEntity SET contentCollapsed = :contentCollapsed """UPDATE TimelineStatusEntity SET contentCollapsed = :contentCollapsed
WHERE timelineUserId = :accountId AND (serverId = :statusId OR reblogServerId = :statusId)""" 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( @Query(
"""UPDATE TimelineStatusEntity SET pinned = :pinned """UPDATE TimelineStatusEntity SET pinned = :pinned
WHERE timelineUserId = :accountId AND (serverId = :statusId OR reblogServerId = :statusId)""" 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( @Query(
"""DELETE FROM TimelineStatusEntity """DELETE FROM TimelineStatusEntity