Skip to content

Commit

Permalink
cache results
Browse files Browse the repository at this point in the history
  • Loading branch information
DatL4g committed Mar 9, 2024
1 parent ac7168d commit 1cce9ee
Show file tree
Hide file tree
Showing 5 changed files with 117 additions and 17 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package dev.datlag.burningseries.model

import kotlinx.datetime.Clock
import kotlinx.datetime.Instant
import kotlin.time.Duration
import kotlin.time.Duration.Companion.hours

class Cacheable<T>(private val timeAlive: Duration = 2.hours) {
private var cachedOn: Instant? = null
private var data: T? = null

fun cache(data: T): T {
this.data = data
this.cachedOn = Clock.System.now()
return data
}

fun getAlive(): T? {
val cacheTime = cachedOn ?: return null

return if (cacheTime.epochSeconds < Clock.System.now().minus(timeAlive).epochSeconds) {
null
} else {
data
}
}

fun getUnAlive(): T? {
return data
}

operator fun get(unAlive: Boolean = false): T? {
return if (unAlive) {
getUnAlive()
} else {
getAlive()
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,18 @@ class HomeStateMachine(
private val json: Json,
private val wrapApi: WrapAPI,
private val wrapApiKey: String?
) : FlowReduxStateMachine<HomeState, HomeAction>(initialState = NetworkStateSaver.initialHomeState) {
) : FlowReduxStateMachine<HomeState, HomeAction>(initialState = currentState) {
init {
spec {
inState<HomeState.Loading> {
onEnterEffect {
NetworkStateSaver.initialHomeState = it
currentState = it
}
onEnter { state ->
NetworkStateSaver.Cache.home.getAlive()?.let {
return@onEnter state.override { HomeState.Success(it.first, it.second) }
}

val result = suspendCatchResult {
var onDeviceReachable: Boolean = true
val loadedHome = BurningSeries.getHome(client) ?: run {
Expand All @@ -37,6 +41,7 @@ class HomeStateMachine(
}!!

if (loadedHome.episodes.isNotEmpty() || loadedHome.series.isNotEmpty()) {
NetworkStateSaver.Cache.home.cache(loadedHome to onDeviceReachable)
HomeState.Success(loadedHome, onDeviceReachable)
} else {
HomeState.Error
Expand All @@ -45,22 +50,36 @@ class HomeStateMachine(
result.onError {
Napier.e("HomeStateError", it)
}
state.override { result.asSuccess { HomeState.Error } }
state.override {
result.asSuccess {
NetworkStateSaver.Cache.home.getUnAlive()?.let {
HomeState.Success(it.first, it.second)
} ?: HomeState.Error
}
}
}
}
inState<HomeState.Success> {
onEnterEffect {
NetworkStateSaver.initialHomeState = it
currentState = it
}
}
inState<HomeState.Error> {
onEnterEffect {
NetworkStateSaver.initialHomeState = it
currentState = it
}
on<HomeAction.Retry> { _, state ->
state.override { HomeState.Loading }
}
}
}
}

companion object {
var currentState: HomeState
set(value) {
NetworkStateSaver.initialHomeState = value
}
get() = NetworkStateSaver.initialHomeState
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
package dev.datlag.burningseries.network.state

import dev.datlag.burningseries.model.Cacheable
import dev.datlag.burningseries.model.Genre
import dev.datlag.burningseries.model.Home
import dev.datlag.burningseries.model.Release
import dev.datlag.burningseries.model.state.*
import dev.gitlive.firebase.auth.FirebaseUser

Expand All @@ -15,4 +19,10 @@ data object NetworkStateSaver {
var initialHomeState: HomeState = HomeState.Loading
var initialReleaseState: ReleaseState = ReleaseState.Loading
var initialSearchState: SearchState = SearchState.Loading

internal data object Cache {
val home: Cacheable<Pair<Home, Boolean>> = Cacheable()
val release: Cacheable<List<Release>> = Cacheable()
val search: Cacheable<List<Genre>> = Cacheable()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,40 +9,56 @@ import kotlinx.coroutines.ExperimentalCoroutinesApi
@OptIn(ExperimentalCoroutinesApi::class)
class ReleaseStateMachine(
private val gitHub: GitHub
) : FlowReduxStateMachine<ReleaseState, Nothing>(initialState = NetworkStateSaver.initialReleaseState) {
) : FlowReduxStateMachine<ReleaseState, Nothing>(initialState = currentState) {
init {
spec {
inState<ReleaseState.Loading> {
onEnterEffect {
NetworkStateSaver.initialReleaseState = it
currentState = it
}
onEnter { state ->
NetworkStateSaver.Cache.release.getAlive()?.let {
return@onEnter state.override { ReleaseState.Success(it) }
}

val result = suspendCatchResult {
val releases = gitHub.getReleases(owner = "DatL4g", repo = "Burning-Series")
val filtered = releases.filterNot { it.draft || it.preRelease }

if (filtered.isEmpty()) {
ReleaseState.Error
} else {
ReleaseState.Success(filtered)
ReleaseState.Success(filtered.also {
NetworkStateSaver.Cache.release.cache(it)
})
}
}.asSuccess {
ReleaseState.Error
NetworkStateSaver.Cache.release.getUnAlive()?.let {
ReleaseState.Success(it)
} ?: ReleaseState.Error
}

state.override { result }
}
}
inState<ReleaseState.Success> {
onEnterEffect {
NetworkStateSaver.initialReleaseState = it
currentState = it
}
}
inState<ReleaseState.Error> {
onEnterEffect {
NetworkStateSaver.initialReleaseState = it
currentState = it
}
}
}
}

companion object {
var currentState: ReleaseState
set(value) {
NetworkStateSaver.initialReleaseState = value
}
get() = NetworkStateSaver.initialReleaseState
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,18 @@ class SearchStateMachine(
private val wrapApiKey: String?,
private val saveToDB: suspend (SearchState.Success) -> Unit,
private val loadFromDB: suspend () -> List<Genre>
) : FlowReduxStateMachine<SearchState, SearchAction>(initialState = NetworkStateSaver.initialSearchState) {
) : FlowReduxStateMachine<SearchState, SearchAction>(initialState = currentState) {
init {
spec {
inState<SearchState.Loading> {
onEnterEffect {
NetworkStateSaver.initialSearchState = it
currentState = it
}
onEnter { state ->
NetworkStateSaver.Cache.search.getAlive()?.let {
return@onEnter state.override { SearchState.Success(it) }
}

val result = suspendCatchResult {
val loadedClient = suspendCatching {
BurningSeries.getSearch(client)
Expand All @@ -55,10 +59,14 @@ class SearchStateMachine(
if (loadedGenres.isEmpty()) {
SearchState.Error
} else {
SearchState.Success(loadedGenres)
SearchState.Success(loadedGenres.also {
NetworkStateSaver.Cache.search.cache(it)
})
}
}.asSuccess {
SearchState.Error
NetworkStateSaver.Cache.search.getUnAlive()?.let {
SearchState.Success(it)
} ?: SearchState.Error
}

state.override { result }
Expand All @@ -67,19 +75,27 @@ class SearchStateMachine(

inState<SearchState.Success> {
onEnterEffect {
NetworkStateSaver.initialSearchState = it
currentState = it
saveToDB(it)
}
}

inState<SearchState.Error> {
onEnterEffect {
NetworkStateSaver.initialSearchState = it
currentState = it
}
on<SearchAction.Retry> { _, state ->
state.override { SearchState.Loading }
}
}
}
}

companion object {
var currentState: SearchState
set(value) {
NetworkStateSaver.initialSearchState = value
}
get() = NetworkStateSaver.initialSearchState
}
}

0 comments on commit 1cce9ee

Please sign in to comment.