Fork me on GitHub
#mount
<
2016-01-04
>
timgilbert17:01:17

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

timgilbert17:01:16

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

timgilbert17:01:28

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

timgilbert17:01:43

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!))

timgilbert17:01:30

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

tolitius18:01:00

@timgilbert: are you using 0.1.7?

timgilbert18:01:16

Yep. Should I try the snapshot?

tolitius18:01:28

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

tolitius18:01:52

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

tolitius18:01:11

since I was going to do it soon anyway

timgilbert19:01:46

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

tolitius19:01:11

great, let me know how it goes

timgilbert19:01:45

That did fix the issue I was seeing, thanks

timgilbert19:01:20

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

timgilbert19:01:04

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

timgilbert19:01:26

Oops, gtg, bbl

tolitius19:01:59

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

timgilbert20:01:38

@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

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

timgilbert20:01:56

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

timgilbert20:01:44

This is without making direct changes in foo.core

timgilbert20:01:35

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

tolitius20:01:55

I don't think it would recompile foo.core

tolitius20:01:20

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

timgilbert20:01:40

I wouldn't have thought so either, yeah

timgilbert20:01:31

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

timgilbert20:01:39

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

timgilbert20:01:10

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

tolitius20:01:23

if you can use any hooks in wrap-reload you can start/stop states without the server (i.e. https://github.com/tolitius/mount#stop-an-application-except-certain-states) 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"

timgilbert20:01:27

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

timgilbert20:01:48

Looking at https://github.com/weavejester/ns-tracker 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

timgilbert20:01:22

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

tolitius20:01:54

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

timgilbert20:01:17

Yeah, that would definitely be handy

timgilbert20:01:13

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

timgilbert20:01:11

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