[github] put coroutine scope into context instead of implementing disposable

GitOrigin-RevId: 581550f992c29ab6da8e7463fcd7ce4dc4feae18
This commit is contained in:
Ivan Semenov
2023-01-10 18:49:08 +01:00
committed by intellij-monorepo-bot
parent 18ca780a98
commit 32805ddfc2
2 changed files with 34 additions and 38 deletions

View File

@@ -1,8 +1,11 @@
// Copyright 2000-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package org.jetbrains.plugins.github.pullrequest.data
import com.intellij.openapi.Disposable
import com.intellij.openapi.util.Disposer
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.awaitCancellation
import kotlinx.coroutines.launch
import org.jetbrains.plugins.github.api.data.pullrequest.GHPullRequest
import org.jetbrains.plugins.github.pullrequest.GHPRDiffRequestModel
import org.jetbrains.plugins.github.pullrequest.data.service.GHPRCreationService
@@ -11,7 +14,8 @@ import org.jetbrains.plugins.github.pullrequest.data.service.GHPRRepositoryDataS
import org.jetbrains.plugins.github.pullrequest.data.service.GHPRSecurityService
import org.jetbrains.plugins.github.ui.avatars.GHAvatarIconsProvider
internal class GHPRDataContext(val listLoader: GHPRListLoader,
internal class GHPRDataContext(val scope: CoroutineScope,
val listLoader: GHPRListLoader,
val listUpdatesChecker: GHPRListUpdatesChecker,
val dataProviderRepository: GHPRDataProviderRepository,
val securityService: GHPRSecurityService,
@@ -20,7 +24,7 @@ internal class GHPRDataContext(val listLoader: GHPRListLoader,
val detailsService: GHPRDetailsService,
val avatarIconsProvider: GHAvatarIconsProvider,
val filesManager: GHPRFilesManager,
val newPRDiffModel: GHPRDiffRequestModel) : Disposable {
val newPRDiffModel: GHPRDiffRequestModel) {
private val listenersDisposable = Disposer.newDisposable("GH PR context listeners disposable")
@@ -38,14 +42,20 @@ internal class GHPRDataContext(val listLoader: GHPRListLoader,
?: dataProviderRepository.findDataProvider(file.pullRequest)?.detailsData?.loadedDetails
if (details != null) filesManager.updateTimelineFilePresentation(details)
}
}
override fun dispose() {
Disposer.dispose(filesManager)
Disposer.dispose(listenersDisposable)
Disposer.dispose(dataProviderRepository)
Disposer.dispose(listLoader)
Disposer.dispose(listUpdatesChecker)
Disposer.dispose(repositoryDataService)
// need immediate to dispose in time
scope.launch(Dispatchers.Main.immediate) {
try {
awaitCancellation()
}
finally {
Disposer.dispose(filesManager)
Disposer.dispose(listenersDisposable)
Disposer.dispose(dataProviderRepository)
Disposer.dispose(listLoader)
Disposer.dispose(listUpdatesChecker)
Disposer.dispose(repositoryDataService)
}
}
}
}

View File

@@ -10,8 +10,8 @@ import com.intellij.openapi.components.service
import com.intellij.openapi.diagnostic.logger
import com.intellij.openapi.progress.*
import com.intellij.openapi.project.Project
import com.intellij.openapi.util.Disposer
import com.intellij.util.IconUtil
import com.intellij.util.childScope
import com.intellij.util.ui.ImageUtil
import git4idea.remote.GitRemoteUrlCoordinates
import icons.CollaborationToolsIcons
@@ -51,8 +51,9 @@ internal class GHPRDataContextRepository(private val project: Project) : Disposa
val existing = cache[repository]
if (existing != null) return@withLock existing
try {
val context = withContext(Dispatchers.IO) {
loadContext(account, requestExecutor, repository, remote)
val contextScope = cs.childScope()
val context = withContext(contextScope.coroutineContext) {
loadContext(contextScope, account, requestExecutor, repository, remote)
}
cache[repository] = context
context
@@ -65,17 +66,16 @@ internal class GHPRDataContextRepository(private val project: Project) : Disposa
}
suspend fun clearContext(repository: GHRepositoryCoordinates) {
cacheGuard.withLock {
withContext(cs.coroutineContext) {
cache.remove(repository)?.let {
Disposer.dispose(it)
}
withContext(cs.coroutineContext) {
cacheGuard.withLock {
cache.remove(repository)?.scope?.coroutineContext?.get(Job)?.cancelAndJoin()
}
}
}
@Throws(IOException::class)
private suspend fun loadContext(account: GithubAccount,
private suspend fun loadContext(contextScope: CoroutineScope,
account: GithubAccount,
requestExecutor: GithubApiRequestExecutor,
parsedRepositoryCoordinates: GHRepositoryCoordinates,
remoteCoordinates: GitRemoteUrlCoordinates): GHPRDataContext {
@@ -147,17 +147,15 @@ internal class GHPRDataContextRepository(private val project: Project) : Disposa
repoOwner,
repositoryInfo.id, repositoryInfo.defaultBranch, repositoryInfo.isFork)
val iconsScope = MainScope()
val iconsScope = contextScope.childScope(Dispatchers.Main)
val avatarIconsProvider = CachingIconsProvider(AsyncImageIconsProvider(iconsScope, ImageLoader(requestExecutor)))
val filesManager = GHPRFilesManagerImpl(project, parsedRepositoryCoordinates)
val creationService = GHPRCreationServiceImpl(ProgressManager.getInstance(), requestExecutor, repoDataService)
return GHPRDataContext(listLoader, listUpdatesChecker, dataProviderRepository,
return GHPRDataContext(contextScope, listLoader, listUpdatesChecker, dataProviderRepository,
securityService, repoDataService, creationService, detailsService, avatarIconsProvider, filesManager,
GHPRDiffRequestModelImpl()).also {
Disposer.register(it, Disposable { iconsScope.cancel() })
}
GHPRDiffRequestModelImpl())
}
private class ImageLoader(private val requestExecutor: GithubApiRequestExecutor)
@@ -178,19 +176,7 @@ internal class GHPRDataContextRepository(private val project: Project) : Disposa
// dangerous to do this without lock, but making it suspendable is too much work
fun findContext(repositoryCoordinates: GHRepositoryCoordinates): GHPRDataContext? = cache[repositoryCoordinates]
override fun dispose() {
runBlocking { cacheGuard.lock() }
try {
val toDispose = cache.values.toList()
cache.clear()
toDispose.forEach {
Disposer.dispose(it)
}
}
finally {
runBlocking { cacheGuard.unlock() }
}
}
override fun dispose() = Unit
companion object {
private val LOG = logger<GHPRDataContextRepository>()