Skip to content

Commit

Permalink
feat: キャッシュを自動同期するようにした
Browse files Browse the repository at this point in the history
  • Loading branch information
pantasystem committed May 18, 2024
1 parent b6e94d8 commit 5459cd2
Show file tree
Hide file tree
Showing 6 changed files with 163 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import net.pantasystem.milktea.worker.drive.CleanupUnusedCacheWorker
import net.pantasystem.milktea.worker.emoji.cache.CacheCustomEmojiImageWorker
import net.pantasystem.milktea.worker.filter.SyncMastodonFilterWorker
import net.pantasystem.milktea.worker.meta.SyncMetaWorker
import net.pantasystem.milktea.worker.note.SyncTimelineWorker
import net.pantasystem.milktea.worker.sw.RegisterAllSubscriptionRegistration
import net.pantasystem.milktea.worker.user.SyncLoggedInUserInfoWorker
import net.pantasystem.milktea.worker.user.renote.mute.SyncRenoteMutesWorker
Expand Down Expand Up @@ -55,6 +56,9 @@ class WorkerJobInitializer @Inject constructor(
CacheCustomEmojiImageWorker.createPeriodicWorkRequest(),
)

enqueue(
SyncTimelineWorker.createOneTimeWorkRequest()
)
enqueue(
SyncRenoteMutesWorker.createOneTimeWorkRequest()
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,4 +91,28 @@ interface TimelineCacheDAO {
"""
)
suspend fun clear(accountId: Long, pageId: Long)

// last previous id
@Query(
"""
SELECT note_id FROM timeline_item
WHERE account_id = :accountId
AND page_id = :pageId
ORDER BY note_id ASC
LIMIT 1
"""
)
suspend fun findLastPreviousId(accountId: Long, pageId: Long): String?

// first later id
@Query(
"""
SELECT note_id FROM timeline_item
WHERE account_id = :accountId
AND page_id = :pageId
ORDER BY note_id DESC
LIMIT 1
"""
)
suspend fun findFirstLaterId(accountId: Long, pageId: Long): String?
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import kotlinx.coroutines.launch
import net.pantasystem.milktea.api.mastodon.status.TootStatusDTO
import net.pantasystem.milktea.api.misskey.notes.NoteDTO
import net.pantasystem.milktea.api.misskey.notes.NoteRequest
import net.pantasystem.milktea.common.Logger
import net.pantasystem.milktea.common.MastodonLinkHeaderDecoder
import net.pantasystem.milktea.common.mapCancellableCatching
import net.pantasystem.milktea.common.runCancellableCatching
Expand Down Expand Up @@ -35,8 +36,13 @@ class TimelineRepositoryImpl @Inject constructor(
private val nodeInfoRepository: NodeInfoRepository,
private val applicationScope: CoroutineScope,
private val noteRepository: NoteRepository,
private val loggerFactory: Logger.Factory,
) : TimelineRepository {

private val logger by lazy {
loggerFactory.create("TimelineRepository")
}

override suspend fun findLaterTimeline(
type: TimelineType,
sinceId: String?,
Expand All @@ -58,6 +64,9 @@ class TimelineRepositoryImpl @Inject constructor(
limit
).getOrThrow()

logger.debug {
"findLaterTimeline: inCache.size=${inCache.timelineItems.size} limit=$limit"
}
if (inCache.timelineItems.size >= limit) {
applicationScope.launch {
if (type.canCache()) {
Expand All @@ -74,7 +83,9 @@ class TimelineRepositoryImpl @Inject constructor(
accountId = account.accountId,
pageId = type.pageId!!,
response.timelineItems.map { it.noteId },
)
).getOrThrow()
}.onFailure {
logger.error("failed sync timeline to cache", it)
}
}
}
Expand Down Expand Up @@ -119,6 +130,9 @@ class TimelineRepositoryImpl @Inject constructor(
limit
).getOrThrow()

logger.debug {
"findPreviousTimeline: inCache.size=${inCache.timelineItems.size} limit=$limit"
}
if (inCache.timelineItems.size >= limit) {
applicationScope.launch {
val lastItemId = inCache.timelineItems.lastOrNull()
Expand All @@ -136,7 +150,9 @@ class TimelineRepositoryImpl @Inject constructor(
accountId = account.accountId,
pageId = type.pageId!!,
response.timelineItems.map { it.noteId },
)
).getOrThrow()
}.onFailure {
logger.error("failed sync timeline to cache", it)
}
}
if (untilId == null && lastItemId != null) {
Expand Down Expand Up @@ -180,6 +196,20 @@ class TimelineRepositoryImpl @Inject constructor(
timelineCacheDAO.clear(type.accountId, type.pageId!!)
}

override suspend fun findFirstLaterId(type: TimelineType): Result<String?> = runCancellableCatching {
if (!type.canCache()) {
return@runCancellableCatching null
}
timelineCacheDAO.findFirstLaterId(type.accountId, type.pageId!!)
}

override suspend fun findLastPreviousId(type: TimelineType): Result<String?> = runCancellableCatching {
if (!type.canCache()) {
return@runCancellableCatching null
}
timelineCacheDAO.findLastPreviousId(type.accountId, type.pageId!!)
}

private suspend fun fetchTimeline(
account: Account,
pageable: Pageable,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package net.pantasystem.milktea.model.note.timeline

import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.coroutineScope
import net.pantasystem.milktea.common.runCancellableCatching
import net.pantasystem.milktea.model.UseCase
import net.pantasystem.milktea.model.account.AccountRepository
import javax.inject.Inject

class SyncTimelineUseCase @Inject constructor(
private val accountRepository: AccountRepository,
private val timelineRepository: TimelineRepository,
) : UseCase {

suspend operator fun invoke(): Result<Unit> = runCancellableCatching {
val accounts = accountRepository.findAll().getOrThrow()
coroutineScope {
accounts.flatMap { it.pages }.map {
async {
val type = TimelineType(
accountId = it.accountId,
pageable = it.pageable(),
pageId = null,
)
if (type.canCache() && it.isSavePagePosition) {
sync(
type,
nextId = timelineRepository.findFirstLaterId(type).getOrNull()
)
}
}
}.awaitAll()
}
}

// ページがなくなるまで最新の投稿を取得し続ける
suspend fun sync(type: TimelineType, nextId: String?): Result<Unit> = runCancellableCatching {
if (type.canCache()) {
return@runCancellableCatching
}
val response = timelineRepository.findLaterTimeline(type, sinceId = nextId).getOrThrow()
if (response.timelineItems.isEmpty()) {
return@runCancellableCatching
}

sync(type, response.untilId)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,13 @@ interface TimelineRepository {
type: TimelineType,
): Result<Unit>

suspend fun findFirstLaterId(
type: TimelineType,
): Result<String?>

suspend fun findLastPreviousId(
type: TimelineType,
): Result<String?>
}

data class TimelineResponse(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package net.pantasystem.milktea.worker.note

import android.content.Context
import androidx.hilt.work.HiltWorker
import androidx.work.CoroutineWorker
import androidx.work.OneTimeWorkRequest
import androidx.work.OneTimeWorkRequestBuilder
import androidx.work.PeriodicWorkRequest
import androidx.work.PeriodicWorkRequestBuilder
import androidx.work.WorkerParameters
import dagger.assisted.Assisted
import dagger.assisted.AssistedInject
import net.pantasystem.milktea.model.note.timeline.SyncTimelineUseCase
import java.util.concurrent.TimeUnit

@HiltWorker

class SyncTimelineWorker @AssistedInject constructor(
@Assisted context: Context,
@Assisted val params: WorkerParameters,
private val syncTimelineUseCase: SyncTimelineUseCase,
): CoroutineWorker(context, params) {

companion object {
const val WORKER_NAME = "SyncTimelineWorker"
fun createPeriodicWorkRequest(): PeriodicWorkRequest {
return PeriodicWorkRequestBuilder<SyncTimelineWorker>(1, TimeUnit.MINUTES)
.build()
}

fun createOneTimeWorkRequest(): OneTimeWorkRequest {
return OneTimeWorkRequestBuilder<SyncTimelineWorker>()
.build()
}
}

override suspend fun doWork(): Result {
syncTimelineUseCase().fold(
onSuccess = {
return Result.success()
},
onFailure = {
return Result.failure()
}
)
}
}

0 comments on commit 5459cd2

Please sign in to comment.