Skip to content

Commit

Permalink
Add Flag API
Browse files Browse the repository at this point in the history
Use flag value LOCAL_STOPS_ENABLED to either call api or use local stops data for feching stops
  • Loading branch information
ksharma-xyz committed Feb 28, 2025
1 parent 12b807b commit f990c51
Show file tree
Hide file tree
Showing 8 changed files with 86 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ internal class RealRemoteConfig(
*/
private suspend fun setDebugFetchInterval() {
if (appInfoProvider.getAppInfo().isDebug) {
remoteConfig.settings { minimumFetchInterval = 10.minutes }
remoteConfig.settings { minimumFetchInterval = 1.minutes }
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ object RemoteConfigDefaults {
fun getDefaults(): Array<Pair<String, Any?>> {
return arrayOf(
Pair("test", false),
Pair("local_stops_enabled", true),
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import kotlinx.coroutines.SupervisorJob
import org.koin.dsl.module
import xyz.ksharma.krail.core.remote_config.RealRemoteConfig
import xyz.ksharma.krail.core.remote_config.RemoteConfig
import xyz.ksharma.krail.core.remote_config.flag.Flag
import xyz.ksharma.krail.core.remote_config.flag.RemoteConfigFlag

val remoteConfigModule = module {
single<RemoteConfig> {
Expand All @@ -14,4 +16,8 @@ val remoteConfigModule = module {
coroutineScope = CoroutineScope(context = SupervisorJob() + Dispatchers.Default),
)
}

single<Flag> {
RemoteConfigFlag(remoteConfig = get())
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package xyz.ksharma.krail.core.remote_config.flag

interface Flag {
fun getFlagValue(key: String): FlagValue
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package xyz.ksharma.krail.core.remote_config.flag

enum class FlagKeys(val key: String) {
LOCAL_STOPS_ENABLED("local_stops_enabled")
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package xyz.ksharma.krail.core.remote_config.flag

sealed class FlagValue {
data class BooleanValue(val value: Boolean) : FlagValue()
data class StringValue(val value: String) : FlagValue()
}

fun FlagValue.asBoolean(): Boolean {
return when (this) {
is FlagValue.BooleanValue -> this.value
is FlagValue.StringValue -> this.value.toBoolean()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package xyz.ksharma.krail.core.remote_config.flag

import xyz.ksharma.krail.core.log.log
import xyz.ksharma.krail.core.remote_config.RemoteConfig

internal class RemoteConfigFlag(private val remoteConfig: RemoteConfig) : Flag {

override fun getFlagValue(key: String): FlagValue {
val configValue = remoteConfig.getConfigValue(key)
log("RemoteConfigFlag: getFlagValue: key=$key, configValue=$configValue")

return when (configValue.asString().toBooleanStrictOrNull()) {
true, false -> FlagValue.BooleanValue(configValue.asBoolean())
else -> FlagValue.StringValue(configValue.asString())
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,14 @@ import xyz.ksharma.krail.core.analytics.Analytics
import xyz.ksharma.krail.core.analytics.AnalyticsScreen
import xyz.ksharma.krail.core.analytics.event.AnalyticsEvent
import xyz.ksharma.krail.core.analytics.event.trackScreenViewEvent
import xyz.ksharma.krail.core.log.log
import xyz.ksharma.krail.core.remote_config.flag.Flag
import xyz.ksharma.krail.core.remote_config.flag.FlagKeys
import xyz.ksharma.krail.core.remote_config.flag.asBoolean
import xyz.ksharma.krail.sandook.Sandook
import xyz.ksharma.krail.sandook.SelectProductClassesForStop
import xyz.ksharma.krail.trip.planner.network.api.service.TripPlanningService
import xyz.ksharma.krail.trip.planner.ui.searchstop.StopResultMapper.toStopResults
import xyz.ksharma.krail.trip.planner.ui.state.TransportMode
import xyz.ksharma.krail.trip.planner.ui.state.TransportModeSortOrder
import xyz.ksharma.krail.trip.planner.ui.state.searchstop.SearchStopState
Expand All @@ -29,6 +34,7 @@ class SearchStopViewModel(
private val tripPlanningService: TripPlanningService,
private val analytics: Analytics,
private val sandook: Sandook,
private val flag: Flag,
) : ViewModel() {

private val _uiState: MutableStateFlow<SearchStopState> = MutableStateFlow(SearchStopState())
Expand All @@ -39,6 +45,10 @@ class SearchStopViewModel(

private var searchJob: Job? = null

private val isLocalStopsEnabled: Boolean by lazy {
flag.getFlagValue(FlagKeys.LOCAL_STOPS_ENABLED.key).asBoolean()
}

fun onEvent(event: SearchStopUiEvent) {
when (event) {
is SearchStopUiEvent.SearchTextChanged -> onSearchTextChanged(event.query)
Expand All @@ -53,39 +63,43 @@ class SearchStopViewModel(
//log(("onSearchTextChanged: $query")
updateUiState { displayLoading() }
searchJob?.cancel()
// TODO - cancel previous flow before starting new one.
searchJob = viewModelScope.launch {
delay(300)
delay(150)
runCatching {
/* val response = tripPlanningService.stopFinder(stopSearchQuery = query)
log("response VM: $response")
val results = response.toStopResults()
log("results: $results")*/

val resultsDb: List<SelectProductClassesForStop> =
sandook.selectStops(stopName = query, excludeProductClassList = listOf())

val stopResults = resultsDb
.map { it.toStopResult() }
.let {
filterProductClasses(
stopResults = it,
excludedProductClasses = listOf(TransportMode.Ferry().productClass).toImmutableList()
)
}
.let(::prioritiseStops)
.take(50)

val stopResults = fetchStopResults(query)
updateUiState { displayData(stopResults) }
}.getOrElse {
delay(1500) // buffer for API response before displaying error.
// TODO- ideally cache all stops and error will never happen.
updateUiState { displayError() }
}
}
}

private suspend fun fetchStopResults(query: String): List<SearchStopState.StopResult> =
if (isLocalStopsEnabled) {
log("fetchStopResults from LOCAL_STOPS")
val resultsDb: List<SelectProductClassesForStop> =
sandook.selectStops(stopName = query, excludeProductClassList = listOf())

val results = resultsDb
.map { it.toStopResult() }
.let {
filterProductClasses(
stopResults = it,
excludedProductClasses = listOf(TransportMode.Ferry().productClass).toImmutableList()
)
}
.let(::prioritiseStops)
.take(50)

results
} else {
log("fetchStopResults from REMOTE")
val response = tripPlanningService.stopFinder(stopSearchQuery = query)
log("response VM: $response")
response.toStopResults()
}

// TODO - move to another file and add UT for it. Inject and use.
private fun prioritiseStops(stopResults: List<SearchStopState.StopResult>): List<SearchStopState.StopResult> {
val sortedTransportModes = TransportMode.sortedValues(TransportModeSortOrder.PRIORITY)
Expand All @@ -109,8 +123,7 @@ class SearchStopViewModel(
"200030",
"200046",
"200050",

)
)

return stopResults.sortedWith(compareBy(
{ stopResult ->
Expand Down

0 comments on commit f990c51

Please sign in to comment.