mount

kurt-yagram 2016-09-22T07:37:50.000293Z

just wondering: defstate is something like a global 'constant'(?) atom? If so, well, I always have a rather weird feeling with globals. So the use case for mount, is it about managing 'system state' rather than the state of a namespace? I'm trying to find out the main difference between mount and component. I did check https://github.com/tolitius/mount/blob/master/doc/differences-from-component.md#differences-from-component already. The only thing that actually bothers me about mount is that state is a global 'constant'(?).

dm3 2016-09-22T13:01:59.000301Z

yes, it's a global constant

dm3 2016-09-22T13:02:28.000302Z

the same way a System of components is a global constant if you store it in a Var

dm3 2016-09-22T13:02:55.000303Z

(in whatever sense we use the word "constant" here)

tolitius 2016-09-22T14:07:10.000304Z

@dhruv1: is it still a problem, or you're just wondering why it happens?

2016-09-22T14:07:35.000305Z

it’s no longer a problem.

2016-09-22T14:08:36.000306Z

and i’ve figured out why it happens. mount has an atom internally which keeps track of the state and that’s where i was running into the problem

2016-09-22T14:09:10.000307Z

i was wondering if there was a way to avoid this situation. it took me a bit of time to figure out why I kept getting the error.

tolitius 2016-09-22T14:17:13.000308Z

@kurt-yagram: I would not call it a constant necessarily since the state does change: does not remain to be "constant" between start and stop. the key here is that it is managed, i.e. it is not just a global singleton, as some people claim: but a managed state. > The only thing that actually bothers me about mount is that state is a global what exactly does bother you about it? the idea is that you'd make a state for an external resource, for example a database. In case you need a state (connection) to another database / different schema, you have plenty of options: https://github.com/tolitius/mount/blob/master/README.md#swapping-alternate-implementations or you can just create a different state. it reflects the reality if you think about it: database is your resource, and it is "single", you need connections to two different databases? it would be two different states (could be the exact same function to create these states, given the different configs, but two different instances with connections to two different databases).

kurt-yagram 2016-09-22T14:32:56.000310Z

@tolitius : yeah, it bothers me because of bad experiences with it, probably. It always bothered me and I don't really know why. Maybe I should just get over it. now, I might have to use mount a little different, but what I do know is: I read my config from, well, that doesn't matter, but I have like 1 configuration map, containing the config for different parts of may application. So I do:

(mount/start-with-args (::datomic config)
                         #'my.ns.db/conn)
  (mount/start-with-args (::security config)
                         #'my.ns.security/config)
  ...
In my.ns.db:
(defstate conn
  :start (new-connection (mount/args))
  :stop ...)
Now, I would prefer to use just (mount/start), or something like in the docs:
(-> (only #{#'foo/a
            #'foo/b
            #'foo/c
            #'bar/d
            #'baz/e})
    (with-args {:a 42})
    (except [#'foo/c
             #'bar/d])
    (swap-states {#'foo/a #'test/a})
    (swap {#'baz/e {:datomic {:uri "datomic:<mem://composable-mount>"}}})
    mount/start)
However, swapping my.ns.db/conn is a connection and can't be started/swapped with the map. So I would actually have to call new-connection where I call mount. I just can't figure out what's the best thing to do here: calling a bunch of functions to configure the state (like new-connection) in the main of the application, or passing the general config to all parts as mount/args? (In the latter, I pass actually way to much configuration). It's just: if I do the former, I get a cyclic dependency (unless I put methods as new-connection not inside the my.ns.db namespace?)

tolitius 2016-09-22T14:37:16.000311Z

@dhruv1: usually you would do something like (reset) https://github.com/tolitius/mount/blob/master/README.md#the-importance-of-being-reloadable but I agree, it might make sense to potentially have a some kind of (mount/reset) that could take params: i.e. (mount/reset :ignore-errors true). which, if well documented, could help in situations like this one. could you create an issue, so we don't forget?

2016-09-22T14:38:33.000314Z

@tolitius sounds good. thanks πŸ™‚

2016-09-22T14:45:43.000316Z

created. thanks @tolitius

tolitius 2016-09-22T14:46:54.000317Z

@dhruv1: thank you!

tolitius 2016-09-22T14:47:02.000318Z

@kurt-yagram: trying to piece the problem together... one sec

tolitius 2016-09-22T14:48:28.000319Z

@kurt-yagram: not understanding this piece:

swapping "my.ns.db/conn" is a connection and can't be started/swapped with the map

tolitius 2016-09-22T14:50:03.000321Z

do you need to create a different connection depending on the arguments? i.e.

tolitius 2016-09-22T14:50:06.000322Z

(defstate conn
  :start (new-connection (config :store))
  :stop ...)

tolitius 2016-09-22T14:50:42.000323Z

where (:config store) may return different (say database schemas)?

tolitius 2016-09-22T14:51:29.000324Z

i.e. -Dconf=prod-config.edn vs. -Dconf=dev-config.edn?

kurt-yagram 2016-09-22T15:00:45.000325Z

yeah, although not with -D parameters as such. The main struggle I have is: the way I start the application now is a bunch of mount/start-with-args. Now, I'm starting to realize that there's probably no way around this. I can use mount/start-with, and put create-... and new-... methods somewhere in the 'main' namespace. I don't really have a default state, so I always need to add the state during start. Or, taking the sms example ( https://github.com/tolitius/mount/blob/master/README.md#swapping-states-with-values ): create-sms-sender is inside the app.sms ns, so I can't call it from the ns where it is mounted. I can't do mount/start-with {#'app.sms/send-sms (app.sms/create-sms-sender (:sms config))}.

tolitius 2016-09-22T15:11:32.000327Z

> the way I start the application now is a bunch of mount/start-with-args why not via a single config? > I can't do mount/start-with {#'app.sms/send-sms (app.sms/create-sms-sender (:sms config))} what I don't understand is why you need to do it πŸ™‚ i.e. why not just https://github.com/tolitius/stater/blob/master/smsio/src/app/sms.clj#L12-L13 where (:sms config) would be different depending on the config file / profile / etc.. ?

kurt-yagram 2016-09-22T15:38:13.000329Z

Yeah, well, I actually just didn't want pass all configuration to each part, but only the component-specific configuration. Anyway, maybe I shouldn't make things so complicated πŸ˜›.

kurt-yagram 2016-09-22T15:38:55.000330Z

using (:whatever config) should do fine...

tolitius 2016-09-22T15:50:06.000331Z

@kurt-yagram: yea, I usually find as the app grows in size and gets more components, a config is a very convenient way to provide runtime dependent values. also, since config could be edn it is not that difficult to destructure, or you can just use cursors: https://github.com/tolitius/cprop#cursors πŸ™‚

πŸ‘ 1
kurt-yagram 2016-09-22T17:03:07.000335Z

cprops... I like