Skip to content

Commit e291c73

Browse files
committed
fix(tokens): prevent stale metadata from persisting over fresh network data
The 3-tier metadata lookup (memory → Room → network) short-circuited on cache hits, never reaching the network to refresh stale icon/description. Add a background refresh on cache hits so fresh metadata eventually replaces persisted data. Also remove symbol-based Coil cache keys that prevented image updates when the URL changed — Coil now keys on URL (its default) so new images are picked up naturally. Signed-off-by: Brandon McAnsh <git@bmcreations.dev>
1 parent 9f2e8aa commit e291c73

2 files changed

Lines changed: 44 additions & 3 deletions

File tree

apps/flipcash/core/src/main/kotlin/com/flipcash/app/core/ui/TokenImageWithName.kt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,9 +98,7 @@ fun TokenIcon(
9898
.data(imageUrl)
9999
.crossfade(false)
100100
.error(R.drawable.ic_placeholder_user)
101-
.memoryCacheKey(symbol)
102101
.memoryCachePolicy(CachePolicy.ENABLED)
103-
.diskCacheKey(symbol)
104102
.diskCachePolicy(CachePolicy.ENABLED)
105103
.build(),
106104
contentDescription = null,

apps/flipcash/shared/tokens/src/main/kotlin/com/flipcash/app/tokens/TokenCoordinator.kt

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ class TokenCoordinator @Inject constructor(
100100

101101
private val cluster = MutableStateFlow<AccountCluster?>(null)
102102
private val fetchingMints = ConcurrentHashMap.newKeySet<Mint>()
103+
private val refreshingMints = ConcurrentHashMap.newKeySet<Mint>()
103104

104105
data class TokenState(
105106
val tokens: Map<Mint, Token> = emptyMap(),
@@ -215,11 +216,16 @@ class TokenCoordinator @Inject constructor(
215216
/**
216217
* 3-tier lookup: in-memory → Room → network (via [TokenController]).
217218
* Each hit hydrates the layer above it.
219+
*
220+
* Cache hits return immediately for fast UI, but also trigger a background
221+
* network refresh so that stale metadata (icon, description, etc.) is
222+
* eventually replaced with fresh data.
218223
*/
219224
override suspend fun getTokenMetadata(mint: Mint): Result<TokenResult> {
220225
// 1. In-memory cache
221226
_state.value.tokens[mint]?.let { cached ->
222227
trace(tag = TAG, message = "Token metadata memory hit for ${cached.symbol}", type = TraceType.Silent)
228+
refreshMetadataInBackground(mint)
223229
return Result.success(TokenResult(cached, DataSource.Memory))
224230
}
225231

@@ -229,6 +235,7 @@ class TokenCoordinator @Inject constructor(
229235
_state.update { state ->
230236
state.copy(tokens = state.tokens + (persisted.address to persisted))
231237
}
238+
refreshMetadataInBackground(mint)
232239
return Result.success(TokenResult(persisted, DataSource.Cache))
233240
}
234241

@@ -250,6 +257,42 @@ class TokenCoordinator @Inject constructor(
250257
}
251258
}
252259

260+
/**
261+
* Fires a background network fetch for fresh metadata.
262+
* If the response differs from the cached version, both in-memory
263+
* state and Room are updated so the UI picks up changes.
264+
*/
265+
private fun refreshMetadataInBackground(mint: Mint) {
266+
if (!refreshingMints.add(mint)) return // already refreshing
267+
268+
scope.launch {
269+
try {
270+
tokenController.getTokenMetadata(mint)
271+
.onSuccess { result ->
272+
val fresh = result.token
273+
val cached = _state.value.tokens[mint]
274+
275+
// Only update if metadata actually changed
276+
if (cached != null && fresh == cached) return@launch
277+
278+
trace(tag = TAG, message = "Background refresh updated metadata for ${fresh.symbol}", type = TraceType.Silent)
279+
280+
_state.update { state ->
281+
state.copy(tokens = state.tokens + (fresh.address to fresh))
282+
}
283+
284+
if (accountController.hasAccountFor(fresh.address)) {
285+
dataSource.upsert(listOf(fresh))
286+
}
287+
}
288+
} finally {
289+
refreshingMints.remove(mint)
290+
}
291+
}
292+
}
293+
294+
295+
253296
// endregion
254297

255298
// region Public API — Selection & Updates
@@ -481,4 +524,4 @@ class TokenCoordinator @Inject constructor(
481524
}
482525

483526
// endregion
484-
}
527+
}

0 commit comments

Comments
 (0)