fix(app-phone): звук при watch (диагностика+подстраховка mirrorByItem) + качка не воскресает после удаления
- onWatch: явные логи в каждой точке отказа (watch result / audio source / уже играет / не скачано / mediaDir пуст), свежий mirrorByItem если files не догрузился, звук стартует с позиции очков при уже идущем видео - resolveAudioSource → resolveAudioSourceDetailed (AudioSourceResult с причиной null) - DownloadManager: поколения generations — delete() инвалидирует старую корутину (не воскрешает качку), ensureActive перед .part/rename, jobs.remove(itemId, job) - Тесты 62/0 (в т.ч. поколения — поймали null != 0L) Инфраструктурный блокер (не код): SeaweedFS на Server3 76.66 в IO-шторме (load ~184, wa 20%, чужой yt-dlp на хосте) — большие GET с s3.binom.pw висят/рвутся с ~14:00; качка на очки FAILED по этой причине.
This commit is contained in:
@@ -15,6 +15,8 @@ import kotlinx.serialization.decodeFromString
|
||||
import kotlinx.serialization.encodeToString
|
||||
import pw.binom.viewmate.core.GlassesMode
|
||||
import pw.binom.viewmate.core.phone.PhoneState
|
||||
import pw.binom.viewmate.core.protocol.DownloadPhase
|
||||
import pw.binom.viewmate.core.protocol.DownloadProgress
|
||||
import pw.binom.viewmate.core.protocol.Gesture
|
||||
import pw.binom.viewmate.core.protocol.GlassesStatus
|
||||
import pw.binom.viewmate.core.protocol.GlassesToHost
|
||||
@@ -112,6 +114,55 @@ class GlassesServerTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun downloadProgressUpdatesHubPerFileMap() = testApplication {
|
||||
val hub = GlassesHub(PhoneState())
|
||||
application { glassesServerModule(hub) }
|
||||
val client = createClient { install(WebSockets) }
|
||||
|
||||
client.webSocket(GLASSES_WS_PATH) {
|
||||
send(json.encodeToString(GlassesToHost.serializer(), DownloadProgress("i1", "video.mkv", 45, 450, 1000, DownloadPhase.DOWNLOADING)))
|
||||
send(json.encodeToString(GlassesToHost.serializer(), DownloadProgress("i1", "audio-0.ogg", 100, 100, 100, DownloadPhase.DONE)))
|
||||
}
|
||||
|
||||
awaitTrue { hub.glassesDownloads.value["i1"]?.size == 2 }
|
||||
assertEquals(45, hub.glassesDownloads.value["i1"]?.get("video.mkv")?.percent)
|
||||
assertEquals(DownloadPhase.DONE, hub.glassesDownloads.value["i1"]?.get("audio-0.ogg")?.phase)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun extendedGlassesStatusUpdatesHubFields() = testApplication {
|
||||
val hub = GlassesHub(PhoneState())
|
||||
application { glassesServerModule(hub) }
|
||||
val client = createClient { install(WebSockets) }
|
||||
|
||||
client.webSocket(GLASSES_WS_PATH) {
|
||||
send(
|
||||
json.encodeToString(
|
||||
GlassesToHost.serializer(),
|
||||
GlassesStatus(
|
||||
batteryPercent = 60,
|
||||
storageUsedGb = 12.5,
|
||||
storageTotalGb = 32.0,
|
||||
storageTotalBytes = 34_359_738_368,
|
||||
storageFreeBytes = 20_971_520_000,
|
||||
mediaBytes = 1_863_946_240,
|
||||
downloadedItemIds = listOf("i1", "i2"),
|
||||
mediaDir = "/data/glasses/files/viewmate",
|
||||
appVersion = "0.2.0",
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
awaitTrue { hub.downloadedItemIds.value.contains("i1") }
|
||||
assertEquals(34_359_738_368L, hub.storageTotalBytes.value)
|
||||
assertEquals(20_971_520_000L, hub.storageFreeBytes.value)
|
||||
assertEquals(1_863_946_240L, hub.mediaBytes.value)
|
||||
assertEquals("/data/glasses/files/viewmate", hub.mediaDir.value)
|
||||
assertEquals("0.2.0", hub.appVersion.value)
|
||||
}
|
||||
|
||||
private suspend fun awaitTrue(timeoutMs: Long = 10_000, condition: () -> Boolean) {
|
||||
val deadline = System.currentTimeMillis() + timeoutMs
|
||||
while (!condition()) {
|
||||
|
||||
Reference in New Issue
Block a user