mount

mnewt 2017-04-05T17:13:43.839200Z

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
  :start
  {:port 4000 :join? false})

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

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

mnewt 2017-04-05T17:15:49.874553Z

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 ServerConnector@3c52e31{HTTP/1.1}{0.0.0.0:4000}
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)
#'yurt-test.core/s
(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 ServerConnector@3c52e31{HTTP/1.1}{0.0.0.0:4000}

mnewt 2017-04-05T17:17:21.899501Z

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

mike_ananev 2017-04-05T21:11:04.663783Z

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

mike_ananev 2017-04-05T21:11:17.666712Z

just (.stop http-server)

mike_ananev 2017-04-05T21:11:32.670284Z

cause http-server holds a state

mnewt 2017-04-05T21:14:28.709766Z

@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.

mike_ananev 2017-04-05T21:15:07.718892Z

: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 ...)

mnewt 2017-04-05T21:17:11.746697Z

Hmm. What about this? https://github.com/tolitius/yurt#stop-functions

mike_ananev 2017-04-05T21:17:43.753743Z

sory, but yurt is unknown for me

mnewt 2017-04-05T21:19:03.771345Z

mount should accept functions: https://github.com/tolitius/mount#value-of-values

tolitius 2017-04-05T21:21:03.797871Z

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

tolitius 2017-04-05T21:21:35.805197Z

i.e. yurts are stopped with yurt/destroy

mnewt 2017-04-05T21:22:31.817596Z

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?

mnewt 2017-04-05T21:22:45.820542Z

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

mnewt 2017-04-05T21:23:03.824413Z

Then add yurt

tolitius 2017-04-05T21:27:44.886472Z

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

tolitius 2017-04-05T21:28:02.890604Z

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

tolitius 2017-04-05T21:28:14.892839Z

vs. just mount for all the environments?

mnewt 2017-04-05T21:31:38.938892Z

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

tolitius 2017-04-05T21:36:40.002686Z

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: https://github.com/jakemcc/lein-test-refresh and boot: https://github.com/adzerk-oss/boot-test (i.e. boot watch speak test)

mnewt 2017-04-05T21:41:51.066082Z

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!

tolitius 2017-04-05T21:44:31.097609Z

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

mnewt 2017-04-05T21:45:15.106625Z

No, thank you!