Fork me on GitHub
#conjure
<
2020-04-06
>
dave10:04:38

I think even if you're starting your REPL on a specific (not random) port, it's useful to write a port file because it means you don't have to coordinate so that Conjure uses that same port. You can configure Conjure to read the port file, and then you can decide to change the port you're using on a whim without needing to reconfigure Conjure

borkdude11:04:44

@pez had some opinions on bb writing an .nrepl-port file. I first implemented it, but then he said something about it which made me remove it. I can't recall the exact discussion. Maybe I should just add it again then?

sogaiu11:04:35

if you use multiple tools, i think it's better that they use separate mechanisms.

borkdude11:04:43

so writing an .nrepl-port is option one and seems to be what a lot of tooling is already doing. maybe it makes sense to choose that one then?

borkdude11:04:07

since there is no clear winner and not a lot of people have responded to that issue, nothing happened

sogaiu11:04:18

if you only use one tool per project, one file is ok.

sogaiu11:04:32

i happen to use multiple tools on one project directory simultaneously on occasion.

sogaiu11:04:40

for that it is not a good fit.

sogaiu11:04:46

may be i'm in a tiny minority.

pez11:04:42

I belong to that tiny minority as well.

sogaiu11:04:52

shadow-cljs makes its own directory

sogaiu11:04:03

so not everyone does the .nrepl-port in the root directory thing

pez11:04:25

shadow creates both files, I think ¯\(ツ)

sogaiu11:04:36

but in the .shadow-cljs directory

sogaiu11:04:40

not in the project root

pez11:04:30

As I recalled it, it creates an .nrepl-port in the root and some other file in .shadow-cljs/

thheller11:04:40

shadow-cljs creates .shadow-cljs/nrepl.port. .nrepl-port only when configured to do so.

sogaiu11:04:40

i may be wrong about the root

pez11:04:55

Ah, when configured. Thanks!

thheller11:04:14

precisely to avoid conflicting with lein

sogaiu11:04:27

ah and in shadow-cljs the name of the file is nrepl.port in the .shadow-cljs dir -- sorry i had that wrong

borkdude11:04:01

if you guys can fight it out and give a summary in issue 157 of babashka, I'd be happy to implement that 🙂

sogaiu11:04:42

it seems clear to me that shadow-cljs has opted for only one instance of shadow-cljs per project. that sounds right, correct?

thheller11:04:56

yes. makes no sense to have multiple.

sogaiu11:04:14

err, may be for shadow-cljs that is so, but not necessarily for clojure projects

sogaiu11:04:24

i run multiple instances off of a single project

thheller11:04:33

yes, only speaking about shadow-cljs

sogaiu11:04:20

if pretty much all other folks use the same model of one program instance at a time per project, it seems like shadow-cljs' approach of a .<name-of-tool> directory and state files within makes sense

sogaiu11:04:36

the thing that doesn't make sense for me is dumping dot files in the project root that multiple tools read/write willy nilly

pez11:04:24

For Calva it would work well if I could tell babashka the name of the portfile.

Olical12:04:36

Propel, has this. It defaults to .prepl-port but can be turned off or renamed.

pez12:04:21

Yeah, it's a sensible thing to do. 😃

sogaiu11:04:00

would calva be starting babashka?

pez12:04:16

That was my use case. I think it would be a very nice way to make people aware of babashka as a thing.

sogaiu12:04:38

you can start babashka telling it a port number -- no file necessary iiuc

sogaiu12:04:09

--socket-repl       Start socket REPL. Specify port (e.g. 1666) or host and port separated by colon (e.g. 127.0.0.1:1666).
  --nrepl-server      Start nREPL server. Specify port (e.g. 1667) or host and port separated by colon (e.g. 127.0.0.1:1667).

pez12:04:24

Yes, that's how I start it manually.

sogaiu12:04:46

i don't understand why a file is necessary -- would you mind elaborating on that?

pez12:04:32

Sure. Calva has a file watcher that it uses to know when jack-in can continue.

sogaiu12:04:52

ah, so it's a coordinating timing issue then?

pez12:04:12

Yeah. I guess it can be put like that. Calva first starts the server, waits for the file, reads the content, then connects to that port.

sogaiu12:04:39

so the existence of the file acts as a signal that the receiving side is ready -- this is how shadow-cljs behaves iirc

pez12:04:05

Yes, it can take quite a while for some projects to start.

pez12:04:40

It is a stupid limitation in Calva that I should try to fix. But VS Code makes it a bit hard.

borkdude12:04:50

you can find a random port like this:

$ bb -e '(import .ServerSocket) (with-open [sock (ServerSocket. 0)] (.getLocalPort sock))'
51611
and you can wait for a port like this:
$ bb -e '(wait/wait-for-port "localhost" 51611)
I think those ingredients are sufficient to get by without writing a file

borkdude12:04:00

if you do need a file, you can write it after the waiting for the port is finished, in the same script

pez12:04:25

Yeah. For now I let the user start and connect manually. That works too.

borkdude12:04:53

I think that's the most flexible thing to do, especially when you also need a classpath

sogaiu12:04:18

we've hijacked #conjure -- oops 🙂

borkdude12:04:51

I think it's on topic since this discussion started with Olical asking for the .nrepl-port 😉

Olical12:04:30

Yeah, I'm fine with this, it's really interesting and ties into UX concerns.

Olical12:04:42

I tend to lean towards "start your repl yourself and write a portfile for automatic connection". Jack in would require some retry until it's there logic I guess.

Olical12:04:06

But if you start it yourself specifying a port in the editor is fine too. Like with a prompt.

sogaiu12:04:15

i was thinking today to put something together to launch my project and editor from the same script 🙂

pez12:04:20

In this case jack-in would mainly serve as an ad for babashka.

sogaiu12:04:26

then they can both be passed necessary info

pez12:04:31

(the Calva case)

borkdude12:04:54

fwiw I don't ever use jack-in. I want to be able to kill my REPL just in case my editor freezes

borkdude12:04:01

the jack-in ad feature for babashka can be entirely implemented using this I think: https://clojurians.slack.com/archives/CK143P6D7/p1586174810213100 without any changes

sogaiu12:04:05

i confess i don't quite understand how that would be done

sogaiu12:04:19

i understand the bit about finding an available port

sogaiu12:04:15

iiuc, pez wants to use the file-watcher capability because it's already tested. to implement another method (instructing babashka to start on a certain port and then wait) isn't clearly a win within the confines of vscode iiuc.

sogaiu12:04:33

or may be i don't understand?

borkdude12:04:17

something like:

(import .ServerSocket)
(require '[babashka.wait :as wait] '[clojure.java.shell :refer [sh]])
(let [nrepl-port (with-open [sock (ServerSocket. 0)] (.getLocalPort sock))
      fut (future (sh "bb" "--nrepl-server" (str nrepl-port)))]
  (wait/wait-for-port "localhost" nrepl-port)
  (println "Aaaaand it's ready!")
  (spit ".nrepl-port" nrepl-port)
  @fut)

borkdude12:04:30

or any variation of this, maybe VSCode would spawn a subprocess etc.

borkdude12:04:17

VSCode can kick off this script from the editor. And then watch the .nrepl-port file.

pez12:04:15

I'll do it something like that. No worries. Still think it makes sense to have a bb option for creating this file, as well as for using a random port, but it is cool that bb itself can be used to get around the lack. 😃

borkdude12:04:27

Even better:

(import [ ServerSocket]
        [java.lang ProcessBuilder$Redirect])

(require '[babashka.wait :as wait])

(let [nrepl-port (with-open [sock (ServerSocket. 0)] (.getLocalPort sock))
      pb (doto (ProcessBuilder. ["bb" "--nrepl-server" (str nrepl-port)])
           (.redirectOutput ProcessBuilder$Redirect/INHERIT))
      proc (.start pb)]
  (wait/wait-for-port "localhost" nrepl-port)
  (spit ".nrepl-port" nrepl-port)
  (.waitFor proc))

borkdude12:04:02

You can even make that script interactive:

(import [ ServerSocket]
        [java.lang ProcessBuilder$Redirect])

(require '[babashka.wait :as wait])

(let [nrepl-port (with-open [sock (ServerSocket. 0)] (.getLocalPort sock))
      pb (doto (ProcessBuilder. ["bb" "--nrepl-server" (str nrepl-port)])
           (.redirectOutput ProcessBuilder$Redirect/INHERIT))
      proc (.start pb)]
  (wait/wait-for-port "localhost" nrepl-port)
  (spit ".nrepl-port" nrepl-port)
  (println "Press enter to kill the nREPL server.")
  (read-line)
  (.destroy proc))

borkdude12:04:16

So by writing something to stdin of that process, it will kill the nREPL server

pez12:04:38

Is there a JVM version of bb packaged?

borkdude12:04:00

@pez There is an uberjar available in the releases

pez12:04:22

Cool! Awesome even.

borkdude12:04:19

ok, back to #babashka for bb related talk I guess 🙂