Fork me on GitHub

Hey, so I got my command-line stuff working, but I'm having a little trouble integrating ring-devel/wrap-reload with mount


Specifically, when I modify a file and re-request a page, I get a message that mount is stopping my web app, but it never seems to resume it


Like, I get the stop message but not the start message


My main app looks roughly like this:

(defn start-app!
  "Entry point for web server"
  (log/infof "Starting server on port %d..." (get-in config/app-config [:immutant :port]))
  (http-kit/run-server (development-mode web/application) (:immutant config/app-config)))

(declare application)
(defn stop-app! []
  (log/infof "Stopping server on port %d..." (get-in config/app-config [:immutant :port]))
  (application :timeout 300))

(defstate application :start (start-app!)
                      :stop  (stop-app!))


...where (development-mode web/application) is roughly (-> app wrap-reload) and app is my compojure-api routes


@timgilbert: are you using 0.1.7?


Yep. Should I try the snapshot?


yep, there (in 0.1.8-SNAPSHOT) was a ClojureScript reload fix, which also fixed the restarting recompiled states


let me know if you need it to be a release version, I'll release 0.1.8


since I was going to do it soon anyway


Ok, I'll try it and let you know if it fixes my problems, thanks


great, let me know how it goes


That did fix the issue I was seeing, thanks


Although I just realized I'm probably trying to solve my problem wrong in this case


To wit, I don't actually want to restart the web server in response to a recompilation - since the sequence is: * GET request to /foo * wrap-reload sees that a ns changed and recompiles it * mount sees that the ns was recompiled, restarts the server * client gets a connection reset error, since the server went down before a new response came in


Oops, gtg, bbl


is the ns that is being changed the same ns that has (defstate application.. ) in it?


@tolitius: Not quite, it's dependent on it though. So I've got more or less:

(ns foo.routes)
(defroutes my-routes (GET "/" ...))

;; ...

(ns foo.core
  (:require [foo.routes :refer [my-routes]])

(defn start-app! [] (http-kit/start-server my-routes {:port 4444})

(defstate application :start (start-app!) :stop (stop-app! application))

timgilbert20:01:00 when I make a change in foo.routes, I assume the compiler picks up on it as a dependency of foo.core and recompiles both namespaces - I haven't tried to verify that though


But it definitely runs through the :stop and (with 0.1.8, thanks) :start states for the application defstate


This is without making direct changes in foo.core


I think this is just a different way I need to think about my workflow


I don't think it would recompile foo.core


since the implementation of foo.core did not change => no need to recompile


I wouldn't have thought so either, yeah


I think I just need to think about the workflow more. I'm used to a ring-devel/wrap-reload workflow, which is roughly: server request -> scan for file changes -> recompile files, updating existing namespaces -> return response based on recompiled code


...but with this it's more like edit file -> reload changed ns from repl -> restart web server -> server request -> response from updated code


But maybe I just have some other dependency links I haven't seen or something


if you can use any hooks in wrap-reload you can start/stop states without the server (i.e. in case a server restart is not something you are looking for but in general, I don't think mount would restart an application state in your example.. I wonder if wrap-reload refreshes everything including foo.core which would make mount restart the "server"


Yeah, I think that might be what's happening. wrap-reload is a little short on docs, unfortunately, and its only option is an argument which changes the source-code tree it scans through


Looking at which wrap-reload uses, it does look as though it builds its own dependency rtee and reloads the tree, which I think would explain the behavior I'm seeing


I think for the purposes of getting stuff done, I'll just have the web server stored in an atom for now rather than defstate, since for my purposes nothing else in my object graph actually depends on it


interesting.. almost feels like in this case a defstate might need to have a some kind of :reload-on-recompile :false thingy..


Yeah, that would definitely be handy


I do feel like reloading the web server mid-request is kind of crazy now that I'm actually thinking about it, but it does work with vanilla ring development, so might be nice to support with mount


In my particular case, I rarely need to restart the web server itself, mostly I'm redefining routes and application code living in regular Clojure ns's, so not having a defstate for it isn't a huge loss necessarily