From 7a1d0ac40be0c8be050905d10f426dcd8c8cf134 Mon Sep 17 00:00:00 2001 From: Piotr Tomiak Date: Thu, 23 Oct 2025 11:29:10 +0200 Subject: [PATCH] [tasks] IJPL-214046 Use coroutines to save task context asynchronously (cherry picked from commit 29b13650f3bb940bc9b9dddbaf7ef19854cc40e9) IJ-CR-179796 GitOrigin-RevId: eba8aa03d06556711556e06fe3cec0b0a9e7cce8 --- .../resources/messages/TaskBundle.properties | 3 +- .../openapi/vcs/checkin/CheckinHandler.java | 2 ++ .../tasks/impl/TaskCheckinHandlerFactory.kt | 35 ++++++++++++++----- 3 files changed, 30 insertions(+), 10 deletions(-) diff --git a/platform/tasks-platform-impl/resources/messages/TaskBundle.properties b/platform/tasks-platform-impl/resources/messages/TaskBundle.properties index cea3aa603c8e..141cca2a33f4 100644 --- a/platform/tasks-platform-impl/resources/messages/TaskBundle.properties +++ b/platform/tasks-platform-impl/resources/messages/TaskBundle.properties @@ -244,4 +244,5 @@ notification.group.tasks=Task server connection failed notification.group.context.corrupted=Task context data corrupted task.list.url.configuration.parameter.is.mandatory='Task list URL' configuration parameter is mandatory do.not.associate.branch=Do ¬ associate branch -tasks.widget.accessible.name.prefix=Task \ No newline at end of file +tasks.widget.accessible.name.prefix=Task +progress.title.saving.task.context=Saving task context\u2026 \ No newline at end of file diff --git a/platform/vcs-api/src/com/intellij/openapi/vcs/checkin/CheckinHandler.java b/platform/vcs-api/src/com/intellij/openapi/vcs/checkin/CheckinHandler.java index a776b19f221d..2b53c40f75b7 100644 --- a/platform/vcs-api/src/com/intellij/openapi/vcs/checkin/CheckinHandler.java +++ b/platform/vcs-api/src/com/intellij/openapi/vcs/checkin/CheckinHandler.java @@ -11,6 +11,7 @@ import com.intellij.openapi.vcs.changes.CommitExecutor; import com.intellij.openapi.vcs.changes.LocalCommitExecutor; import com.intellij.openapi.vcs.ui.RefreshableOnComponent; import com.intellij.util.PairConsumer; +import com.intellij.util.concurrency.annotations.RequiresEdt; import org.jetbrains.annotations.Nullable; import java.util.List; @@ -96,6 +97,7 @@ public abstract class CheckinHandler { * {@link BaseCheckinHandlerFactory#createHandler(CheckinProjectPanel, CommitContext)} to * get information about the checked in files. */ + @RequiresEdt public void checkinSuccessful() { } diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/TaskCheckinHandlerFactory.kt b/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/TaskCheckinHandlerFactory.kt index 9f8e2ced4c19..98abf6823966 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/TaskCheckinHandlerFactory.kt +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/TaskCheckinHandlerFactory.kt @@ -1,15 +1,23 @@ // Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.intellij.tasks.impl -import com.intellij.openapi.application.ApplicationManager +import com.intellij.openapi.components.Service +import com.intellij.openapi.components.service import com.intellij.openapi.project.DumbAware import com.intellij.openapi.vcs.CheckinProjectPanel import com.intellij.openapi.vcs.changes.CommitContext import com.intellij.openapi.vcs.checkin.CheckinHandler import com.intellij.openapi.vcs.checkin.CheckinHandlerFactory +import com.intellij.platform.ide.progress.withBackgroundProgress import com.intellij.tasks.Task +import com.intellij.tasks.TaskBundle import com.intellij.tasks.TaskManager import com.intellij.tasks.context.WorkingContextManager +import com.intellij.util.concurrency.annotations.RequiresEdt +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext import java.util.* class TaskCheckinHandlerFactory : CheckinHandlerFactory() { @@ -17,22 +25,31 @@ class TaskCheckinHandlerFactory : CheckinHandlerFactory() { TaskCheckinHandler(panel) private class TaskCheckinHandler(val panel: CheckinProjectPanel) : CheckinHandler(), DumbAware { + + @RequiresEdt override fun checkinSuccessful() { val message = panel.getCommitMessage() val project = panel.getProject() val manager = TaskManager.getManager(project) as TaskManagerImpl if (manager.getState().saveContextOnCommit) { - val task = findTaskInRepositories(message, manager) - ?: manager.createLocalTask(message) - .also { (it as LocalTaskImpl).isClosed = true } - val localTask = manager.addTask(task) - localTask.setUpdated(Date()) - - ApplicationManager.getApplication().invokeLater( - { WorkingContextManager.getInstance(project).saveContext(localTask) }, project.getDisposed()) + project.service().launch { + withBackgroundProgress(project, TaskBundle.message("progress.title.saving.task.context"), cancellable = true) { + val task = findTaskInRepositories(message, manager) + ?: manager.createLocalTask(message) + .also { (it as LocalTaskImpl).isClosed = true } + val localTask = manager.addTask(task) + localTask.setUpdated(Date()) + withContext(Dispatchers.Main) { + WorkingContextManager.getInstance(project).saveContext(localTask) + } + } + } } } } + + @Service(Service.Level.PROJECT) + private class CoroutineScopeHolder(private val cs: CoroutineScope) : CoroutineScope by cs } private fun findTaskInRepositories(message: String, manager: TaskManager): Task? {