From 7b3541b9ffbc7c8f8539e311c873f15fe73df882 Mon Sep 17 00:00:00 2001 From: Marko Kocic Date: Thu, 20 Feb 2025 20:06:41 +0100 Subject: [PATCH] Implement better findRemoteKey logic --- .../api/mediator/ArticleFeedMediator.kt | 29 +++++++++++++++---- .../articles/db/ArticleFeedCrossRefDao.kt | 3 ++ .../networking/sockets/NostrSocketClient.kt | 3 +- .../android/notes/db/FeedPostRemoteKeyDao.kt | 3 ++ 4 files changed, 32 insertions(+), 6 deletions(-) diff --git a/app/src/main/kotlin/net/primal/android/articles/api/mediator/ArticleFeedMediator.kt b/app/src/main/kotlin/net/primal/android/articles/api/mediator/ArticleFeedMediator.kt index 294fc3431..9498f9bd3 100644 --- a/app/src/main/kotlin/net/primal/android/articles/api/mediator/ArticleFeedMediator.kt +++ b/app/src/main/kotlin/net/primal/android/articles/api/mediator/ArticleFeedMediator.kt @@ -23,6 +23,7 @@ import net.primal.android.nostr.ext.orderByPagingIfNotNull import net.primal.android.nostr.model.NostrEvent import net.primal.android.nostr.model.primal.content.ContentPrimalPaging import net.primal.android.notes.db.FeedPostRemoteKey +import timber.log.Timber @OptIn(ExperimentalPagingApi::class) class ArticleFeedMediator( @@ -52,10 +53,17 @@ class ArticleFeedMediator( @Suppress("ReturnCount") override suspend fun load(loadType: LoadType, state: PagingState): MediatorResult { val nextUntil = when (loadType) { - LoadType.APPEND -> findLastRemoteKey()?.sinceId - ?: return MediatorResult.Success(endOfPaginationReached = true) + LoadType.APPEND -> findLastRemoteKey(state = state)?.sinceId + ?: run { + Timber.d("APPEND no remote key found exit.") + return MediatorResult.Success(endOfPaginationReached = true) + } + + LoadType.PREPEND -> { + Timber.d("PREPEND end of pagination exit.") + return MediatorResult.Success(endOfPaginationReached = true) + } - LoadType.PREPEND -> return MediatorResult.Success(endOfPaginationReached = true) LoadType.REFRESH -> null } @@ -72,6 +80,7 @@ class ArticleFeedMediator( } catch (error: WssException) { MediatorResult.Error(error) } catch (_: RepeatingRequestBodyException) { + Timber.d("RepeatingRequestBody exit.") MediatorResult.Success(endOfPaginationReached = true) } } @@ -107,9 +116,19 @@ class ArticleFeedMediator( return response } - private suspend fun findLastRemoteKey(): FeedPostRemoteKey? = + private suspend fun findLastRemoteKey(state: PagingState): FeedPostRemoteKey? { + val lastItemId = state.lastItemOrNull()?.data?.eventId + ?: findLastItemOrNull()?.articleId + + return withContext(dispatcherProvider.io()) { + lastItemId?.let { database.feedPostsRemoteKeys().findByEventId(eventId = lastItemId) } + ?: database.feedPostsRemoteKeys().findLatestByDirective(directive = feedSpec) + } + } + + private suspend fun findLastItemOrNull(): ArticleFeedCrossRef? = withContext(dispatcherProvider.io()) { - database.feedPostsRemoteKeys().findLatestByDirective(directive = feedSpec) + database.articleFeedsConnections().findLastBySpec(spec = feedSpec) } private suspend fun processAndPersistToDatabase(response: ArticleResponse, clearFeed: Boolean) { diff --git a/app/src/main/kotlin/net/primal/android/articles/db/ArticleFeedCrossRefDao.kt b/app/src/main/kotlin/net/primal/android/articles/db/ArticleFeedCrossRefDao.kt index 40c4265ba..c87b39f7f 100644 --- a/app/src/main/kotlin/net/primal/android/articles/db/ArticleFeedCrossRefDao.kt +++ b/app/src/main/kotlin/net/primal/android/articles/db/ArticleFeedCrossRefDao.kt @@ -11,6 +11,9 @@ interface ArticleFeedCrossRefDao { @Insert(onConflict = OnConflictStrategy.REPLACE) fun connect(data: List) + @Query("SELECT * FROM ArticleFeedCrossRef WHERE spec = :spec ORDER BY position DESC LIMIT 1") + fun findLastBySpec(spec: String): ArticleFeedCrossRef? + @Query("DELETE FROM ArticleFeedCrossRef WHERE spec = :spec") fun deleteConnectionsBySpec(spec: String) } diff --git a/app/src/main/kotlin/net/primal/android/networking/sockets/NostrSocketClient.kt b/app/src/main/kotlin/net/primal/android/networking/sockets/NostrSocketClient.kt index cd88b81b0..8e04e9bfe 100644 --- a/app/src/main/kotlin/net/primal/android/networking/sockets/NostrSocketClient.kt +++ b/app/src/main/kotlin/net/primal/android/networking/sockets/NostrSocketClient.kt @@ -157,7 +157,8 @@ class NostrSocketClient( chunks.forEachIndexed { index, chunk -> val prefix = if (incoming) "<--" else "-->" val suffix = if (index == chunksCount - 1) "[$url]" else "" - Timber.d("$prefix $chunk $suffix") + Timber.tag(if (incoming) "NostrSocketClientIncoming" else "NostrSocketClientOutgoing") + .d("$prefix $chunk $suffix") } } diff --git a/app/src/main/kotlin/net/primal/android/notes/db/FeedPostRemoteKeyDao.kt b/app/src/main/kotlin/net/primal/android/notes/db/FeedPostRemoteKeyDao.kt index 5747d08de..ee631aa6b 100644 --- a/app/src/main/kotlin/net/primal/android/notes/db/FeedPostRemoteKeyDao.kt +++ b/app/src/main/kotlin/net/primal/android/notes/db/FeedPostRemoteKeyDao.kt @@ -11,6 +11,9 @@ interface FeedPostRemoteKeyDao { @Insert(onConflict = OnConflictStrategy.REPLACE) fun upsert(data: List) + @Query("SELECT * FROM FeedPostRemoteKey WHERE eventId = :eventId LIMIT 1") + fun findByEventId(eventId: String): FeedPostRemoteKey? + @Query( """ SELECT * FROM FeedPostRemoteKey