Skip to content

Instantly share code, notes, and snippets.

@daveyarwood
Last active February 5, 2020 17:22
Show Gist options
  • Save daveyarwood/f890bf1529cb633c04b90ce5d5201d6d to your computer and use it in GitHub Desktop.
Save daveyarwood/f890bf1529cb633c04b90ce5d5201d6d to your computer and use it in GitHub Desktop.
Dave's setup for starting a prepl server in tools.deps projects
;; ~/.config/conjure/conjure.edn
{:conns
;; My `clj -Aprepl-server` alias spits out a `.socket-port` file when it starts
;; a prepl server. This configuration allows Conjure to find the prepl server
;; without needing to specify the port explicitly.
{:cwd {:port #slurp-edn ".socket-port"}}}
$ tree ~/.clojure
/home/dave/.clojure
├── deps.edn
└── src
└── dave
└── prepl_server.clj
2 directories, 2 files
{:deps
{org.clojure/clojure {:mvn/version "1.10.1"}}
:aliases
{:prepl-server
{:extra-paths ["/home/dave/.clojure/src"]
:main-opts ["-m" "dave.prepl-server"]}}}
(ns dave.prepl-server
(:require [clojure.core.server :as server]
[clojure.java.io :as io])
(:import [java.net ConnectException Socket]))
(defn port-listening?
[host port]
(try
(.close (Socket. host port))
true
(catch ConnectException _ false)))
(defn- log
[& args]
(println (apply format args)))
(defn start-prepl-server!
[port]
(let [host "localhost"]
(when (port-listening? host port)
(log "Unable to start prepl server on port %d; that port is in use." port)
(System/exit 1))
(let [socket (server/start-server
{:accept `server/io-prepl
:address host
:port port
:name "Dave's amazing prepl server"})
effective-port (.getLocalPort socket)]
(doto (io/file ".socket-port")
.deleteOnExit
(spit effective-port))
(log "Started prepl server on port %d." effective-port))
;; Wait until process is interrupted.
@(promise)))
(defn -main
[& [port]]
(start-prepl-server! (if port (Integer/parseInt port) 0)))
# Run this in the root directory of any project with a deps.edn
$ clj -Aprepl-server
@gtoast
Copy link

gtoast commented Feb 5, 2020

Ah, I think I get it. You need to return a truthy value when closing the port succeeds, and the .close() method on Socket instances has a void return value which probably translates to a null value in Clojure, so you throw in a true. As the last evaluation in the function, that true becomes the return value for a successful call to port-listening?.

Thank you!

@daveyarwood
Copy link
Author

Yes, exactly!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment