This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2017-04-07
Channels
- # beginners (41)
- # boot (38)
- # cider (17)
- # cljs-dev (52)
- # cljsjs (3)
- # clojure (200)
- # clojure-italy (8)
- # clojure-russia (50)
- # clojure-spec (28)
- # clojure-uk (45)
- # clojurescript (28)
- # core-async (9)
- # core-matrix (2)
- # cursive (16)
- # datascript (15)
- # datomic (50)
- # dirac (5)
- # emacs (20)
- # figwheel (8)
- # flambo (2)
- # hoplon (10)
- # incanter (1)
- # jobs (1)
- # leiningen (2)
- # lumo (26)
- # mount (171)
- # off-topic (22)
- # om (54)
- # onyx (2)
- # pedestal (27)
- # re-frame (10)
- # reagent (12)
- # ring (27)
- # ring-swagger (3)
- # rum (2)
- # slack-help (1)
- # spacemacs (134)
- # specter (6)
- # sql (15)
- # testing (20)
- # uncomplicate (5)
- # unrepl (49)
- # untangled (9)
- # yada (29)
@oahner ^:on-reload :noop
should only care about namespace recompilations / state redefinition. start / stop should work as usual.
it's the update-meta!
in mount-it
; it always runs even with :noop
so the state gets overwritten with the blank state in @meta-state
I had assumed it would behave like a defonce but no; the derefable state is defined with defonce but the content always gets reset by the defstate call
What I wanted out of :noop is a defonce-like defstate that does absolutely nothing on a subsequent call and keeps the initial state running as-is
While it does keep the initial state running through a reload (a webserver that binds to port 80 in the :start fn will not stop), it still replaces the state's @meta-state entry with a new, not running state, so the next (stop) does nothing and the subsequent (start) fails to start the actual webserver since port 80 is still in use by the previous state
yep, I see it. it does not cleanup the second time, since it "thinks" the state is stopped:
boot.user=> (require '[mount.tools.graph :as g])
nil
boot.user=> (pprint (g/states-with-deps))
({:name "#'boot.user/beatles",
:order 1,
:status #{:stopped},
:deps #{}})
which usually does not happen, since it's a noop
to begin with: i.e. the same state keeps running
well, the second start
sees a stopped state since mount-it
replaces the entry with a blank one
you have something like:
(defstate ^{:on-reload :noop} http-server
:start (start-www (config :hubble))
:stop ((:stop-server http-server)))
correct, but after the recompile, @meta-state's #'http-server entry now points to a new var
let me reproduce it with: https://github.com/tolitius/stater/tree/master/smsio
as an aside, if :on-reload :noop really was a noop on subsequent calls, there is a possibility that the initial running service (in this case http-server) could break with clojure.tools.namespace's refresh
, since it undefs pretty much everything, even a defonce, but I'm not sure it actually deletes anything from memory, so the thread spawned by start-www
probably wouldn't get affected
java.net.BindException: Address already in use
java.lang.RuntimeException: could not start [#'app.www/web-server] due to
hmm.. I wonder what "broke?" it. looks like a noop
state should not be marked as :stopped
I suppose t.n.refresh
can't entirely unmap the existing web-service since a) mount still has a reference to it and b) the whole environment gets captured by the closure that calls start-www
, but I'm pulling facts out of thin air on this subject
I sure am glad I'm not the only one getting this behavior tho, I spent the entire day looking at examples and other projects to see where I was using mount wrong
ok, so https://github.com/tolitius/mount/blob/master/src/mount/core.cljc#L150 should not be called (when (and ((running-states) s-name) (= :noop on-reload)))
well, a t.n.refresh
doesn't break a running web server, even tho everything under it gets undef'd
the lesser recompiles, either (require ... :reload)
and just copy/pasting the defstate
block into the repl, don't actually undef vars defined with defonce either, so they're pretty safe
meanwhile, when running a webserver in debug mode, most projects I've seen refer to the handler by ref so it always points to the latest defined routes anyway
what I've been doing so far is comment out the on-reload meta on the defstate, running it, then uncommenting it with the modified defstate again
I am looking at it.. the fix is not hard. the tricky part is to make "macro + var + ns" work in both clj
and cljs
I guess I have not noticed it lately since iff I change the ns
where I have things like server(s) defined, I want the server to restart..
yea, I love these challenges.. only when you think "ok, this is finally rock solid" people who pay attention have a question 🙂
heck, for now I think I'll just put the web-server into its own namespace without making it :noop and disable-reload! it
why do you have it :noop
to being with: what do you change in that namespace that does not require a server restart?
I learned more about how clojure deals with namespaces in the last 24 hours than in the 2 years before
strange.. I can pull it, and see it here: https://clojars.org/mount/versions/0.1.12-SNAPSHOT
so now ring's wrap-reload works without restarting the state, and t.n.refresh :after 'reset
works by restarting the state
I usually have something like: https://github.com/tolitius/stater/blob/master/smsio/dev/dev.clj
but having t.n.refresh is helpful for those edge cases where the state has just diverged too badly
yea, I used to carry this everywhere: https://github.com/tolitius/mount/blob/master/dev/clj/app/utils/logging.clj
ohh, I love cprop btw, I had a small utils module in my projects that pretty much did exactly that but worse and with less features, was an easy swap
yea, cprop
also started as a traveler file from project to project, until "I got my self together"..
I mostly use it with envoy
the last couple of years: https://github.com/tolitius/envoy
then I add a sprinkle of vault https://www.dotkam.com/2017/01/10/hubble-space-mission-securely-configured/ and I am a happy camper
a centralized server for all your projects' configuration and credentials that auto updates to your clojure config at runtime? what's not to like 🙂
right.. "auto updates to your clojure config at runtime" may not be to everyone's liking (ops people don't find this too appealing), but merging overrides (and secrets from vault) on start instead of carrying different files / ENV for different environments is a big win
cljs.user=> (defstate ^{:on-reload :noop} web-server :start 28 :stop :stopped)
#'cljs.user/web-server
cljs.user=> (mount/start)
{:started ["#'cljs.user/web-server"]}
cljs.user=> @@#'cljs.user/web-server
28
cljs.user=> (defstate ^{:on-reload :noop} web-server :start 28 :stop :stopped)
#'cljs.user/web-server
cljs.user=> @@#'cljs.user/web-server
28
cljs.user=> (mount/stop)
{:stopped ["#'cljs.user/web-server"]}
cljs.user=> (defstate ^{:on-reload :noop} web-server :start 42 :stop :stopped)
#'cljs.user/web-server
cljs.user=> (mount/start)
{:started ["#'cljs.user/web-server"]}
cljs.user=> @@#'cljs.user/web-server
42
so I clicked and clicked and clicked from those last links you shared and now I'm looking at hazelcast
I've been fighting with my IT guys to get redis and so far it's been blocked because "not supported on Windows Server" well enough and we're a microsoft shop
well that and I skimmed through the readme on https://github.com/tolitius/chazel
chazel
only implements features I actively use. it is minor compare to what hazelcast
can do
I am sure you'll get a kick out of hazelcast
, it is really simple, straight forward and quite powerful