Skip to content

Commit

Permalink
Include retry mechanism in multiple coroutines flow
Browse files Browse the repository at this point in the history
Numerous streams of data in the Kotlin coroutines flow now have the retry operator included. This optimizes error handling by implementing automated retries upon encountering failures. The modification affects key parts of the code, such as PackageListViewModel, PackageSearchProjectService, and several viewModel modules related to UI and project services.

(cherry picked from commit 7e2f7a5)
  • Loading branch information
lamba92 authored and fscarponi committed Jan 11, 2024
1 parent a05a2ea commit 8fa6499
Show file tree
Hide file tree
Showing 5 changed files with 35 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.asFlow
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.consumeAsFlow
import kotlinx.coroutines.flow.debounce
Expand All @@ -43,6 +42,8 @@ import kotlinx.coroutines.flow.flatMapMerge
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.retry
import kotlinx.coroutines.flow.retryWhen
import kotlinx.coroutines.flow.shareIn
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.sync.Mutex
Expand All @@ -69,7 +70,12 @@ class PackageSearchProjectService(
.apiPackageCache
.getKnownRepositories()
.associateBy { it.id }
}.stateIn(coroutineScope, SharingStarted.Eagerly, emptyMap())
}
.retry {
logWarn("${this::class.simpleName}#knownRepositoriesStateFlow", throwable = it)
true
}
.stateIn(coroutineScope, SharingStarted.Eagerly, emptyMap())

override val knownRepositories: Map<String, ApiRepository>
get() = knownRepositoriesStateFlow.value
Expand Down Expand Up @@ -114,20 +120,15 @@ class PackageSearchProjectService(
private var counter = 0
private val counterMutex = Mutex()

private suspend fun restartWithCounter() = counterMutex.withLock {
if (counter++ < 3) {
restart()
}
}

private suspend fun resetCounter() = counterMutex.withLock { counter = 0 }

val modulesStateFlow = restartFlow
.withInitialValue(Unit)
.flatMapLatest { moduleProvidersList }
.catch {
logWarn("${this::class.simpleName}#modulesStateFlow", throwable = it)
restartWithCounter()
.retryWhen { cause, attempt ->
logWarn("${this::class.simpleName}#modulesStateFlow", throwable = cause)
restart()
attempt < 3
}
.onEach { resetCounter() }
.stateIn(coroutineScope, SharingStarted.Eagerly, emptyList())
Expand All @@ -144,12 +145,20 @@ class PackageSearchProjectService(

stableOnlyStateFlow
.onEach { logOnlyStableToggle(it) }
.retry {
logWarn("${this::class.simpleName}#stableOnlyStateFlow", throwable = it)
true
}
.launchIn(coroutineScope)

IntelliJApplication.PackageSearchApplicationCachesService
.isOnlineFlow
.filter { it }
.onEach { restart() }
.retry {
logWarn("${this::class.simpleName}#isOnlineFlow", throwable = it)
true
}
.launchIn(coroutineScope)

combine(
Expand All @@ -169,6 +178,10 @@ class PackageSearchProjectService(
?.let { DaemonCodeAnalyzer.getInstance(project).restart(it) }
}
}
.retry {
logWarn("${this::class.simpleName}#fileOpenedFlow", throwable = it)
true
}
.launchIn(coroutineScope)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.debounce
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.retry
import kotlinx.coroutines.flow.stateIn
import org.jetbrains.compose.splitpane.SplitPaneState

Expand Down Expand Up @@ -76,6 +77,7 @@ class ToolWindowViewModel(project: Project, private val viewModelScope: Coroutin
else -> PackageSearchToolWindowState.NoModules
}
}
.retry()
.stateIn(
scope = viewModelScope,
started = SharingStarted.Lazily,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.mapNotNull
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.retry
import kotlinx.coroutines.flow.stateIn
import org.jetbrains.packagesearch.api.v3.ApiPackage

Expand Down Expand Up @@ -73,6 +74,7 @@ class InfoPanelViewModel(
}
}
}
.retry()
.stateIn(viewModelScope, SharingStarted.Eagerly, emptyList())

private val activeTabTitleMutableStateFlow: MutableStateFlow<String?> = MutableStateFlow(null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.mapLatest
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.retry
import kotlinx.coroutines.flow.shareIn
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.flow.update
Expand Down Expand Up @@ -165,14 +166,16 @@ class PackageListViewModel(
else -> value
}
}
}.modifiedBy(selectedModulesFlow) { current: Map<PackageListItem.Header.Id.Remote, Search>, change ->
}
.modifiedBy(selectedModulesFlow) { current: Map<PackageListItem.Header.Id.Remote, Search>, change ->
val changeIdentities = change.map { it.identity }
if (current.keys.any { it.moduleIdentity !in changeIdentities }) {
emptyMap()
} else {
current
}
}
.retry()
.stateIn(viewModelScope, SharingStarted.Eagerly, emptyMap())

val selectableLazyListState = SelectableLazyListState(LazyListState())
Expand Down Expand Up @@ -204,6 +207,7 @@ class PackageListViewModel(
}
}
}
.retry()
.stateIn(viewModelScope, SharingStarted.Eagerly, emptyList())

private suspend fun PackageSearchModule.Base.getSearchQuery(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.retry
import kotlinx.coroutines.flow.stateIn
import org.jetbrains.jewel.foundation.lazy.SelectableLazyListState
import org.jetbrains.jewel.foundation.lazy.tree.Tree
Expand All @@ -29,6 +30,7 @@ internal class TreeViewModel(
) { modules, stableOnly ->
modules.asTree(stableOnly)
}
.retry()
.stateIn(viewModelScope, SharingStarted.Lazily, emptyTree())

internal val lazyListState = LazyListState()
Expand Down

0 comments on commit 8fa6499

Please sign in to comment.