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))
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}
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 ...)
Hmm. What about this? https://github.com/tolitius/yurt#stop-functions
sory, but yurt is unknown for me
mount
should accept functions: https://github.com/tolitius/mount#value-of-values
@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: https://github.com/jakemcc/lein-test-refresh and boot: https://github.com/adzerk-oss/boot-test (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!