Fork me on GitHub

Would someone be willing to help me understand what is wrong with this code?

(defn handler [request]
  {:status 200
   :headers {"Content-Type" "text/html"}
   :body "Hello yurt!"})

(defstate config
  {:port 4000 :join? false})

(defstate http-server
  (run-jetty handler config)
  (fn [server]
    (println "Stopping server" (str server))
    (.stop server)))

(defn -main [args]
  (start #'config)
  (start #'http-server))


This is what happens:

=> (-main nil)
2017-04-05 10:12:10.060:INFO:oejs.Server:nREPL-worker-0: jetty-9.2.10.v20150310
2017-04-05 10:12:10.118:INFO:oejs.ServerConnector:nREPL-worker-0: Started [email protected]{HTTP/1.1}{}
2017-04-05 10:12:10.120:INFO:oejs.Server:nREPL-worker-0: Started @11435ms
{:started ["#'yurt-test.core/http-server"]}
=> (def s http-server)
(stop #'http-server)
{:stopped ["#'yurt-test.core/http-server"]}
=> (.stop s)
2017-04-05 10:12:43.420:INFO:oejs.ServerConnector:nREPL-worker-0: Stopped [email protected]{HTTP/1.1}{}


Notice that the :stop function does not run, even though mount says the component stopped


@mnewt hi. may be you should not pass "abstract" server as argument to a :stop fn


just (.stop http-server)


cause http-server holds a state


@mike1452 Thanks. It does indeed work fine if I set :stop to (.stop http-server). However, the :stop value needs to be a 1 argument function because I’m trying to use yurt.


:stop should contain a block of code which works with http-server directly. :stop should be not fn but executable block of code like (do ...)


sory, but yurt is unknown for me


@mnewt does the code snippet you have use mount or yurt?


i.e. yurts are stopped with yurt/destroy


I want it to use both. I was thinking that mount should be used for production and yurt for testing. Is that how they are intended?


But first I was trying to get mount to work on its own


Then add yurt


hmm interesting 🙂 I would not say they should be used together, since they are a bit different in the approach: * with mount your app is started / stopped but it is "attached to the namespaces" * yurt creates an instance of your app that is completely "detached from the namespaces" yurt is useful when you need several instances of the whole application


is there a reason you'd like to use yurt in prod?


vs. just mount for all the environments?


Here is my use case: I have a running dev environment in my REPL, with server and database stuff going on. I want to run tests using my test environment, also in the REPL. So, I figured I could use yurt to fire up another instance of the application in test mode, without disturbing the dev environment


ah.. I see. it should theoretically work but you have to destroy yurts with (yurt/destroy ..), since if you build and start a yurt, it does no longer know what #'yurt-test.core/http-server var is. however I would not recommend to run dev and test envs within the same REPL, since it could quickly lead to confusion (classpath, class loaders, recompiled namespaces, any other changes, etc.). what I normally do, I have two REPLs running: one where I develop, and the other one that continuously runs tests (i.e. watches for any file changes and reruns the tests). this can be easily done with lein: and boot: (i.e. boot watch speak test)


Makes sense, thanks @mike1452 and @tolitius. In trying to get this to work, I could get either mount or yurt to be completely happy but weird things did happen when using both. I like lein-test-refresh but I find when I’m doing TDD that all the errors drive me nuts so I instead like to run tests individually until I get to a stable state. I’ll go back to just using mount, which is working great. Cheers!


@mnewt yep, I would agree that just using mount should do it. thanks for the feedback 🙂


No, thank you!