Skip to content

Commit 38fcbe3

Browse files
authored
Fix ApplicationThreadPoolScope without disposable (#2731)
1 parent 9ac694d commit 38fcbe3

File tree

54 files changed

+222
-217
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

54 files changed

+222
-217
lines changed

jetbrains-core/resources/META-INF/plugin.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ with what features/services are supported.
126126
</extensionPoints>
127127

128128
<extensions defaultExtensionNs="com.intellij">
129+
<projectService serviceImplementation="software.aws.toolkits.jetbrains.core.ProjectLevelCoroutineScopeTracker"/>
129130
<!-- Credential Management -->
130131
<applicationService serviceInterface="software.aws.toolkits.jetbrains.core.RemoteResourceResolverProvider"
131132
serviceImplementation="software.aws.toolkits.jetbrains.core.DefaultRemoteResourceResolverProvider"/>

jetbrains-core/src/software/aws/toolkits/jetbrains/core/AwsResourceCache.kt

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import com.intellij.openapi.components.service
1010
import com.intellij.openapi.project.Project
1111
import com.intellij.util.Alarm
1212
import com.intellij.util.AlarmFactory
13-
import kotlinx.coroutines.CoroutineScope
1413
import kotlinx.coroutines.Deferred
1514
import kotlinx.coroutines.async
1615
import kotlinx.coroutines.coroutineScope
@@ -265,8 +264,8 @@ class DefaultAwsResourceCache(
265264
private val clock: Clock,
266265
private val maximumCacheEntries: Int,
267266
private val maintenanceInterval: Duration
268-
) : AwsResourceCache, Disposable, ToolkitCredentialsChangeListener, CoroutineScope by ApplicationThreadPoolScope("DefaultAwsResourceCache") {
269-
267+
) : AwsResourceCache, Disposable, ToolkitCredentialsChangeListener {
268+
private val coroutineScope = ApplicationThreadPoolScope("DefaultAwsResourceCache", this)
270269
@Suppress("unused")
271270
constructor() : this(Clock.systemDefaultZone(), MAXIMUM_CACHE_ENTRIES, DEFAULT_MAINTENANCE_INTERVAL)
272271

@@ -299,7 +298,7 @@ class DefaultAwsResourceCache(
299298
fetchIfNeeded(context, currentValue)
300299
} as Entry<T>
301300

302-
launch {
301+
coroutineScope.launch {
303302
try {
304303
context.future.complete(result.value.await())
305304
} catch (e: Throwable) {
@@ -370,7 +369,7 @@ class DefaultAwsResourceCache(
370369
}
371370

372371
override fun dispose() {
373-
launch { clear() }
372+
coroutineScope.launch { clear() }
374373
}
375374

376375
override fun providerRemoved(identifier: CredentialIdentifier) = clearByCredential(identifier.id)
@@ -396,7 +395,7 @@ class DefaultAwsResourceCache(
396395
}
397396

398397
private fun <T> fetch(context: Context<T>): Entry<T> {
399-
val value = async {
398+
val value = coroutineScope.async {
400399
context.resource.fetch(context.region, context.credentials)
401400
}
402401

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package software.aws.toolkits.jetbrains.core
5+
6+
import com.intellij.openapi.Disposable
7+
import com.intellij.openapi.components.ServiceManager
8+
import com.intellij.openapi.project.Project
9+
import com.intellij.util.containers.ContainerUtil
10+
import software.aws.toolkits.jetbrains.utils.ApplicationThreadPoolScope
11+
12+
class ProjectLevelCoroutineScopeTracker(
13+
@Suppress("unused")
14+
private val project: Project
15+
) : Disposable {
16+
private val scopes: MutableMap<String, ApplicationThreadPoolScope> = ContainerUtil.createConcurrentWeakValueMap()
17+
fun applicationThreadPoolScope(coroutineName: String): ApplicationThreadPoolScope =
18+
scopes.computeIfAbsent(coroutineName) { ApplicationThreadPoolScope(coroutineName, this) }
19+
20+
override fun dispose() { }
21+
22+
companion object {
23+
fun getInstance(project: Project) = ServiceManager.getService(project, ProjectLevelCoroutineScopeTracker::class.java)
24+
}
25+
}
26+
27+
fun Project.applicationThreadPoolScope(coroutineName: String) = ProjectLevelCoroutineScopeTracker.getInstance(this).applicationThreadPoolScope(coroutineName)
28+
29+
@Suppress("unused") // T receiver needed to infer type
30+
inline fun <reified T : Any> T.applicationThreadPoolScope(project: Project) = project.applicationThreadPoolScope(T::class.java.name)

jetbrains-core/src/software/aws/toolkits/jetbrains/core/credentials/RefreshConnectionAction.kt

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,14 @@ import com.intellij.icons.AllIcons
77
import com.intellij.openapi.actionSystem.AnAction
88
import com.intellij.openapi.actionSystem.AnActionEvent
99
import com.intellij.openapi.project.DumbAware
10-
import kotlinx.coroutines.CoroutineScope
1110
import kotlinx.coroutines.launch
1211
import software.aws.toolkits.jetbrains.core.AwsResourceCache
13-
import software.aws.toolkits.jetbrains.utils.ApplicationThreadPoolScope
12+
import software.aws.toolkits.jetbrains.core.applicationThreadPoolScope
1413
import software.aws.toolkits.resources.message
1514
import software.aws.toolkits.telemetry.AwsTelemetry
1615

1716
class RefreshConnectionAction(text: String = message("settings.refresh.description")) :
1817
AnAction(text, null, AllIcons.Actions.Refresh),
19-
CoroutineScope by ApplicationThreadPoolScope("RefreshConnectionAction"),
2018
DumbAware {
2119
override fun update(e: AnActionEvent) {
2220
val project = e.project ?: return
@@ -28,7 +26,8 @@ class RefreshConnectionAction(text: String = message("settings.refresh.descripti
2826

2927
override fun actionPerformed(e: AnActionEvent) {
3028
val project = e.project ?: return
31-
launch { AwsResourceCache.getInstance().clear() }
29+
val scope = project.applicationThreadPoolScope("RefreshConnectionAction")
30+
scope.launch { AwsResourceCache.getInstance().clear() }
3231
AwsConnectionManager.getInstance(project).refreshConnectionState()
3332
AwsTelemetry.refreshExplorer(project)
3433
}

jetbrains-core/src/software/aws/toolkits/jetbrains/core/docker/ToolkitDockerAdapter.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ abstract class AbstractToolkitDockerAdapter(protected val project: Project, prot
5252
abstract fun buildLocalImage(dockerfile: File): String?
5353

5454
open suspend fun hackyBuildDockerfileWithUi(project: Project, pushRequest: DockerfileEcrPushRequest): String? {
55-
val (runConfiguration, remoteRepo, remoteTag) = pushRequest
55+
val (runConfiguration, _, _) = pushRequest
5656
// use connection specified in run configuration
5757
val server = RemoteServersManager.getInstance().findByName(runConfiguration.serverName, runConfiguration.serverType)
5858
val (serverConnection, dockerRuntime) = EcrUtils.getDockerServerRuntimeInstance(server)

jetbrains-core/src/software/aws/toolkits/jetbrains/services/apprunner/actions/PauseServiceAction.kt

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,21 +10,20 @@ import com.intellij.openapi.ui.DialogWrapper
1010
import com.intellij.openapi.ui.Messages
1111
import com.intellij.ui.components.JBLabel
1212
import com.intellij.ui.layout.panel
13-
import kotlinx.coroutines.CoroutineScope
1413
import kotlinx.coroutines.launch
1514
import software.amazon.awssdk.services.apprunner.AppRunnerClient
1615
import software.amazon.awssdk.services.apprunner.model.AppRunnerException
1716
import software.amazon.awssdk.services.apprunner.model.ServiceStatus
1817
import software.amazon.awssdk.services.apprunner.model.ServiceSummary
1918
import software.aws.toolkits.core.utils.error
2019
import software.aws.toolkits.core.utils.getLogger
20+
import software.aws.toolkits.jetbrains.core.applicationThreadPoolScope
2121
import software.aws.toolkits.jetbrains.core.awsClient
2222
import software.aws.toolkits.jetbrains.core.explorer.actions.SingleResourceNodeAction
2323
import software.aws.toolkits.jetbrains.core.explorer.refreshAwsTree
2424
import software.aws.toolkits.jetbrains.core.help.HelpIds
2525
import software.aws.toolkits.jetbrains.services.apprunner.AppRunnerServiceNode
2626
import software.aws.toolkits.jetbrains.services.apprunner.resources.AppRunnerResources
27-
import software.aws.toolkits.jetbrains.utils.ApplicationThreadPoolScope
2827
import software.aws.toolkits.jetbrains.utils.notifyError
2928
import software.aws.toolkits.jetbrains.utils.notifyInfo
3029
import software.aws.toolkits.resources.message
@@ -34,8 +33,7 @@ import javax.swing.JComponent
3433

3534
class PauseServiceAction :
3635
SingleResourceNodeAction<AppRunnerServiceNode>(message("apprunner.action.pause")),
37-
DumbAware,
38-
CoroutineScope by ApplicationThreadPoolScope("PauseServiceAction") {
36+
DumbAware {
3937
override fun update(selected: AppRunnerServiceNode, e: AnActionEvent) {
4038
e.presentation.isVisible = selected.service.status() == ServiceStatus.RUNNING
4139
}
@@ -60,7 +58,8 @@ class PauseServiceAction :
6058
}
6159
}
6260
if (dialog.showAndGet()) {
63-
launch {
61+
val scope = applicationThreadPoolScope(selected.nodeProject)
62+
scope.launch {
6463
performPause(selected.nodeProject, selected.nodeProject.awsClient(), selected.service)
6564
}
6665
} else {

jetbrains-core/src/software/aws/toolkits/jetbrains/services/apprunner/actions/ResumeServiceAction.kt

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,21 +10,20 @@ import com.intellij.openapi.ui.DialogWrapper
1010
import com.intellij.openapi.ui.Messages
1111
import com.intellij.ui.components.JBLabel
1212
import com.intellij.ui.layout.panel
13-
import kotlinx.coroutines.CoroutineScope
1413
import kotlinx.coroutines.launch
1514
import software.amazon.awssdk.services.apprunner.AppRunnerClient
1615
import software.amazon.awssdk.services.apprunner.model.AppRunnerException
1716
import software.amazon.awssdk.services.apprunner.model.ServiceStatus
1817
import software.amazon.awssdk.services.apprunner.model.ServiceSummary
1918
import software.aws.toolkits.core.utils.error
2019
import software.aws.toolkits.core.utils.getLogger
20+
import software.aws.toolkits.jetbrains.core.applicationThreadPoolScope
2121
import software.aws.toolkits.jetbrains.core.awsClient
2222
import software.aws.toolkits.jetbrains.core.explorer.actions.SingleResourceNodeAction
2323
import software.aws.toolkits.jetbrains.core.explorer.refreshAwsTree
2424
import software.aws.toolkits.jetbrains.core.help.HelpIds
2525
import software.aws.toolkits.jetbrains.services.apprunner.AppRunnerServiceNode
2626
import software.aws.toolkits.jetbrains.services.apprunner.resources.AppRunnerResources
27-
import software.aws.toolkits.jetbrains.utils.ApplicationThreadPoolScope
2827
import software.aws.toolkits.jetbrains.utils.notifyError
2928
import software.aws.toolkits.jetbrains.utils.notifyInfo
3029
import software.aws.toolkits.resources.message
@@ -34,8 +33,7 @@ import javax.swing.JComponent
3433

3534
class ResumeServiceAction :
3635
SingleResourceNodeAction<AppRunnerServiceNode>(message("apprunner.action.resume")),
37-
DumbAware,
38-
CoroutineScope by ApplicationThreadPoolScope("ResumeServiceAction") {
36+
DumbAware {
3937
override fun update(selected: AppRunnerServiceNode, e: AnActionEvent) {
4038
e.presentation.isVisible = selected.service.status() == ServiceStatus.PAUSED
4139
}
@@ -61,7 +59,8 @@ class ResumeServiceAction :
6159
}
6260

6361
if (dialog.showAndGet()) {
64-
launch {
62+
val scope = applicationThreadPoolScope(selected.nodeProject)
63+
scope.launch {
6564
performResume(selected.nodeProject, selected.nodeProject.awsClient(), selected.service)
6665
}
6766
} else {

jetbrains-core/src/software/aws/toolkits/jetbrains/services/apprunner/actions/ViewLogsAction.kt

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,25 +6,24 @@ package software.aws.toolkits.jetbrains.services.apprunner.actions
66
import com.intellij.openapi.actionSystem.AnActionEvent
77
import com.intellij.openapi.project.DumbAware
88
import icons.AwsIcons
9-
import kotlinx.coroutines.CoroutineScope
109
import kotlinx.coroutines.launch
1110
import software.amazon.awssdk.services.cloudwatchlogs.CloudWatchLogsClient
11+
import software.aws.toolkits.jetbrains.core.applicationThreadPoolScope
1212
import software.aws.toolkits.jetbrains.core.awsClient
1313
import software.aws.toolkits.jetbrains.core.explorer.actions.SingleResourceNodeAction
1414
import software.aws.toolkits.jetbrains.services.apprunner.AppRunnerServiceNode
1515
import software.aws.toolkits.jetbrains.services.cloudwatch.logs.CloudWatchLogWindow
1616
import software.aws.toolkits.jetbrains.services.cloudwatch.logs.checkIfLogGroupExists
17-
import software.aws.toolkits.jetbrains.utils.ApplicationThreadPoolScope
1817
import software.aws.toolkits.jetbrains.utils.notifyError
1918
import software.aws.toolkits.resources.message
2019
import software.aws.toolkits.telemetry.ApprunnerTelemetry
2120

2221
class ViewSystemLogsAction :
2322
SingleResourceNodeAction<AppRunnerServiceNode>(message("apprunner.view_service_log_streams"), null, AwsIcons.Resources.CloudWatch.LOGS),
24-
CoroutineScope by ApplicationThreadPoolScope("AppRunnerViewServiceLogStreamsAction"),
2523
DumbAware {
2624
override fun actionPerformed(selected: AppRunnerServiceNode, e: AnActionEvent) {
27-
launch {
25+
val scope = applicationThreadPoolScope(selected.nodeProject)
26+
scope.launch {
2827
try {
2928
viewLogGroup(selected, "service")
3029
} finally {
@@ -36,10 +35,10 @@ class ViewSystemLogsAction :
3635

3736
class ViewApplicationLogsAction :
3837
SingleResourceNodeAction<AppRunnerServiceNode>(message("apprunner.view_application_log_streams"), null, AwsIcons.Resources.CloudWatch.LOGS),
39-
CoroutineScope by ApplicationThreadPoolScope("AppRunnerViewApplicationLogStreamsAction"),
4038
DumbAware {
4139
override fun actionPerformed(selected: AppRunnerServiceNode, e: AnActionEvent) {
42-
launch {
40+
val scope = applicationThreadPoolScope(selected.nodeProject)
41+
scope.launch {
4342
try {
4443
viewLogGroup(selected, "application")
4544
} finally {

jetbrains-core/src/software/aws/toolkits/jetbrains/services/apprunner/ui/CreationDialog.kt

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ package software.aws.toolkits.jetbrains.services.apprunner.ui
66
import com.intellij.openapi.application.ModalityState
77
import com.intellij.openapi.project.Project
88
import com.intellij.openapi.ui.DialogWrapper
9-
import kotlinx.coroutines.CoroutineScope
109
import kotlinx.coroutines.launch
1110
import kotlinx.coroutines.withContext
1211
import software.amazon.awssdk.services.apprunner.AppRunnerClient
@@ -17,10 +16,10 @@ import software.amazon.awssdk.services.apprunner.model.ImageRepositoryType
1716
import software.amazon.awssdk.services.apprunner.model.SourceCodeVersionType
1817
import software.aws.toolkits.core.utils.error
1918
import software.aws.toolkits.core.utils.getLogger
19+
import software.aws.toolkits.jetbrains.core.applicationThreadPoolScope
2020
import software.aws.toolkits.jetbrains.core.awsClient
2121
import software.aws.toolkits.jetbrains.core.explorer.refreshAwsTree
2222
import software.aws.toolkits.jetbrains.services.apprunner.resources.AppRunnerResources
23-
import software.aws.toolkits.jetbrains.utils.ApplicationThreadPoolScope
2423
import software.aws.toolkits.jetbrains.utils.getCoroutineUiContext
2524
import software.aws.toolkits.jetbrains.utils.notifyInfo
2625
import software.aws.toolkits.resources.message
@@ -30,8 +29,8 @@ import software.aws.toolkits.telemetry.Result
3029
import javax.swing.JComponent
3130

3231
class CreationDialog(private val project: Project, ecrUri: String? = null) :
33-
DialogWrapper(project),
34-
CoroutineScope by ApplicationThreadPoolScope("ApprunnerCreationPanel") {
32+
DialogWrapper(project) {
33+
private val coroutineScope = applicationThreadPoolScope(project)
3534
val panel = CreationPanel(project, ecrUri)
3635

3736
init {
@@ -54,7 +53,7 @@ class CreationDialog(private val project: Project, ecrUri: String? = null) :
5453
isOKActionEnabled = false
5554
setOKButtonText(message("general.create_in_progress"))
5655
panel.component.apply()
57-
launch {
56+
coroutineScope.launch {
5857
try {
5958
val client = project.awsClient<AppRunnerClient>()
6059
val request = buildRequest(panel)

jetbrains-core/src/software/aws/toolkits/jetbrains/services/cloudwatch/logs/CloudWatchLogWindow.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,26 +7,26 @@ import com.intellij.openapi.components.ServiceManager
77
import com.intellij.openapi.project.Project
88
import com.intellij.util.text.DateFormatUtil
99
import icons.AwsIcons
10-
import kotlinx.coroutines.CoroutineScope
1110
import kotlinx.coroutines.withContext
1211
import software.amazon.awssdk.services.cloudwatchlogs.CloudWatchLogsClient
1312
import software.aws.toolkits.core.utils.error
1413
import software.aws.toolkits.core.utils.getLogger
14+
import software.aws.toolkits.jetbrains.core.applicationThreadPoolScope
1515
import software.aws.toolkits.jetbrains.core.toolwindow.ToolkitToolWindowManager
1616
import software.aws.toolkits.jetbrains.core.toolwindow.ToolkitToolWindowType
1717
import software.aws.toolkits.jetbrains.services.cloudwatch.logs.editor.CloudWatchLogGroup
1818
import software.aws.toolkits.jetbrains.services.cloudwatch.logs.editor.CloudWatchLogStream
1919
import software.aws.toolkits.jetbrains.services.cloudwatch.logs.insights.DetailedLogRecord
2020
import software.aws.toolkits.jetbrains.services.cloudwatch.logs.insights.QueryDetails
2121
import software.aws.toolkits.jetbrains.services.cloudwatch.logs.insights.QueryResultList
22-
import software.aws.toolkits.jetbrains.utils.ApplicationThreadPoolScope
2322
import software.aws.toolkits.jetbrains.utils.getCoroutineUiContext
2423
import software.aws.toolkits.resources.message
2524
import software.aws.toolkits.telemetry.CloudwatchlogsTelemetry
2625
import software.aws.toolkits.telemetry.Result
2726
import java.time.Duration
2827

29-
class CloudWatchLogWindow(private val project: Project) : CoroutineScope by ApplicationThreadPoolScope("openLogGroup") {
28+
class CloudWatchLogWindow(private val project: Project) {
29+
private val coroutineScope = applicationThreadPoolScope(project)
3030
private val toolWindow = ToolkitToolWindowManager.getInstance(project, CW_LOGS_TOOL_WINDOW)
3131
private val edtContext = getCoroutineUiContext()
3232

0 commit comments

Comments
 (0)