mirror of
https://github.com/austinried/subtracks.git
synced 2026-11-15 00:42:54 +01:00
sync: make queue reset publication recoverable
This commit is contained in:
@@ -474,6 +474,25 @@ class QueueRepositoryTest {
|
||||
repository.removeAt(snapshot, 0)
|
||||
|
||||
assertEquals(listOf("s2", "s3"), resolveAll(repository.snapshot()))
|
||||
fun aMatchingOriginStillPublishesWhenItsEntriesDoNotChange() =
|
||||
runTest {
|
||||
seedLibrary()
|
||||
db.libraryDao().upsertSongs(listOf(song("s0", "al1", track = 0, album = "First Album")))
|
||||
setPlaylist("p1", "s1", "s2", "s3")
|
||||
repository.snapshotAfter(listOf(repository.playlistEntry(1, "p1")))
|
||||
repository.setCursor(1)
|
||||
val point = repository.captureResetPoint()
|
||||
var resets = 0
|
||||
repository.setResetListener {
|
||||
resets++
|
||||
QueueResetPreparation(it.snapshot)
|
||||
}
|
||||
|
||||
setPlaylist("p1", "s0", "s1", "s2", "s3")
|
||||
repository.resetChangedOrigins(setOf(QueueOrigin(QueueKind.Playlist, 1, "p1")), point)
|
||||
|
||||
assertEquals(1, resets)
|
||||
assertEquals(2L, repository.cursor())
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -387,6 +387,42 @@ class SyncManagerTest {
|
||||
assertTrue(db.queueDao().pendingSyncOrigins(1).isEmpty())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun aPublicationFailureRecoversFromCommittedReset() =
|
||||
runBlocking {
|
||||
server.dispatcher = healthyDispatcher()
|
||||
sourceRepository.addSource("Local", server.url("/").toString(), "u", "p", useTokenAuth = false)
|
||||
queueRepository.replace(listOf(queueRepository.albumEntry(1, "al1").copy(rangeStart = 0, rangeEnd = 0)))
|
||||
val before = queueRepository.snapshot()
|
||||
val recoveries = AtomicInteger()
|
||||
queueRepository.setResetListener { reset ->
|
||||
QueueResetPreparation(
|
||||
reset.snapshot,
|
||||
publish = { throw IllegalStateException("publish failed") },
|
||||
recover = { published ->
|
||||
assertEquals(before.version + 1, published.version)
|
||||
assertEquals(before.resetVersion + 1, published.resetVersion)
|
||||
recoveries.incrementAndGet()
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
manager.requestSync()
|
||||
withTimeout(TEST_TIMEOUT_MS) { manager.status.first { it is SyncStatus.Success } }
|
||||
|
||||
assertEquals(1, recoveries.get())
|
||||
assertNull(
|
||||
queueRepository
|
||||
.snapshot()
|
||||
.entries
|
||||
.single()
|
||||
.entry.rangeStart,
|
||||
)
|
||||
assertTrue(db.queueDao().pendingSyncOrigins(1).isEmpty())
|
||||
assertEquals(before.version + 1, queueRepository.contentVersion())
|
||||
assertEquals(before.resetVersion + 1, queueRepository.snapshot().resetVersion)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun aQueueWriteFailureAfterPendingClearRollsBackWithoutPublishing() =
|
||||
runBlocking {
|
||||
|
||||
@@ -48,6 +48,9 @@ class FakePlayerHandle : PlayerHandle {
|
||||
@Volatile
|
||||
var beforeRemoveFirst: (() -> Unit)? = null
|
||||
|
||||
@Volatile
|
||||
var beforeCurrentItem: (() -> Unit)? = null
|
||||
|
||||
@Volatile
|
||||
var roundTripItemsThroughMedia3 = false
|
||||
|
||||
@@ -86,6 +89,7 @@ class FakePlayerHandle : PlayerHandle {
|
||||
|
||||
override val currentItem: QueueItem?
|
||||
get() {
|
||||
beforeCurrentItem?.invoke()
|
||||
checkThread()
|
||||
return items.getOrNull(index)
|
||||
}
|
||||
|
||||
@@ -3598,6 +3598,36 @@ class PlaybackControllerTest {
|
||||
assertEquals(listOf("s0", "s1", "s2", "s3", "s4", "s5"), handle.items.map { it.id })
|
||||
}
|
||||
|
||||
@Test
|
||||
fun aTransitionBetweenResetPreparationAndPublicationRebuildsFromCommittedState() {
|
||||
seedPlaylist(5)
|
||||
seedSong("s0", "al1")
|
||||
controller.playPlaylist(1, "p1", 2)
|
||||
await { handle.currentItem?.id == "s3" && controller.state.value.isPlaying }
|
||||
val point = runBlocking { queues.captureResetPoint() }
|
||||
var currentItemReads = 0
|
||||
handle.beforeCurrentItem = {
|
||||
currentItemReads++
|
||||
if (currentItemReads == 2) {
|
||||
handle.beforeCurrentItem = null
|
||||
handle.advanceTo(3)
|
||||
}
|
||||
}
|
||||
handle.beforeRemoveFirst = {
|
||||
handle.beforeRemoveFirst = null
|
||||
handle.advanceTo(3)
|
||||
}
|
||||
|
||||
setPlaylist("s0", "s1", "s2", "s3", "s4", "s5")
|
||||
runBlocking { queues.resetChangedOrigins(setOf(QueueOrigin(QueueKind.Playlist, 1, "p1")), point) }
|
||||
|
||||
await {
|
||||
handle.currentItem?.id == "s4" && controller.state.value.position == 3L &&
|
||||
handle.items.size == 5 && handle.items.distinctBy { it.id }.size == 5
|
||||
}
|
||||
assertEquals(listOf("s1", "s2", "s3", "s4", "s5"), handle.items.map { it.id })
|
||||
}
|
||||
|
||||
@Test
|
||||
fun aSourceResetLetsTheRemovedCurrentFinishBeforeTheClampedTrack() {
|
||||
seedPlaylist(5)
|
||||
|
||||
Reference in New Issue
Block a user