mirror of
https://github.com/meshtastic/Meshtastic-Android.git
synced 2026-07-12 06:15:55 -04:00
fix(firmware): never offer an alpha release older than current stable (#6198)
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -75,7 +75,8 @@ open class FirmwareReleaseRepositoryImpl(
|
||||
private fun getLatestFirmware(releaseType: FirmwareReleaseType): Flow<FirmwareRelease?> = staleWhileRevalidateFlow(
|
||||
loadFromCache = {
|
||||
ensureSeeded()
|
||||
localDataSource.getLatestRelease(releaseType)?.asExternalModel()
|
||||
val latest = localDataSource.getLatestRelease(releaseType)?.asExternalModel()
|
||||
if (releaseType == FirmwareReleaseType.ALPHA) latest.notBelowStable() else latest
|
||||
},
|
||||
shouldFetch = { cached ->
|
||||
cached == null || localDataSource.getLatestRelease(releaseType)?.isStale() != false
|
||||
@@ -93,6 +94,17 @@ open class FirmwareReleaseRepositoryImpl(
|
||||
localDataSource.deleteAllFirmwareReleases()
|
||||
}
|
||||
|
||||
/**
|
||||
* After a stable promotion the alpha channel lags behind stable — never offer a downgrade. Reads the cached stable
|
||||
* row (every refresh writes both types together, so it is as fresh as the alpha row) rather than combining with
|
||||
* [stableRelease], which would run a second revalidate pipeline — and potentially a duplicate network refresh — for
|
||||
* every alpha collector.
|
||||
*/
|
||||
private suspend fun FirmwareRelease?.notBelowStable(): FirmwareRelease? {
|
||||
val stable = localDataSource.getLatestRelease(FirmwareReleaseType.STABLE)?.asExternalModel()
|
||||
return if (this != null && stable != null && asDeviceVersion() < stable.asDeviceVersion()) stable else this
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the bundled snapshot per release type whenever it is newer than what is cached for that type — not just
|
||||
* when the cache is empty. The bundle is refreshed weekly in CI, so an app update carries fresh data even for users
|
||||
|
||||
@@ -228,6 +228,18 @@ class FirmwareReleaseRepositoryImplTest {
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun alphaChannelNeverOffersVersionBelowStable() = runBlocking {
|
||||
// After a promotion the newest alpha (2.7.25) is older than stable (2.7.26) — offer stable instead.
|
||||
dao.insert(FirmwareReleaseEntity(id = "v2.7.26.54e0d8d", releaseType = FirmwareReleaseType.STABLE))
|
||||
dao.insert(FirmwareReleaseEntity(id = "v2.7.25.104df5f", releaseType = FirmwareReleaseType.ALPHA))
|
||||
assertEquals("v2.7.26.54e0d8d", repository.alphaRelease.toList().last()?.id)
|
||||
|
||||
// A genuinely newer alpha is still offered.
|
||||
dao.insert(FirmwareReleaseEntity(id = "v2.7.27.abc1234", releaseType = FirmwareReleaseType.ALPHA))
|
||||
assertEquals("v2.7.27.abc1234", repository.alphaRelease.toList().last()?.id)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun olderBundledSnapshotNeverRegressesCache() = runBlocking {
|
||||
// A successful network refresh left the cache newer than the (weekly) bundle.
|
||||
|
||||
Reference in New Issue
Block a user