Skip to content

Instantly share code, notes, and snippets.

@Aidanvii7
Last active March 30, 2024 11:47
Show Gist options
  • Save Aidanvii7/14b6557d03f8b133b9af01c7f797267a to your computer and use it in GitHub Desktop.
Save Aidanvii7/14b6557d03f8b133b9af01c7f797267a to your computer and use it in GitHub Desktop.
possible solution to syncing the OtrKeyManagerStoreImpl with a Room DB
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
import kotlin.io.encoding.Base64
import kotlin.io.encoding.ExperimentalEncodingApi
interface OtrKeyManagerStore {
fun getPropertyBytes(key: String): ByteArray
}
class OtrKeyManagerStoreImpl(
private val propertyCache: PropertyCache,
) : OtrKeyManagerStore {
@OptIn(ExperimentalEncodingApi::class)
override fun getPropertyBytes(key: String): ByteArray =
Base64.decode(propertyCache.getEncodedProperty(key))
}
@Entity
data class Property(
@PrimaryKey val key: String,
val value: String
)
interface MyDao {
@Query("SELECT * FROM Property")
fun getProperties(): Flow<List<Property>>
}
class PropertyCache {
private val cachedPropertiesMutex = Mutex()
private val cachedProperties = mutableMapOf<String, String>()
// called from OtrKeyManagerStoreImpl
fun getEncodedProperty(key: String): String {
val property: String? = runBlocking {
cachedPropertiesMutex.withLock { cachedProperties[key] }
}
return checkNotNull(property) { "no property found with key: $key" }
}
// called from MyRepository
suspend fun update(properties: List<Property>) {
cachedPropertiesMutex.withLock {
cachedProperties.clear()
cachedProperties.putAll(properties.associate { (key, value) -> key to value })
}
}
}
class MyRepository(
private val myDao: MyDao,
private val propertyCache: PropertyCache,
) {
init {
syncCacheWithDao()
}
@OptIn(DelicateCoroutinesApi::class) // possibly use your own CoroutineScope instead
private fun syncCacheWithDao() {
myDao.getProperties()
// whenever you push to the Dao, this should run and update the in memory cache
.onEach { propertyCache.update(it) }
.launchIn(GlobalScope)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment