Last active
February 5, 2020 17:22
-
-
Save daveyarwood/f890bf1529cb633c04b90ce5d5201d6d to your computer and use it in GitHub Desktop.
Dave's setup for starting a prepl server in tools.deps projects
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
;; ~/.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"}}} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
$ tree ~/.clojure | |
/home/dave/.clojure | |
├── deps.edn | |
└── src | |
└── dave | |
└── prepl_server.clj | |
2 directories, 2 files |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{:deps | |
{org.clojure/clojure {:mvn/version "1.10.1"}} | |
:aliases | |
{:prepl-server | |
{:extra-paths ["/home/dave/.clojure/src"] | |
:main-opts ["-m" "dave.prepl-server"]}}} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(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))) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Run this in the root directory of any project with a deps.edn | |
$ clj -Aprepl-server |
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!
Yes, exactly!
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
port-listening?
attempts to connect to the port in order to determine if the port is listening.Creating a Socket with that host and port as arguments will either connect successfully or it will throw a ConnectException. If it throws a ConnectException, we catch it and return false because we can conclude that the port is not listening.
We don't want the Socket hanging around, so we close it immediately. Then we return true because if we got that far (i.e. a ConnectException was not thrown), then we can conclude that the port is listening.