Skip to content

Commit

Permalink
fully async cache
Browse files Browse the repository at this point in the history
  • Loading branch information
anonvt committed Jul 23, 2024
1 parent 95f62b8 commit 8e67a02
Showing 1 changed file with 72 additions and 76 deletions.
148 changes: 72 additions & 76 deletions TopsortAnalytics/src/main/java/com/topsort/analytics/CacheAsync.kt
Original file line number Diff line number Diff line change
@@ -1,26 +1,26 @@
package com.topsort.analytics

import android.content.Context
import android.content.SharedPreferences
import android.text.TextUtils
import androidx.datastore.core.DataStore
import androidx.datastore.preferences.core.Preferences
import androidx.datastore.preferences.core.edit
import androidx.datastore.preferences.core.longPreferencesKey
import androidx.datastore.preferences.core.stringPreferencesKey
import androidx.datastore.preferences.preferencesDataStore
import com.topsort.analytics.model.ClickEvent
import com.topsort.analytics.model.ImpressionEvent
import com.topsort.analytics.model.PurchaseEvent
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.runBlocking
import java.util.Locale

private const val preferencesName = "TOPSORT_EVENTS_CACHE"

private val KEY_TOKEN = stringPreferencesKey("KEY_TOKEN")
private val KEY_SESSION_ID = stringPreferencesKey("KEY_SESSION_ID")
private const val KEY_RECORD = "KEY_RECORD_%d"
private const val KEY_RECENT_RECORD_ID = "KEY_RECORD_ID"
private val KEY_OPAQUE_USER_ID = stringPreferencesKey("KEY_OPAQUE_USER_ID")
private const val KEY_RECORD_FORMAT = "KEY_RECORD_%d"
private val KEY_RECENT_RECORD_ID = longPreferencesKey("KEY_RECORD_ID")

val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = "settings")

Expand All @@ -30,132 +30,128 @@ internal object CacheAsync {

private var recentRecordId: Long = 0

var token: String = ""
set(value) {
field = value
runBlocking {
applicationContext.dataStore.edit{ store ->
store[KEY_TOKEN] = value
}
}
}
private var token: String = ""
fun getToken() = token

private suspend fun setToken(value: String) {
token = value
applicationContext.dataStore.edit { store ->
store[KEY_TOKEN] = value
}
}

var sessionId: String = ""
set(value) {
field = value
runBlocking {
applicationContext.dataStore.edit { store ->
store[KEY_SESSION_ID] = value
}
}
private var opaqueUserId: String = ""
fun getOpaqueUserId() = opaqueUserId
private suspend fun setOpaqueUserId(value: String){
opaqueUserId = value
applicationContext.dataStore.edit { store ->
store[KEY_OPAQUE_USER_ID] = value
}
}

fun initialize(context: Context) {
private fun initialize(context: Context) {
applicationContext = context.applicationContext


applicationContext.dataStore.data
.map { store ->
store[KEY_TOKEN]
}

token = preferences.getString(KEY_TOKEN, "")!!
sessionId = preferences.getString(KEY_SESSION_ID, "")!!
runBlocking {
val store = applicationContext.dataStore.data.first()
token = store[KEY_TOKEN] ?: ""
opaqueUserId = store[KEY_OPAQUE_USER_ID] ?: ""
}
}

fun setup(
context: Context,
sessionId: String,
opaqueUserId: String,
token: String
) {
initialize(context)

recentRecordId = preferences.getLong(KEY_RECENT_RECORD_ID, 0)
this.sessionId = sessionId
runBlocking {
val store = applicationContext.dataStore.data.first()
recentRecordId = store[KEY_RECENT_RECORD_ID] ?: 0L
}

this.opaqueUserId = opaqueUserId
this.token = token
}

fun storeImpression(
suspend fun storeImpression(
impressionEvent: ImpressionEvent
): Long {
val json = impressionEvent.toJsonObject().toString()
preferences
.edit()
.putString(nextRecordKey(), json)
.apply()

return recentRecordId
return storeEvent(json)
}

fun readImpression(recordId: Long): ImpressionEvent? {
suspend fun readImpression(recordId: Long): ImpressionEvent? {
return ImpressionEvent.fromJson(readEvent(recordId))
}

fun storeClick(
suspend fun storeClick(
clickEvent: ClickEvent
): Long {
val json = clickEvent.toJsonObject().toString()
preferences
.edit()
.putString(nextRecordKey(), json)
.apply()

return recentRecordId
return storeEvent(json)
}

fun readClick(recordId: Long): ClickEvent? {
suspend fun readClick(recordId: Long): ClickEvent? {
return ClickEvent.fromJson(readEvent(recordId))
}

fun storePurchase(
suspend fun storePurchase(
purchaseEvent: PurchaseEvent
): Long {
val json = purchaseEvent.toJsonObject().toString()
preferences
.edit()
.putString(nextRecordKey(), json)
.apply()

return recentRecordId
return storeEvent(json)
}

fun readPurchase(recordId: Long): PurchaseEvent? {
suspend fun readPurchase(recordId: Long): PurchaseEvent? {
return PurchaseEvent.fromJson(readEvent(recordId))
}

fun deleteEvent(recordId: Long) {
preferences
.edit()
.remove(recordKey(recordId))
.apply()
suspend fun deleteEvent(recordId: Long) {
applicationContext.dataStore.edit { store ->
store.remove(recordKey(recordId))
}
}

private fun readEvent(recordId: Long): String? {
val json = preferences.getString(recordKey(recordId), "")
private suspend fun readEvent(recordId: Long): String? {
val json = applicationContext.dataStore.data.first()[recordKey(recordId)] ?: ""
if (TextUtils.isEmpty(json)) {
return null
}

return json
}

private fun recordKey(recordId: Long) = String.format(
Locale.ENGLISH,
KEY_RECORD,
recordId
private suspend fun storeEvent(json: String): Long {
val recordId = nextRecordKey()
applicationContext.dataStore.edit { store ->
store[recordId] = json
}

return recentRecordId
}

private fun recordKey(recordId: Long) = stringPreferencesKey(
String.format(
Locale.ENGLISH,
KEY_RECORD_FORMAT,
recordId
)
)

private fun nextRecordKey(): String {
private suspend fun nextRecordKey(): Preferences.Key<String> {
recentRecordId = if (recentRecordId < Long.MAX_VALUE) {
recentRecordId + 1
} else {
0
}

preferences
.edit()
.putLong(KEY_RECENT_RECORD_ID, recentRecordId)
.apply()
return recordKey(recentRecordId)
val recentRecordKey = recordKey(recentRecordId)

applicationContext.dataStore.edit { store ->
store[KEY_RECENT_RECORD_ID] = recentRecordId
}

return recentRecordKey
}
}

0 comments on commit 8e67a02

Please sign in to comment.