mirror of
https://github.com/austinried/subtracks.git
synced 2026-11-11 07:29:14 +01:00
address review: test the source wiring, one default, clamp the stored value
- Add a `SourceRepositoryTest` that sets the preference to 1 and proves the active source fetches sequentially; removing the `maxConcurrentFetches` wiring now fails it. - `playlistSongsRespectsASmallerFetchBound` now holds the first `bound` fetches and asserts no `(bound + 1)`th starts, instead of timing an overlap; it fails when the semaphore ignores the bound. - One `DEFAULT_FETCH_CONCURRENCY` (in `data.source`) backs both the source default and the preference default, so they cannot drift. - Clamp the stored preference in `syncConcurrency()` too, so a bad stored value can't make `SubsonicSource` throw on construction.
This commit is contained in:
@@ -8,6 +8,7 @@ import androidx.datastore.preferences.core.intPreferencesKey
|
||||
import androidx.datastore.preferences.core.stringPreferencesKey
|
||||
import androidx.datastore.preferences.preferencesDataStore
|
||||
import com.subtracks.data.net.NetworkMode
|
||||
import com.subtracks.data.source.DEFAULT_FETCH_CONCURRENCY
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.first
|
||||
import kotlinx.coroutines.flow.map
|
||||
@@ -43,8 +44,6 @@ data class StreamQuality(
|
||||
val transcodes: Boolean get() = maxBitrate > 0 || !format.isNullOrEmpty()
|
||||
}
|
||||
|
||||
const val DEFAULT_SYNC_CONCURRENCY = 4
|
||||
|
||||
private val Context.preferences: DataStore<Preferences> by preferencesDataStore("user_prefs")
|
||||
|
||||
data class ArtworkSeedValue(
|
||||
@@ -79,7 +78,7 @@ class UserPreferences(
|
||||
|
||||
private fun streamQualityKey(mode: NetworkMode) = stringPreferencesKey("stream_quality_${mode.key}")
|
||||
|
||||
fun syncConcurrency(): Flow<Int> = store.data.map { prefs -> prefs[syncConcurrencyKey] ?: DEFAULT_SYNC_CONCURRENCY }
|
||||
fun syncConcurrency(): Flow<Int> = store.data.map { prefs -> (prefs[syncConcurrencyKey] ?: DEFAULT_FETCH_CONCURRENCY).coerceAtLeast(1) }
|
||||
|
||||
suspend fun setSyncConcurrency(value: Int) {
|
||||
store.edit { prefs -> prefs[syncConcurrencyKey] = value.coerceAtLeast(1) }
|
||||
|
||||
@@ -7,6 +7,8 @@ import com.subtracks.data.model.PlaylistSong
|
||||
import com.subtracks.data.model.Song
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
const val DEFAULT_FETCH_CONCURRENCY = 4
|
||||
|
||||
interface MusicSource {
|
||||
val id: Long
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ import com.subtracks.data.model.Artist
|
||||
import com.subtracks.data.model.Playlist
|
||||
import com.subtracks.data.model.PlaylistSong
|
||||
import com.subtracks.data.model.Song
|
||||
import com.subtracks.data.source.DEFAULT_FETCH_CONCURRENCY
|
||||
import com.subtracks.data.source.MusicSource
|
||||
import com.subtracks.data.source.StarType
|
||||
import kotlinx.coroutines.CancellationException
|
||||
@@ -34,7 +35,7 @@ class SubsonicSource(
|
||||
private val maxBitrate: Int = 0,
|
||||
private val streamFormat: String? = null,
|
||||
private val maxPages: Int = MAX_PAGES,
|
||||
private val maxConcurrentFetches: Int = MAX_CONCURRENT_FETCHES,
|
||||
private val maxConcurrentFetches: Int = DEFAULT_FETCH_CONCURRENCY,
|
||||
) : MusicSource {
|
||||
private var emptyQuerySearchSupported: Boolean? = null
|
||||
|
||||
@@ -306,8 +307,6 @@ class SubsonicSource(
|
||||
}
|
||||
}
|
||||
|
||||
internal const val MAX_CONCURRENT_FETCHES = 4
|
||||
|
||||
private class PageCapExceeded(
|
||||
message: String,
|
||||
) : SubsonicException(-1, message)
|
||||
|
||||
@@ -4,11 +4,11 @@ import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.subtracks.data.model.Source
|
||||
import com.subtracks.data.net.NetworkMode
|
||||
import com.subtracks.data.prefs.DEFAULT_SYNC_CONCURRENCY
|
||||
import com.subtracks.data.prefs.StreamQuality
|
||||
import com.subtracks.data.prefs.UserPreferences
|
||||
import com.subtracks.data.repo.DownloadRepository
|
||||
import com.subtracks.data.repo.SourceRepository
|
||||
import com.subtracks.data.source.DEFAULT_FETCH_CONCURRENCY
|
||||
import kotlinx.coroutines.flow.SharingStarted
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.stateIn
|
||||
@@ -38,7 +38,7 @@ class SettingsViewModel(
|
||||
val syncConcurrency: StateFlow<Int> =
|
||||
userPreferences
|
||||
.syncConcurrency()
|
||||
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(5_000), DEFAULT_SYNC_CONCURRENCY)
|
||||
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(5_000), DEFAULT_FETCH_CONCURRENCY)
|
||||
|
||||
fun selectSource(id: Long) {
|
||||
viewModelScope.launch { sourceRepository.selectSource(id) }
|
||||
|
||||
Reference in New Issue
Block a user