Hi! First of all, huge shout-out for creating portal, I've been using it for the past few days and I'm loving it. I created this https://github.com/rfhayashi/emacs.d/blob/master/config.org#org-mode--clojure-portal to integrate it with emacs org-mode. Curious to hear if anybody else is doing something like this. One thing that didn't work very well is that when you close the browser window, the underlying process remains alive, would it be possible to kill it?
I was thinking a little more about this, and I guess I implemented this way because it was the easiest thing to do, but instead of creating a new portal each time I eval something, I could have only one portal process and send new evaluations to it via nrepl. Does it make sense?
@djblue I've managed to reuse the same portal process (code is https://github.com/rfhayashi/emacs.d/blob/master/config.org#org-mode--clojure-portal if you're curious), but it would still be useful to know whether the browser window was closed so that I could create a new one in that case. I did some testing and found that httpkit has a function that tells whether the websocket channel is open (http://http-kit.github.io/http-kit/org.httpkit.server.html#var-open.3F). It does return false after I close the browser window. I was thinking of having a function (maybe in portal.api
?) that tells whether a portal instance is open or not. If you agree, I could work on a PR (should I open an issue before?).
@rfhayashi Now that you have experience with both, what do you like more, having multiple portal windows or a single one with values that change over time?
I'm still thinking of maybe having a way to define in the org file to which portal instance an evaluation goes, but answering your question, overall having a single window with values that change over time works well.
Well in that case, I think I would rather have p/open take an existing portal object that will ensure it's open, that way all you do is call open every time before you output a new value
I think maybe all the api methods can optionally take an existing session object to limit the action to that session
When omitted, they continue to operate as a sort of broadcast
Does that make sense?
Also, all of the current sessions are stored in https://github.com/djblue/portal/blob/master/src/portal/runtime/jvm/client.clj#L4. The map is kept in sync with active ws connections. If the session-id isn't in the map, the browser is probably closed
That means that the history would be preserved? (i.e. if I close the browser window and call open on the same session, the window would reopen with the same state as before)
If it's not part of the tap list, the state will not be preserved
But open shouldn't close the session if it's already open
it should be a nop in that case
The session-id is more about routing messages vs state management
what you'd essentially be doing is to create a new session with the previous id (or doing a no-op in case the session is still open), is that right?
Yeah, that way you don't have to ask if it's open. Rather, you just say you still want it to be open, and if that's not true, make it so.
Then it's symmetric with close, which does nothing if it's already closed
got it, I'll work on that, I'll get back to you when I have something (it may take a little because of the holidays), thanks!
No worries, enjoy the holidays!
you too, merry christmas! 🎄
Hi @rfhayashi, thanks for the kind words! Also, that's a really neat way to integrate with portal. So I don't think there is a reliable way for the browser to notify the parent process if you close the window, especially because it looks exactly the same as a browser reload.
It's also a bit at odds with the other style of using portal in a long lived process where you might open/close a few sessions.
I'll see if I can come up with a solution, let me know if you think of any.
I've never played with websockets, don't know if there would be a way the portal process could figure out that the browser is not listening anymore. But I agree this should be an option and not the default behavior.