mirror of
https://github.com/JustinZeus/Wholphin.git
synced 2026-07-09 16:11:20 +02:00
Fix: optimize suggestions performance (#849)
## Description - Aims to further optimize performance for the suggestions fetching ### Related issues Fixes #833 ### Testing Android Emulator NVIDIA Shield Pro 2019 ## Screenshots N/A ## AI or LLM usage AI being used to assist with updating/creating unit tests
This commit is contained in:
parent
fd9063fbad
commit
0b73b4cf64
4 changed files with 79 additions and 8 deletions
|
|
@ -8,6 +8,7 @@ import androidx.work.Constraints
|
|||
import androidx.work.ExistingPeriodicWorkPolicy
|
||||
import androidx.work.NetworkType
|
||||
import androidx.work.PeriodicWorkRequestBuilder
|
||||
import androidx.work.WorkInfo
|
||||
import androidx.work.WorkManager
|
||||
import androidx.work.workDataOf
|
||||
import com.github.damontecres.wholphin.data.ServerRepository
|
||||
|
|
@ -17,9 +18,11 @@ import dagger.hilt.android.scopes.ActivityScoped
|
|||
import kotlinx.coroutines.CoroutineDispatcher
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import timber.log.Timber
|
||||
import java.util.UUID
|
||||
import javax.inject.Inject
|
||||
import kotlin.random.Random
|
||||
import kotlin.time.Duration.Companion.hours
|
||||
import kotlin.time.Duration.Companion.minutes
|
||||
import kotlin.time.Duration.Companion.seconds
|
||||
|
|
@ -31,7 +34,6 @@ class SuggestionsSchedulerService
|
|||
constructor(
|
||||
@param:ActivityContext private val context: Context,
|
||||
private val serverRepository: ServerRepository,
|
||||
private val cache: SuggestionsCache,
|
||||
private val workManager: WorkManager,
|
||||
) {
|
||||
private val activity =
|
||||
|
|
@ -42,6 +44,7 @@ class SuggestionsSchedulerService
|
|||
|
||||
// Exposed for testing
|
||||
internal var dispatcher: CoroutineDispatcher = Dispatchers.IO
|
||||
internal var initialDelaySecondsProvider: () -> Long = { 60L + Random.nextLong(0L, 121L) }
|
||||
|
||||
init {
|
||||
serverRepository.current.observe(activity) { user ->
|
||||
|
|
@ -60,6 +63,28 @@ class SuggestionsSchedulerService
|
|||
userId: UUID,
|
||||
serverId: UUID,
|
||||
) {
|
||||
val workInfos =
|
||||
withContext(dispatcher) {
|
||||
workManager
|
||||
.getWorkInfosForUniqueWork(SuggestionsWorker.WORK_NAME)
|
||||
.get()
|
||||
}
|
||||
val activeWork =
|
||||
workInfos.firstOrNull {
|
||||
!it.state.isFinished
|
||||
}
|
||||
val scheduledUserId =
|
||||
activeWork
|
||||
?.tags
|
||||
?.firstOrNull { it.startsWith("user:") }
|
||||
?.removePrefix("user:")
|
||||
|
||||
val isAlreadyScheduledForUser = scheduledUserId == userId.toString()
|
||||
if (isAlreadyScheduledForUser) {
|
||||
Timber.d("SuggestionsWorker already scheduled for user %s", userId)
|
||||
return
|
||||
}
|
||||
|
||||
val constraints =
|
||||
Constraints
|
||||
.Builder()
|
||||
|
|
@ -75,12 +100,18 @@ class SuggestionsSchedulerService
|
|||
val periodicWorkRequestBuilder =
|
||||
PeriodicWorkRequestBuilder<SuggestionsWorker>(
|
||||
repeatInterval = 12.hours.toJavaDuration(),
|
||||
flexTimeInterval = 1.hours.toJavaDuration(),
|
||||
).setConstraints(constraints)
|
||||
.setBackoffCriteria(
|
||||
BackoffPolicy.EXPONENTIAL,
|
||||
15.minutes.toJavaDuration(),
|
||||
).setInputData(inputData)
|
||||
.setInitialDelay(60.seconds.toJavaDuration())
|
||||
.addTag("user:$userId")
|
||||
|
||||
val initialDelaySeconds = initialDelaySecondsProvider().coerceIn(60L, 180L)
|
||||
periodicWorkRequestBuilder.setInitialDelay(initialDelaySeconds.seconds.toJavaDuration())
|
||||
|
||||
Timber.i("Scheduling periodic SuggestionsWorker with ${initialDelaySeconds}s delay")
|
||||
|
||||
workManager.enqueueUniquePeriodicWork(
|
||||
uniqueWorkName = SuggestionsWorker.WORK_NAME,
|
||||
|
|
|
|||
|
|
@ -99,11 +99,17 @@ class SuggestionsWorker
|
|||
itemsPerRow,
|
||||
)
|
||||
ensureActive()
|
||||
val newIds = suggestions.map { it.id }
|
||||
val cachedIds = cache.get(userId, view.id, itemKind)?.ids
|
||||
if (cachedIds == newIds) {
|
||||
Timber.v("Suggestions unchanged for view %s, skipping cache write", view.id)
|
||||
return@runCatching
|
||||
}
|
||||
cache.put(
|
||||
userId,
|
||||
view.id,
|
||||
itemKind,
|
||||
suggestions.map { it.id },
|
||||
newIds,
|
||||
)
|
||||
}.onFailure { e ->
|
||||
Timber.e(
|
||||
|
|
@ -242,7 +248,7 @@ class SuggestionsWorker
|
|||
GetItemsRequest(
|
||||
parentId = parentId,
|
||||
userId = userId,
|
||||
fields = listOf(ItemFields.PRIMARY_IMAGE_ASPECT_RATIO, ItemFields.OVERVIEW) + extraFields,
|
||||
fields = extraFields,
|
||||
includeItemTypes = listOf(itemKind),
|
||||
genreIds = genreIds,
|
||||
recursive = true,
|
||||
|
|
@ -252,7 +258,7 @@ class SuggestionsWorker
|
|||
sortOrder = sortOrder?.let { listOf(it) },
|
||||
limit = limit,
|
||||
enableTotalRecordCount = false,
|
||||
imageTypeLimit = 1,
|
||||
imageTypeLimit = 0,
|
||||
)
|
||||
return GetItemsRequestHandler
|
||||
.execute(api, request)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue