mirror of
https://github.com/austinried/subtracks.git
synced 2026-11-15 00:42:54 +01:00
library: unify artist credit totals and backfill song counts
Use songCount as the total for both artist status queries and stop excluding albumless tracks from download attribution, so the Artists badge and the artist page agree. Backfill song counts in the 29->30 migration for offline upgrades, and recompute only when a song moves albums or its credits change rather than on every play-metadata sync.
This commit is contained in:
@@ -153,6 +153,30 @@ class MigrationsTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun theArtistSongCountBackfillCountsLegacyCredits() =
|
||||
runTest {
|
||||
driver.open(":memory:").use { migrated ->
|
||||
applySchema(migrated, 29)
|
||||
migrated.execSQL(
|
||||
"INSERT INTO sources (id, name, address, isActive, createdAt) VALUES (1, 's', 'http://x', 1, 0)",
|
||||
)
|
||||
migrated.execSQL("INSERT INTO artists (sourceId, id, name, albumCount) VALUES (1, 'ar1', 'Album Artist', 1)")
|
||||
migrated.execSQL("INSERT INTO artists (sourceId, id, name, albumCount) VALUES (1, 'ar2', 'Guest', 0)")
|
||||
migrated.execSQL(
|
||||
"INSERT INTO albums (sourceId, id, artistId, name, albumArtist, created, songCount) " +
|
||||
"VALUES (1, 'al1', 'ar1', 'Album', 'Album Artist', 0, 1)",
|
||||
)
|
||||
migrated.execSQL("INSERT INTO songs (sourceId, id, albumId, artistId, title) VALUES (1, 's1', 'al1', 'ar1', 'One')")
|
||||
migrated.execSQL("INSERT INTO songs (sourceId, id, albumId, artistId, title) VALUES (1, 's2', NULL, 'ar2', 'Two')")
|
||||
|
||||
MIGRATION_29_30.migrate(migrated)
|
||||
|
||||
assertEquals(1L, long(migrated, "SELECT songCount FROM artists WHERE id = 'ar1'"))
|
||||
assertEquals(1L, long(migrated, "SELECT songCount FROM artists WHERE id = 'ar2'"))
|
||||
}
|
||||
}
|
||||
|
||||
private fun text(
|
||||
connection: SQLiteConnection,
|
||||
sql: String,
|
||||
|
||||
@@ -647,7 +647,17 @@ class DownloadRepositoryTest {
|
||||
),
|
||||
)
|
||||
db.libraryDao().upsertArtists(
|
||||
listOf(Artist(sourceId = 1, id = "ar-guest", name = "Guest", albumCount = 0, starred = null, coverArt = null)),
|
||||
listOf(
|
||||
Artist(
|
||||
sourceId = 1,
|
||||
id = "ar-guest",
|
||||
name = "Guest",
|
||||
albumCount = 0,
|
||||
starred = null,
|
||||
coverArt = null,
|
||||
songCount = 1,
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -999,6 +999,71 @@ class SyncServiceTest {
|
||||
assertEquals(0L, db.libraryDao().artistOnce(1, "a2")!!.songCount)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun artistSongCountsAndDownloadsIncludeAlbumlessTracks() =
|
||||
runTest {
|
||||
insertSource()
|
||||
val source =
|
||||
FakeMusicSource(
|
||||
artists = listOf(artist("a1", "A")),
|
||||
songs =
|
||||
listOf(
|
||||
song("s1").copy(albumId = null),
|
||||
song("s2").copy(albumId = null),
|
||||
),
|
||||
)
|
||||
|
||||
SyncService(db, source).sync()
|
||||
|
||||
assertEquals(2L, db.libraryDao().artistOnce(1, "a1")!!.songCount)
|
||||
db.downloadDao().upsert(SongDownload(1, "s1", DownloadStatus.Completed))
|
||||
db.downloadDao().upsert(SongDownload(1, "s2", DownloadStatus.Completed))
|
||||
|
||||
assertEquals(
|
||||
ListDownloadStatus(total = 2, downloaded = 2),
|
||||
db.downloadDao().artistStatus(1, "a1").first(),
|
||||
)
|
||||
assertEquals(
|
||||
2L,
|
||||
db
|
||||
.downloadDao()
|
||||
.artistStatuses(1)
|
||||
.first()
|
||||
.single { it.id == "a1" }
|
||||
.downloaded,
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun movingASongBetweenAlbumsUpdatesAlbumArtistCounts() =
|
||||
runTest {
|
||||
insertSource()
|
||||
val source =
|
||||
FakeMusicSource(
|
||||
artists = listOf(artist("a1", "A"), artist("a2", "B"), artist("a3", "Track")),
|
||||
albums =
|
||||
listOf(
|
||||
album("al1").copy(artistId = "a1"),
|
||||
album("al2").copy(artistId = "a2"),
|
||||
),
|
||||
songs = listOf(song("s1").copy(artistId = "a3", albumId = "al1")),
|
||||
)
|
||||
|
||||
SyncService(db, source).sync()
|
||||
|
||||
assertEquals(1L, db.libraryDao().artistOnce(1, "a1")!!.songCount)
|
||||
assertEquals(0L, db.libraryDao().artistOnce(1, "a2")!!.songCount)
|
||||
assertEquals(1L, db.libraryDao().artistOnce(1, "a3")!!.songCount)
|
||||
|
||||
source.songs = listOf(song("s1").copy(artistId = "a3", albumId = "al2"))
|
||||
|
||||
SyncService(db, source).sync()
|
||||
|
||||
assertEquals(0L, db.libraryDao().artistOnce(1, "a1")!!.songCount)
|
||||
assertEquals(1L, db.libraryDao().artistOnce(1, "a2")!!.songCount)
|
||||
assertEquals(1L, db.libraryDao().artistOnce(1, "a3")!!.songCount)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun anIdenticalSyncDoesNotRewriteArtistRows() =
|
||||
runTest {
|
||||
|
||||
Reference in New Issue
Block a user