Skip to content

feat: cache user favorites to local database#326

Closed
arkon wants to merge 11 commits intomainfrom
claude/cache-user-favourites-Oae8A
Closed

feat: cache user favorites to local database#326
arkon wants to merge 11 commits intomainfrom
claude/cache-user-favourites-Oae8A

Conversation

@arkon
Copy link
Copy Markdown
Contributor

@arkon arkon commented Feb 24, 2026

Introduces a two-table Room database (songs + favourites) so the app can
show cached favourites instantly on launch while refreshing in the background.

  • songs table stores song metadata; structured to later hold all songs
  • favourites table has a FK to songs and is cleared when a different user
    logs in (detected via uuid stored in SharedPreferences)
  • UserService now reads from the DB cache before the network response
    arrives, then replaces the cache with fresh data
  • Favourite toggles keep the DB in sync via the existing favoriteEvents flow

https://claude.ai/code/session_011KtuHPsAhM395DnPGr6Zcs

Introduces a two-table Room database (songs + favourites) so the app can
show cached favourites instantly on launch while refreshing in the background.

- songs table stores song metadata; structured to later hold all songs
- favourites table has a FK to songs and is cleared when a different user
  logs in (detected via uuid stored in SharedPreferences)
- UserService now reads from the DB cache before the network response
  arrives, then replaces the cache with fresh data
- Favourite toggles keep the DB in sync via the existing favoriteEvents flow

https://claude.ai/code/session_011KtuHPsAhM395DnPGr6Zcs
@arkon arkon changed the title Add Room database with local cache for user favourites feat: cache user favorites to local database Feb 24, 2026
@arkon
Copy link
Copy Markdown
Contributor Author

arkon commented Feb 24, 2026

Code review

Found 1 issue:

  1. @Transaction on a concrete suspend fun in a Kotlin DAO interface is not honored by Room's annotation processor — replaceAll is not atomic. Room only generates a transaction wrapper for abstract methods or methods in abstract classes; it does not wrap concrete default interface methods. As a result, deleteAll() and insertAll() each run in their own transaction, leaving a window where the favourites table is empty. A concurrent read (e.g., from the favoriteEvents collector) could observe zero favourites during this gap. Fix by changing FavouritesDao from an interface to an abstract class, or by using withTransaction { } from room-ktx.

suspend fun deleteAll()
@Transaction
suspend fun replaceAll(favourites: List<FavouriteEntity>) {
deleteAll()
insertAll(favourites)
}
}

🤖 Generated with Claude Code

- If this code review was useful, please react with 👍. Otherwise, react with 👎.

@arkon arkon closed this Apr 3, 2026
@arkon arkon deleted the claude/cache-user-favourites-Oae8A branch April 3, 2026 22:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants