Skip to content

fix: discard stale resolve responses and add @Volatile to InMemoryCache#230

Merged
nicklasl merged 3 commits intomainfrom
nicklasl/test-reproduce-android-default-value-race-condition
Mar 16, 2026
Merged

fix: discard stale resolve responses and add @Volatile to InMemoryCache#230
nicklasl merged 3 commits intomainfrom
nicklasl/test-reproduce-android-default-value-race-condition

Conversation

@nicklasl
Copy link
Member

@nicklasl nicklasl commented Mar 13, 2026

Summary

Fixes intermittent default value returns on Android:

  • Stale context check in fetch(): When the evaluation context changes during an in-flight resolve request, the response is now discarded instead of being stored to disk.
  • @Volatile on InMemoryCache.flagResolution: Ensures cross-thread visibility on ARM/Android so writes from Dispatchers.IO are visible to reads on the main thread.

Test plan

  • testStaleResolveResponseDiscardedWhenContextChanged — verified RED without fix, GREEN with fix
  • testContextChangeTriggersRefetchAndEvaluationDuringFetchReturnsStale — stale evaluation during re-fetch
  • testFetchAndActivateDoesNotReturnDefaultValues — positive control

🤖 Generated with Claude Code

@nicklasl nicklasl force-pushed the nicklasl/test-reproduce-android-default-value-race-condition branch from c152d27 to 5bef712 Compare March 13, 2026 10:29
@nicklasl nicklasl changed the title test: reproduce Android race conditions causing default value returns fix: discard stale resolve responses when context changes during flight Mar 13, 2026
@nicklasl nicklasl force-pushed the nicklasl/test-reproduce-android-default-value-race-condition branch from 5bef712 to cc9e526 Compare March 13, 2026 12:30
@nicklasl nicklasl changed the title fix: discard stale resolve responses when context changes during flight fix: discard stale resolve responses and add @Volatile to InMemoryCache Mar 13, 2026
nicklasl and others added 2 commits March 13, 2026 14:08
Tests assert expected behavior:
- Stale resolve responses must be discarded when context changes during flight
- Flag evaluation returns stale values (not defaults) during re-fetch
- FetchAndActivate correctly resolves and activates flags

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Check resolve response context against current context before storing
  to disk. Prevents storing flag values for an outdated context.
- Add @volatile to InMemoryCache.flagResolution for cross-thread
  visibility on ARM/Android.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@nicklasl nicklasl force-pushed the nicklasl/test-reproduce-android-default-value-race-condition branch from cc9e526 to 0529024 Compare March 13, 2026 13:24
Comment on lines +262 to +272
// Discard stale responses: if context changed during the
// in-flight request, the response is for an outdated context
if (resolveResponse.data.context == getContext()) {
diskStorage.store(resolveResponse.data)
} else {
debugLogger?.logMessage(
"Discarding stale resolve response: " +
"context changed during in-flight request",
isWarning = true
)
}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is in addition to cancelling the coroutine that makes the network request, so twice the safety?

@nicklasl nicklasl marked this pull request as ready for review March 13, 2026 14:27
@nicklasl nicklasl merged commit 8fa647b into main Mar 16, 2026
2 checks passed
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