-
Notifications
You must be signed in to change notification settings - Fork 1.3k
[jb] enable connect button only when JetBrains Client not activated #10177
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
/werft run 👍 started the job as gitpod-build-jb-gw-fork.0 Nice addition! |
It's working great! One thing I've noticed though, is that if we close the Client, it will only change back the button to "Connect" (instead of "Connected") if we click the Refresh button. I think it might be a problem. Ideally, we should also have a listener (or a long-polling) to reset the button when the Thin Client gets closed. |
Hey @felladrin! That's a good catch!!! Thanks for your thorough testing! Previously I thought the JBClient closing event would fire at the Gateway SDK is a black box sadly, I'm quite curious how @akosyakov gets to know the extension points of Gateway & figures out which apis to use :-) If we have more docs about the Gateway SDK, we could avoid lots of unexpected behaviors |
Logging and trying 😆 |
Thanks for fixing it @yaohui-wyh! Maybe we could delay Lines 258 to 260 in 24efeeb
There might be a better solution than using a timer, but I couldn't think on anything else at this moment (intellisense inside |
Hi @felladrin, Thanks again for the thorough testing!
Yeah, I can reproduce it. (And sorry for that) So the previous attempt (add And after digging into the properties of
In short, we should rely on |
The exact fix is only @@ -256,13 +259,19 @@ class GitpodConnectionProvider : GatewayConnectionProvider {
)
val client = connector.connect()
client.clientClosed.advise(connectionLifetime) {
application.invokeLater {
- dispatcher.multicaster.didChange()
+ connectionLifetime.onTermination {
+ dispatcher.multicaster.didChange()
+ }
connectionLifetime.terminate()
}
}
@@ -295,7 +301,7 @@ class GitpodWorkspacesView(
}
label(getRelativeTimeSpan(info.latestInstance.creationTime))
val jbClientConnected = GitpodConnectionProvider.jetbrainsClientMap[info.workspace.id]
- ?.clientPresent ?: false
+ ?.lifetime?.isAlive ?: false
val btnText = if (jbClientConnected) "Connected" else "Connect"
button(btnText) {
if (!canConnect) {
However I think it would be better to keep the logging statements & extension functions, since they are not on the critical path and wouldn't jam the log. |
...rains/gateway-plugin/src/main/kotlin/io/gitpod/jetbrains/gateway/GitpodConnectionProvider.kt
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's working great now! Thanks for this PR @yaohui-wyh!
client.clientClosed.advise(connectionLifetime) { | ||
thisLogger().d("clientClosed, ${client.prettyPrint()}") | ||
application.invokeLater { | ||
connectionLifetime.onTermination { | ||
thisLogger().d("clientTermination, clientClosed didChange fired, ${client.prettyPrint()}") | ||
dispatcher.multicaster.didChange() | ||
} | ||
connectionLifetime.terminate() | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One thing I've noticed, is that we could benefit from letting the connectionLifetime.onTermination
set even before the client gets closed. Because there is another place where we call connectionLifetime.terminate()
, and in the future we can have even more cases.
Something like the following, which can be done in a follow-up PR if needed:
client.clientClosed.advise(connectionLifetime) { | |
thisLogger().d("clientClosed, ${client.prettyPrint()}") | |
application.invokeLater { | |
connectionLifetime.onTermination { | |
thisLogger().d("clientTermination, clientClosed didChange fired, ${client.prettyPrint()}") | |
dispatcher.multicaster.didChange() | |
} | |
connectionLifetime.terminate() | |
} | |
} | |
connectionLifetime.onTermination { | |
thisLogger().d("clientLifetimeTermination, didChange fired, ${client.prettyPrint()}") | |
dispatcher.multicaster.didChange() | |
} | |
client.clientClosed.advise(connectionLifetime) { | |
thisLogger().d("clientClosed, ${client.prettyPrint()}") | |
application.invokeLater { | |
connectionLifetime.terminate() | |
} | |
} |
@@ -52,6 +57,26 @@ class GitpodConnectionProvider : GatewayConnectionProvider { | |||
|
|||
private val gitpod = service<GitpodConnectionService>() | |||
|
|||
companion object { | |||
var jetbrainsClientMap: MutableMap<String, ThinClientHandle> = mutableMapOf() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When do we remove a client from this map?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(nit) Should not it also be private and we expose instead getClient
?
This PR is leaking thin clients and does not look very structured :( |
@@ -293,7 +300,10 @@ class GitpodWorkspacesView( | |||
) | |||
} | |||
label(getRelativeTimeSpan(info.latestInstance.creationTime)) | |||
button("Connect") { | |||
val jbClientConnected = GitpodConnectionProvider.jetbrainsClientMap[info.workspace.id] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should not we rather focus existing client instead?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a good idea, however I haven't found a way to requestFocus for the ThinClient yet
if (client.clientPresent) { | ||
statusMessage.text = "" | ||
} | ||
} | ||
} | ||
thinClient = client | ||
jetbrainsClientMap[update.workspaceId] = client |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should not it be like:
jetbrainsClientMap[update.workspaceId] = client
dispatcher.multicaster.didChange()
connectionLifetime.onTermination {
jetbrainsClientMap.remove(update.workspaceId)
dispatcher.multicaster.didChange()
}
We could also create a private function setCleint(id, client | null)
and then do here:
setClient(id, client);
connectionLifetime.onTermination {
setClient(id, null)
}
@yaohui-wyh Will you send a clean up PR? of @felladrin takes care about clean up? |
Sure, I will make a clean up PR. Thanks for the comments:) @akosyakov @felladrin |
Description
Each time user clicked on the "connect" button, previous activated JetBrainsClient is restarted. Since JBClient takes quite a long startup time, disable the connect button to prevent unexpected restart might be reasonable.
This PR syncs the jbclient's state for workspace view: when a JetBrainsClient is launched for a Gitpod workspace (via JetBrains Gateway Plugin), update the "connect" button text as "connected", and disable the connect button until the JetBrainsClient is closed
Related Issue(s)
How to test
Build & Install the plugin following
https://github.com/gitpod-io/gitpod/blob/main/components/ide/jetbrains/gateway-plugin/README.md#L8
Release Notes