mount

2016-01-24T02:03:05.000007Z

@tolitius it is expensive in the sense that it hits an api with a limit, the limit might not be a problem but I live in China, which means I don't have the best connectivity when I travel so I like to be able to keep state unreloaded as with an atom in defonce. Actually travel or not, internet to outside the Chinese firewall is unstable. Even the (albeit small unimportant) Google office in Shanghai didn't have decent internet, hahah.

2016-01-24T02:06:39.000008Z

I do change the data in the process, so it is kinda ephemeral. I do save it to be application state though.

tolitius 2016-01-24T02:10:30.000009Z

@bbss: wow that's quite a story :simple_smile:

2016-01-24T02:11:32.000010Z

Heheh, yes, living here is great except for the smog and bad internet.

tolitius 2016-01-24T02:16:40.000011Z

looks like there are two things: * this state is mutable * the restart / reload is "expensive" I don't have a good answer.. need to think about it.. looks like the usage implies some kind of start-with path, where you call the real API cache/persist data and then do start-with {#'your/state this-cache}. when you want to refresh that data from API, you would just call start... just thinking out loud without knowing the actual context :simple_smile:

tolitius 2016-01-24T02:19:43.000012Z

also mount should not "restart" a state if you recompile namespace(s) not associated with it

tolitius 2016-01-24T02:23:53.000015Z

did not add docs for it yet, but start-with now takes values as substitutes. start-with-states takes states as substitutes.

2016-01-24T02:33:35.000016Z

Wow, quick turnaround. I can separate the state to a different namespace then didn't try that one yet.

2016-01-24T02:34:22.000017Z

That was what I was slightly confused about, I don't need to call start anywhere in this project and defstates will still work.

tolitius 2016-01-24T03:04:51.000019Z

@bbss: yes, in cljs, you are probably running in cljc mode? which would mean that states will be lazily started when they are dereferenced: i.e. @my-state

2016-01-24T03:05:34.000020Z

ah, that explains the "has no deref" errors I didn't understand!

tolitius 2016-01-24T03:05:44.000022Z

they will also be all started by (mount/start), but this is an interesting property of cljc mode, where the system can be just lazily started

tolitius 2016-01-24T03:06:22.000023Z

not sure if you had a chance to read this: https://github.com/tolitius/mount/blob/0.1.9-SNAPSHOT/doc/clojurescript.md#managing-state-in-clojurescript

tolitius 2016-01-24T03:06:55.000025Z

I might need to make it stand out a little more.. since it does not seem to be easy to find from the docs table of context

2016-01-24T03:07:50.000026Z

ah yes I had read it but still very new to all of it so not sure I understood all.

tolitius 2016-01-24T03:08:02.000027Z

*"table of contents"

tolitius 2016-01-24T03:08:18.000028Z

ah.. not a problem at all, I can explain

tolitius 2016-01-24T03:09:16.000029Z

so the whole idea is, in cljs :advanced optimization wipes out all the namespaces, and renames all the vars, so we can no longer depend on a var being there to change it's value on start/stop

tolitius 2016-01-24T03:09:31.000030Z

hence mount has a cljc mode

tolitius 2016-01-24T03:09:44.000031Z

(mount/in-cljc-mode)

tolitius 2016-01-24T03:09:57.000032Z

that would be called anywhere before a call to (mount/start), usually at the entry point of an app: in the -main, web handler, etc.

tolitius 2016-01-24T03:10:16.000033Z

in this mode states are like simple version of an atom

tolitius 2016-01-24T03:10:54.000034Z

they don't have all the atom API (i.e. swap / reset!, etc..), but they have a @ (i.e. deref)

tolitius 2016-01-24T03:11:10.000035Z

so in order to use the state you would just deref it

2016-01-24T03:11:12.000036Z

right, that's why the double @@ on an atom

tolitius 2016-01-24T03:11:21.000037Z

(ns app.websockets
  (:require [app.conf :refer [config]]
            [app.audit-log :refer [audit log]])
  (:require-macros [mount.core :refer [defstate]]))

;; ...

(defstate system-a :start (connect (get-in @config [:system-a :uri]))
                   :stop (disconnect system-a))

tolitius 2016-01-24T03:11:48.000038Z

if you deref it without calling (mount/start) it would still work

2016-01-24T03:12:56.000039Z

I see. What would the downside of not calling start be?

tolitius 2016-01-24T03:13:16.000040Z

i.e. (a little internals): https://github.com/tolitius/mount/blob/0.1.9-SNAPSHOT/src/mount/core.cljc#L130-L132

tolitius 2016-01-24T03:14:13.000042Z

the system would be started lazily, which means you might expect certain things to start on, say, page load, but they would not be, because nobody needed them yet

tolitius 2016-01-24T03:14:55.000043Z

e.g. something needs to be loaded, but unless it is referenced anywhere or (mount/start) was called it would not be (loaded)

2016-01-24T03:15:04.000044Z

got it

2016-01-24T03:15:37.000045Z

so biggest problem would be that it takes a little longer load

tolitius 2016-01-24T03:17:23.000046Z

that would depend on the use case (app), but I would not say longer, I would say.. it could start certain states at different time

tolitius 2016-01-24T03:18:01.000047Z

if you need everything to start, and be very deterministic, you can call (mount/start)

2016-01-24T03:19:03.000048Z

okay

2016-01-24T03:19:24.000049Z

Thanks for the explanations!

2016-01-24T03:19:36.000050Z

I like using mount so far.

2016-01-24T03:20:24.000051Z

Hadn't looked at (or had the need to) component yet and found the recent discussions around mount vs component very interesting. Mount seemed like the more light-weight solution.

tolitius 2016-01-24T03:24:27.000052Z

sure, thanks for you feedback, keep it coming :simple_smile: I am sure we can improve, especially on the cljs side, so I would be very interested to know what works and what does not / could work better

2016-01-24T03:26:08.000053Z

I am experimenting a bit core.async, I needed a way to switch the way a put was handled for testing purposes and mount seemed good for that with it's start-with.

2016-01-24T03:27:12.000054Z

One optimization I think would be nice is to not reload the whole namespace but just the parts that changed. If I am not mistaken that is what figwheel does.

tolitius 2016-01-24T03:27:46.000056Z

mount does not reload namespaces :simple_smile:

tolitius 2016-01-24T03:28:06.000057Z

just restarts states that belong to a namespace that was reloaded

2016-01-24T03:28:06.000058Z

I mean restart all the defstates in a namespace that was editted

2016-01-24T03:29:31.000059Z

it's just a nice-to-have I guess, if I don't want a state to be reloaded I can change its namespace.

tolitius 2016-01-24T03:29:42.000060Z

ah.. yea, that's a thought. the problem is stale references. for example you have a conn state that holds a connection to a db, when a namespace is recompiled, a new conn reference is created

tolitius 2016-01-24T03:31:07.000062Z

that is what I alluded to a little earlier: > it might make sense to make this behavior configurable: https://github.com/tolitius/mount#recompiling-namespaces-with-running-states >I feel like, in cljs, it could address both issues above, especially during full page reloads / sending large recompiled increments (by figwheel)

tolitius 2016-01-24T03:33:20.000065Z

so you could potentially say something like

(defstate ^:dont-reload db :start (connect) :stop (disconnect))

tolitius 2016-01-24T03:33:37.000066Z

something like that... this is a rough thought :simple_smile:

tolitius 2016-01-24T03:33:57.000067Z

since I don't think it is nice to cary these ^:dont-reload around

2016-01-24T03:34:01.000068Z

or (defstateonce) or does that have different semantics

tolitius 2016-01-24T03:34:23.000069Z

well defstate already creates defonce

tolitius 2016-01-24T03:34:57.000070Z

mount has logic to cleanup and potentially restart dirty states

tolitius 2016-01-24T03:35:21.000071Z

which could be turned off for certain states or for all states..

tolitius 2016-01-24T03:35:59.000072Z

might be good to have regardless.. i.e. (mount/don't-reload-on-recompile), but a better name

2016-01-24T03:37:59.000073Z

I see. Something that still got me stuck sometimes with figwheel and cursive is not understanding how to manage creation of go-blocks. If I were to take from a channel with a go block and change the go block and re-evaluate the old go block would also still grab off the channel until I reload the browser.

2016-01-24T03:38:20.000074Z

I haven't tried that yet with mount but maybe that clean-up logic will take care of that too?

tolitius 2016-01-24T03:43:13.000075Z

yep, it will, if you provide that logic :simple_smile:

tolitius 2016-01-24T03:43:28.000076Z

i.e. some kind of a poison pill on :stop

2016-01-24T03:43:38.000078Z

not sure how to remove a go block though

tolitius 2016-01-24T03:44:52.000079Z

you mean something like this: https://github.com/danboykis/shipper/blob/master/src/shipper/tools.clj#L8-L18 ?

tolitius 2016-01-24T03:46:29.000081Z

i.e. using a some kind of stop channel to not recur anymore

2016-01-24T03:47:27.000083Z

Thanks. That could help me out.

tolitius 2016-01-24T03:48:54.000084Z

sure, let me know how it goes :simple_smile:

2016-01-24T03:49:19.000085Z

I will, working on different stuff now but I will