From 62d498f6270d9701f8eec299641bb2eb4744843d Mon Sep 17 00:00:00 2001 From: Daniel M Date: Mon, 8 Apr 2024 08:04:04 -0400 Subject: [PATCH] refactor:remove dataloader --- .../ghmanager/actions/PostWorkflowActions.kt | 2 +- .../ghmanager/api/GetJobLogRequest.kt | 3 +- .../com/dsoftware/ghmanager/api/GithubApi.kt | 2 +- .../data/JobsLoadingModelListener.kt | 4 +- .../data/WorkflowDataContextService.kt | 11 +-- .../data/WorkflowRunSelectionContext.kt | 73 ++++++++++++++----- .../ghmanager/data/providers/DataProvider.kt | 3 +- ...obsDataProvider.kt => JobsDataProvider.kt} | 5 +- .../data/providers/LogDataProvider.kt | 5 +- .../data/providers/SingleRunDataLoader.kt | 60 --------------- 10 files changed, 67 insertions(+), 101 deletions(-) rename src/main/kotlin/com/dsoftware/ghmanager/data/providers/{WorkflowRunJobsDataProvider.kt => JobsDataProvider.kt} (74%) delete mode 100644 src/main/kotlin/com/dsoftware/ghmanager/data/providers/SingleRunDataLoader.kt diff --git a/src/main/kotlin/com/dsoftware/ghmanager/actions/PostWorkflowActions.kt b/src/main/kotlin/com/dsoftware/ghmanager/actions/PostWorkflowActions.kt index 87ccfd2a..771fd517 100644 --- a/src/main/kotlin/com/dsoftware/ghmanager/actions/PostWorkflowActions.kt +++ b/src/main/kotlin/com/dsoftware/ghmanager/actions/PostWorkflowActions.kt @@ -33,7 +33,7 @@ abstract class PostUrlAction( getUrl(e.dataContext)?.let { val request = GithubApi.postUrl(text, it, getData(e.dataContext)) val context = e.getRequiredData(ActionKeys.ACTION_DATA_CONTEXT) - val future = context.dataLoader.createDataProvider(request).request + val future = context.createDataProvider(request).request future.thenApply { afterPostUrl() } diff --git a/src/main/kotlin/com/dsoftware/ghmanager/api/GetJobLogRequest.kt b/src/main/kotlin/com/dsoftware/ghmanager/api/GetJobLogRequest.kt index 97ce41a8..c330e33e 100644 --- a/src/main/kotlin/com/dsoftware/ghmanager/api/GetJobLogRequest.kt +++ b/src/main/kotlin/com/dsoftware/ghmanager/api/GetJobLogRequest.kt @@ -5,6 +5,7 @@ import com.dsoftware.ghmanager.api.model.Job import com.dsoftware.ghmanager.api.model.JobStep import com.dsoftware.ghmanager.i18n.MessagesBundle.message import com.intellij.openapi.diagnostic.logger +import com.intellij.util.io.HttpSecurityUtil import kotlinx.datetime.Instant import org.jetbrains.annotations.VisibleForTesting import org.jetbrains.plugins.github.api.GithubApiRequest @@ -106,7 +107,7 @@ class GetJobLogRequest(private val job: Job) : GithubApiRequest.Get(job. if (res.length + (stepLogs[stepNumber]?.length ?: 0) < 990_000) { res.append(stepLogs[stepNumber]) } else { - res.append(message("log.step.truncated", job.htmlUrl+"?#step:$stepNumber")) + res.append(message("log.step.truncated", job.htmlUrl + "?#step:$stepNumber")) } } } diff --git a/src/main/kotlin/com/dsoftware/ghmanager/api/GithubApi.kt b/src/main/kotlin/com/dsoftware/ghmanager/api/GithubApi.kt index 32cca6b0..0310d16d 100644 --- a/src/main/kotlin/com/dsoftware/ghmanager/api/GithubApi.kt +++ b/src/main/kotlin/com/dsoftware/ghmanager/api/GithubApi.kt @@ -22,7 +22,7 @@ data class WorkflowRunFilter( object GithubApi : GithubApiRequests.Entity("/repos") { private val LOG = logger() - fun getJobLog(job: Job) = GetJobLogRequest(job).withOperationName("Get Job log ${job.id}") + fun getLogForSingleJob(job: Job) = GetJobLogRequest(job).withOperationName("Get Job log ${job.id}") fun postUrl(name: String, url: String, data: Any = Object()) = GithubApiRequest.Post.Json(url, data, Object::class.java, null).withOperationName(name) diff --git a/src/main/kotlin/com/dsoftware/ghmanager/data/JobsLoadingModelListener.kt b/src/main/kotlin/com/dsoftware/ghmanager/data/JobsLoadingModelListener.kt index 50a647be..f6b6348b 100644 --- a/src/main/kotlin/com/dsoftware/ghmanager/data/JobsLoadingModelListener.kt +++ b/src/main/kotlin/com/dsoftware/ghmanager/data/JobsLoadingModelListener.kt @@ -2,7 +2,7 @@ package com.dsoftware.ghmanager.data import com.dsoftware.ghmanager.api.model.WorkflowRunJobs import com.dsoftware.ghmanager.data.providers.DataProvider -import com.dsoftware.ghmanager.data.providers.WorkflowRunJobsDataProvider +import com.dsoftware.ghmanager.data.providers.JobsDataProvider import com.intellij.collaboration.ui.SingleValueModel import com.intellij.openapi.Disposable import com.intellij.openapi.util.Disposer @@ -12,7 +12,7 @@ import org.jetbrains.plugins.github.pullrequest.ui.GHLoadingModel class JobsLoadingModelListener( workflowRunDisposable: Disposable, - dataProviderModel: SingleValueModel, + dataProviderModel: SingleValueModel, runSelectionHolder: WorkflowRunListSelectionHolder, ) : GHLoadingModel.StateChangeListener { val jobsModel = SingleValueModel(null) diff --git a/src/main/kotlin/com/dsoftware/ghmanager/data/WorkflowDataContextService.kt b/src/main/kotlin/com/dsoftware/ghmanager/data/WorkflowDataContextService.kt index 2b78b65f..95e72ac5 100644 --- a/src/main/kotlin/com/dsoftware/ghmanager/data/WorkflowDataContextService.kt +++ b/src/main/kotlin/com/dsoftware/ghmanager/data/WorkflowDataContextService.kt @@ -1,9 +1,6 @@ package com.dsoftware.ghmanager.data -import com.dsoftware.ghmanager.data.providers.SingleRunDataLoader import com.dsoftware.ghmanager.ui.settings.GhActionsSettingsService -import com.intellij.collaboration.async.CompletableFutureUtil.submitIOTask -import com.intellij.collaboration.async.CompletableFutureUtil.successOnEdt import com.intellij.openapi.components.Service import com.intellij.openapi.components.service import com.intellij.openapi.diagnostic.logger @@ -11,9 +8,7 @@ import com.intellij.openapi.progress.ProcessCanceledException import com.intellij.openapi.progress.ProgressManager import com.intellij.openapi.project.Project import com.intellij.openapi.util.CheckedDisposable -import com.intellij.openapi.util.Disposer import com.intellij.openapi.wm.ToolWindow -import com.intellij.util.concurrency.annotations.RequiresBackgroundThread import com.intellij.util.concurrency.annotations.RequiresEdt import org.jetbrains.plugins.github.api.GHRepositoryPath import org.jetbrains.plugins.github.api.GithubApiRequestExecutor @@ -23,7 +18,6 @@ import org.jetbrains.plugins.github.exceptions.GithubMissingTokenException import org.jetbrains.plugins.github.util.GHCompatibilityUtil import org.jetbrains.plugins.github.util.GHGitRepositoryMapping import org.jetbrains.plugins.github.util.LazyCancellableBackgroundProcessValue -import java.io.IOException import java.util.concurrent.CompletableFuture data class RepositoryCoordinates(val serverPath: GithubServerPath, val repositoryPath: GHRepositoryPath) @@ -56,6 +50,9 @@ class WorkflowDataContextService(private val project: Project) { } else { settingsService.state.apiToken } + + val requestExecutor = + GithubApiRequestExecutor.Factory.getInstance().create { token } if (checkedDisposable.isDisposed) { throw ProcessCanceledException( RuntimeException("Skipped creating data context for ${repositoryMapping.remote.url} because it was disposed") @@ -66,7 +63,7 @@ class WorkflowDataContextService(private val project: Project) { toolWindow, account, repositoryMapping, - token, + requestExecutor, ) } catch (e: Exception) { if (e !is ProcessCanceledException) diff --git a/src/main/kotlin/com/dsoftware/ghmanager/data/WorkflowRunSelectionContext.kt b/src/main/kotlin/com/dsoftware/ghmanager/data/WorkflowRunSelectionContext.kt index ea65e076..b3567e47 100644 --- a/src/main/kotlin/com/dsoftware/ghmanager/data/WorkflowRunSelectionContext.kt +++ b/src/main/kotlin/com/dsoftware/ghmanager/data/WorkflowRunSelectionContext.kt @@ -1,22 +1,28 @@ package com.dsoftware.ghmanager.data import com.dsoftware.ghmanager.api.WorkflowRunFilter +import com.dsoftware.ghmanager.api.model.Job +import com.dsoftware.ghmanager.api.model.WorkflowRun +import com.dsoftware.ghmanager.data.providers.DataProvider +import com.dsoftware.ghmanager.data.providers.JobsDataProvider import com.dsoftware.ghmanager.data.providers.LogDataProvider -import com.dsoftware.ghmanager.data.providers.SingleRunDataLoader -import com.dsoftware.ghmanager.data.providers.WorkflowRunJobsDataProvider import com.dsoftware.ghmanager.ui.ToolbarUtil import com.dsoftware.ghmanager.ui.panels.wfruns.LoadingErrorHandler +import com.google.common.cache.CacheBuilder import com.intellij.collaboration.ui.SingleValueModel import com.intellij.openapi.Disposable import com.intellij.openapi.diagnostic.logger import com.intellij.openapi.util.CheckedDisposable import com.intellij.openapi.util.Disposer import com.intellij.openapi.wm.ToolWindow +import com.intellij.util.EventDispatcher +import org.jetbrains.plugins.github.api.GithubApiRequest import org.jetbrains.plugins.github.api.GithubApiRequestExecutor import org.jetbrains.plugins.github.api.data.GHUser import org.jetbrains.plugins.github.authentication.accounts.GithubAccount import org.jetbrains.plugins.github.util.GHGitRepositoryMapping import org.jetbrains.plugins.github.util.GithubUrlUtil +import java.util.EventListener import java.util.concurrent.ScheduledFuture @@ -25,28 +31,33 @@ class WorkflowRunSelectionContext internal constructor( val toolWindow: ToolWindow, val account: GithubAccount, val repositoryMapping: GHGitRepositoryMapping, - token: String, + val requestExecutor: GithubApiRequestExecutor, val runSelectionHolder: WorkflowRunListSelectionHolder = WorkflowRunListSelectionHolder(), val jobSelectionHolder: JobListSelectionHolder = JobListSelectionHolder(), ) : Disposable.Parent { private val task: ScheduledFuture<*> - val requestExecutor = GithubApiRequestExecutor.Factory.getInstance().create(token = token) + val currentBranchName: String? + get() = repositoryMapping.gitRepository.currentBranchName val runsListLoader: WorkflowRunListLoader + + private val invalidationEventDispatcher = EventDispatcher.create(DataInvalidatedListener::class.java) + + private val cache = CacheBuilder.newBuilder() + .removalListener> {} + .maximumSize(200) + .build>() + var selectedRunDisposable = Disposer.newDisposable("Selected run disposable") - val jobDataProviderLoadModel: SingleValueModel = SingleValueModel(null) - val jobsDataProvider: WorkflowRunJobsDataProvider? - get() = runSelectionHolder.selection?.let { dataLoader.getJobsDataProvider(it) } + val jobDataProviderLoadModel: SingleValueModel = SingleValueModel(null) + val jobsDataProvider: JobsDataProvider? + get() = runSelectionHolder.selection?.let { getJobsDataProvider(it) } var selectedJobDisposable = Disposer.newDisposable("Selected job disposable") val logDataProviderLoadModel: SingleValueModel = SingleValueModel(null) - - val dataLoader = SingleRunDataLoader(requestExecutor) val logDataProvider: LogDataProvider? - get() = jobSelectionHolder.selection?.let { dataLoader.getJobLogDataProvider(it) } + get() = jobSelectionHolder.selection?.let { getLogDataProvider(it) } - val currentBranchName: String? - get() = repositoryMapping.gitRepository.currentBranchName init { Disposer.register(parentDisposable, this) @@ -86,12 +97,22 @@ class WorkflowRunSelectionContext internal constructor( selectedJobDisposable.dispose() selectedJobDisposable = Disposer.newDisposable("Selected job disposable") } - dataLoader.addInvalidationListener(this) {// When wf-runs are invalidated, invalidate jobs and logs - LOG.debug("invalidation listener") - jobDataProviderLoadModel.value = null - jobDataProviderLoadModel.value = null - selectedRunDisposable.dispose() - } + + } + + + private fun getLogDataProvider(job: Job): LogDataProvider { + return cache.get("${job.url}/logs") { LogDataProvider(requestExecutor, job) } as LogDataProvider + } + + private fun getJobsDataProvider(workflowRun: WorkflowRun): JobsDataProvider { + return cache.get(workflowRun.jobsUrl) { + JobsDataProvider(requestExecutor, workflowRun.jobsUrl) + } as JobsDataProvider + } + + fun createDataProvider(request: GithubApiRequest): DataProvider { + return DataProvider(requestExecutor, request, null) } fun getCurrentAccountGHUser(): GHUser { @@ -118,7 +139,9 @@ class WorkflowRunSelectionContext internal constructor( fun resetAllData() { runsListLoader.reset() runsListLoader.loadMore(true) - dataLoader.invalidateAllData() + jobDataProviderLoadModel.value = null + jobDataProviderLoadModel.value = null + selectedRunDisposable.dispose() } companion object { @@ -139,4 +162,16 @@ class WorkflowRunSelectionContext internal constructor( runsListLoader.setFilter(filter) resetAllData() } + + + fun addInvalidationListener(disposable: Disposable, listener: () -> Unit) = + invalidationEventDispatcher.addListener(object : DataInvalidatedListener { + override fun dataLoadersInvalidated() { + listener() + } + }, disposable) + + private interface DataInvalidatedListener : EventListener { + fun dataLoadersInvalidated() + } } \ No newline at end of file diff --git a/src/main/kotlin/com/dsoftware/ghmanager/data/providers/DataProvider.kt b/src/main/kotlin/com/dsoftware/ghmanager/data/providers/DataProvider.kt index fccd4027..53d103ad 100644 --- a/src/main/kotlin/com/dsoftware/ghmanager/data/providers/DataProvider.kt +++ b/src/main/kotlin/com/dsoftware/ghmanager/data/providers/DataProvider.kt @@ -14,7 +14,6 @@ import java.util.concurrent.CompletableFuture import kotlin.properties.ReadOnlyProperty open class DataProvider( - progressManager: ProgressManager, private val requestExecutor: GithubApiRequestExecutor, private val githubApiRequest: GithubApiRequest, private val errorValue: T?, @@ -22,7 +21,7 @@ open class DataProvider( private val runChangesEventDispatcher = EventDispatcher.create(DataProviderChangeListener::class.java) private val processValue: LazyCancellableBackgroundProcessValue = - LazyCancellableBackgroundProcessValue.create(progressManager) { + LazyCancellableBackgroundProcessValue.create(ProgressManager.getInstance()) { try { LOG.info("Executing ${githubApiRequest.url}") val request = githubApiRequest diff --git a/src/main/kotlin/com/dsoftware/ghmanager/data/providers/WorkflowRunJobsDataProvider.kt b/src/main/kotlin/com/dsoftware/ghmanager/data/providers/JobsDataProvider.kt similarity index 74% rename from src/main/kotlin/com/dsoftware/ghmanager/data/providers/WorkflowRunJobsDataProvider.kt rename to src/main/kotlin/com/dsoftware/ghmanager/data/providers/JobsDataProvider.kt index 77afb503..a321ad8f 100644 --- a/src/main/kotlin/com/dsoftware/ghmanager/data/providers/WorkflowRunJobsDataProvider.kt +++ b/src/main/kotlin/com/dsoftware/ghmanager/data/providers/JobsDataProvider.kt @@ -2,15 +2,12 @@ package com.dsoftware.ghmanager.data.providers import com.dsoftware.ghmanager.api.GithubApi import com.dsoftware.ghmanager.api.model.WorkflowRunJobs -import com.intellij.openapi.progress.ProgressManager import org.jetbrains.plugins.github.api.GithubApiRequestExecutor -class WorkflowRunJobsDataProvider( - progressManager: ProgressManager, +class JobsDataProvider( requestExecutor: GithubApiRequestExecutor, jobsUrl: String ) : DataProvider( - progressManager, requestExecutor, GithubApi.getWorkflowRunJobs(jobsUrl), WorkflowRunJobs(0, emptyList()) diff --git a/src/main/kotlin/com/dsoftware/ghmanager/data/providers/LogDataProvider.kt b/src/main/kotlin/com/dsoftware/ghmanager/data/providers/LogDataProvider.kt index c71bb16e..03207ba5 100644 --- a/src/main/kotlin/com/dsoftware/ghmanager/data/providers/LogDataProvider.kt +++ b/src/main/kotlin/com/dsoftware/ghmanager/data/providers/LogDataProvider.kt @@ -2,16 +2,13 @@ package com.dsoftware.ghmanager.data.providers import com.dsoftware.ghmanager.api.GithubApi import com.dsoftware.ghmanager.api.model.Job -import com.intellij.openapi.progress.ProgressManager import org.jetbrains.plugins.github.api.GithubApiRequestExecutor class LogDataProvider( - progressManager: ProgressManager, requestExecutor: GithubApiRequestExecutor, job: Job ) : DataProvider( - progressManager, requestExecutor, - GithubApi.getJobLog(job), + GithubApi.getLogForSingleJob(job), null ) \ No newline at end of file diff --git a/src/main/kotlin/com/dsoftware/ghmanager/data/providers/SingleRunDataLoader.kt b/src/main/kotlin/com/dsoftware/ghmanager/data/providers/SingleRunDataLoader.kt deleted file mode 100644 index 6fb2ffd5..00000000 --- a/src/main/kotlin/com/dsoftware/ghmanager/data/providers/SingleRunDataLoader.kt +++ /dev/null @@ -1,60 +0,0 @@ -package com.dsoftware.ghmanager.data.providers - -import com.dsoftware.ghmanager.api.model.Job -import com.dsoftware.ghmanager.api.model.WorkflowRun -import com.google.common.cache.CacheBuilder -import com.intellij.openapi.Disposable -import com.intellij.openapi.progress.ProgressManager -import com.intellij.util.EventDispatcher -import com.intellij.util.concurrency.annotations.RequiresEdt -import org.jetbrains.plugins.github.api.GithubApiRequest -import org.jetbrains.plugins.github.api.GithubApiRequestExecutor -import java.util.EventListener - -class SingleRunDataLoader(private val requestExecutor: GithubApiRequestExecutor) : Disposable { - private val progressManager = ProgressManager.getInstance() - private val invalidationEventDispatcher = EventDispatcher.create(DataInvalidatedListener::class.java) - - private val cache = CacheBuilder.newBuilder() - .removalListener> {} - .maximumSize(200) - .build>() - - fun getJobLogDataProvider(job: Job): LogDataProvider { - return cache.get("${job.url}/logs") { - LogDataProvider(progressManager, requestExecutor, job) - } as LogDataProvider - } - - fun getJobsDataProvider(workflowRun: WorkflowRun): WorkflowRunJobsDataProvider { - return cache.get(workflowRun.jobsUrl) { - WorkflowRunJobsDataProvider(progressManager, requestExecutor, workflowRun.jobsUrl) - } as WorkflowRunJobsDataProvider - } - - fun createDataProvider(request: GithubApiRequest): DataProvider { - return DataProvider(progressManager, requestExecutor, request, null) - } - - @RequiresEdt - fun invalidateAllData() { - cache.invalidateAll() - invalidationEventDispatcher.multicaster.dataLoadersInvalidated() - } - - fun addInvalidationListener(disposable: Disposable, listener: () -> Unit) = - invalidationEventDispatcher.addListener(object : DataInvalidatedListener { - override fun dataLoadersInvalidated() { - listener() - } - }, disposable) - - override fun dispose() { - invalidationEventDispatcher.listeners.clear() - invalidateAllData() - } - - private interface DataInvalidatedListener : EventListener { - fun dataLoadersInvalidated() - } -} \ No newline at end of file