Skip to content

Commit 0949310

Browse files
author
Andrea Falzetti
committed
feat(jb): observe ports status and send notification
1 parent e148325 commit 0949310

File tree

1 file changed

+101
-0
lines changed
  • components/ide/jetbrains/backend-plugin/src/main/kotlin/io/gitpod/jetbrains/remote

1 file changed

+101
-0
lines changed

components/ide/jetbrains/backend-plugin/src/main/kotlin/io/gitpod/jetbrains/remote/GitpodManager.kt

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
package io.gitpod.jetbrains.remote
66

7+
import com.intellij.ide.BrowserUtil
78
import com.intellij.ide.plugins.PluginManagerCore
89
import com.intellij.notification.NotificationAction
910
import com.intellij.notification.NotificationGroupManager
@@ -23,6 +24,10 @@ import io.gitpod.jetbrains.remote.utils.Retrier.retry
2324
import io.gitpod.supervisor.api.*
2425
import io.gitpod.supervisor.api.Info.WorkspaceInfoResponse
2526
import io.gitpod.supervisor.api.Notification.*
27+
import io.gitpod.supervisor.api.Status.OnPortExposedAction
28+
import io.gitpod.supervisor.api.Status.PortsStatus
29+
import io.gitpod.supervisor.api.Status.PortsStatusRequest
30+
import io.gitpod.supervisor.api.Status.PortsStatusResponse
2631
import io.grpc.ManagedChannel
2732
import io.grpc.ManagedChannelBuilder
2833
import io.grpc.stub.ClientCallStreamObserver
@@ -46,6 +51,7 @@ import java.util.concurrent.CancellationException
4651
import java.util.concurrent.CompletableFuture
4752
import javax.websocket.DeploymentException
4853

54+
4955
@Service
5056
class GitpodManager : Disposable {
5157

@@ -199,6 +205,101 @@ class GitpodManager : Disposable {
199205
}
200206
}
201207

208+
private val portsObserveJob = GlobalScope.launch {
209+
if (application.isHeadlessEnvironment) {
210+
return@launch
211+
}
212+
213+
val portsStatus = hashMapOf<Int, PortsStatus>()
214+
215+
val status = StatusServiceGrpc.newStub(supervisorChannel)
216+
//while (isActive) {
217+
try {
218+
val f = CompletableFuture<Void>()
219+
status.portsStatus(
220+
PortsStatusRequest.newBuilder().setObserve(true).build(),
221+
object : ClientResponseObserver<PortsStatusRequest, PortsStatusResponse> {
222+
override fun beforeStart(requestStream: ClientCallStreamObserver<PortsStatusRequest>) {
223+
println("[Andrea]: beforeStart")
224+
// TODO(ak): actually should be bound to cancellation of notifications job
225+
lifetime.onTerminationOrNow {
226+
requestStream.cancel(null, null)
227+
}
228+
}
229+
230+
override fun onNext(ps: PortsStatusResponse) {
231+
for (port in ps.portsList) {
232+
if (!portsStatus.containsKey(port.localPort)) {
233+
portsStatus[port.localPort] = port
234+
continue
235+
}
236+
237+
println("DEBUG[${port.localPort}] -> before hasExposed(${portsStatus[port.localPort]?.hasExposed().toString()}) -> now hasExposed(${port.hasExposed()})")
238+
if (!portsStatus[port.localPort]?.hasExposed()!! && port.hasExposed()) {
239+
if (port.exposed.onExposed.number == OnPortExposedAction.ignore_VALUE) {
240+
continue
241+
}
242+
243+
if (port.exposed.onExposed.number == OnPortExposedAction.open_browser_VALUE) {
244+
BrowserUtil.browse(port.exposed.url)
245+
continue
246+
}
247+
248+
if (port.exposed.onExposed.number == OnPortExposedAction.open_preview_VALUE) {
249+
BrowserUtil.browse(port.exposed.url)
250+
continue
251+
}
252+
253+
if (port.served && !port.exposed.url.isNullOrEmpty()) {
254+
println("Show port notification‼️‼️ ${port.localPort}")
255+
val message =
256+
"Your application running on port " + port.localPort + " is available."
257+
println(message)
258+
val notification =
259+
notificationGroup.createNotification(message, NotificationType.INFORMATION)
260+
// TODO(andreafalzetti): add analytics event
261+
val lambda = { BrowserUtil.browse(port.exposed.url) }
262+
val action = NotificationAction.createSimpleExpiring("Open in browser", lambda)
263+
notification.addAction(action)
264+
notification.notify(null)
265+
}
266+
//
267+
}
268+
269+
}
270+
271+
}
272+
273+
override fun onError(t: Throwable) {
274+
println("[Andrea]: onError")
275+
println(t)
276+
f.completeExceptionally(t)
277+
}
278+
279+
override fun onCompleted() {
280+
f.complete(null)
281+
}
282+
})
283+
} catch (t: Throwable) {
284+
if (t is CancellationException) {
285+
throw t
286+
}
287+
thisLogger().error("gitpod: failed to stream ports status: ", t)
288+
}
289+
//println("**** DEBUG **** ${portsStatus.size}")
290+
//portsStatus.forEach { ps ->
291+
// println("${ps.key} : ${ps.value.exposed.url}")
292+
//}
293+
// println("***************")
294+
// delay(1000)
295+
//}
296+
}
297+
init {
298+
lifetime.onTerminationOrNow {
299+
portsObserveJob.cancel()
300+
}
301+
}
302+
202303
val pendingInfo = CompletableFuture<WorkspaceInfoResponse>()
203304
private val infoJob = GlobalScope.launch {
204305
if (application.isHeadlessEnvironment) {

0 commit comments

Comments
 (0)