This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2016-02-02
Channels
- # admin-announcements (33)
- # announcements (2)
- # beginners (75)
- # boot (340)
- # braid-chat (6)
- # cider (30)
- # cljsrn (44)
- # clojars (19)
- # clojure (169)
- # clojure-austin (12)
- # clojure-czech (1)
- # clojure-japan (6)
- # clojure-miami (1)
- # clojure-poland (7)
- # clojure-russia (83)
- # clojurebridge (4)
- # clojurescript (166)
- # community-development (55)
- # component (2)
- # core-async (39)
- # core-matrix (3)
- # cursive (32)
- # data-science (3)
- # datavis (3)
- # datomic (58)
- # dirac (28)
- # emacs (4)
- # events (7)
- # hoplon (254)
- # immutant (29)
- # jobs (2)
- # jobs-discuss (4)
- # ldnclj (35)
- # lein-figwheel (3)
- # mount (202)
- # off-topic (9)
- # om (123)
- # onyx (22)
- # parinfer (112)
- # proton (11)
- # re-frame (6)
- # reagent (43)
- # ring (3)
- # spacemacs (2)
@wkf: let me know which solution worked for you, so I can keep a note of it, in case others need help with the start order, thx!
@tolitius: I got it working for now, just by putting the elasticmq namespace before the sqs namespace
it would be nice to be able to pass dependencies like component, maybe something like (mount/using {#’app.sqs/sqs [#’app.elasticmq/elasticmq]})
also, despite my criticism, mount feels better than component when developing at the repl
@wkf: I agree. the only case where it proves useful so far is in case of "one off" states that need a specific start order. I did not want to make it a requirement, but I agree, this is a very valid use case.
it's actually not a bad idea.. to be able to specify some desired order before (mount/start)
I actually welcome criticism, since it helps me think harder
I am trying to be very careful not to complicate the API, hence I am still thinking on depends-on
feature.. for about a month now
It seems like it would be quite useful to be able to wrap or transform states. for instance, I’ve got app.config/config, and in development, I’d like to add/change a few values
would be nice to have something like (mount/hook #’app.config/config (fn [c] (assoc c :whatever 123)))
there is some visual: https://github.com/tolitius/mount/issues/12#issuecomment-167150505
what I didn't want to do is specify all the dependencies, since it will have to be kept in sync with a natural order.
to handle indirect dependencies (ie, I depend on a rest api provided by another state, not its namespace)
but I agree. explicit dependencies to help out structure the start order are very good to have
one difficulty that I see with enriching
is validation.. but it might be easier than I think
i.e. in case a state a
is "enriched" with a dependency on state b
, how do we know that by starting b
a bit earlier to satisfy this dependency we not hurting it (`b`) by now not yet starting states that b
naturally depends on
but if we were to have access to the natural dependency graph, we could add new constraints
I "feel" there is a solution without breaking the idea of relying on the compiler, but I have not worked hard on validation yet..
if it is on a state level, but a final explicit order is still available via (graph/states-with-deps)
, I feel specifying :on-depends
on the individual state still has value of only needing to (mount/start)
without remembering (mount/something-else args)
beforehand
("component" / "state".. same thing), yes, I am not dismissing the central meta for :depends-on
, I see it being useful
just thinking out loud here… I’m not sure I would care if, as a first pass, the mount/using
api required I (the user) specify all dependencies
maybe some kind of :after
/ :before
can work here.. then elasticmq
can be:
(defstate elasticmq :start foo
:stop bar
:before #{#'app/sqs})
maybe an even looser constraint would work… if you use mount/using
, and you specify dependencies for a state, you must specify all its dependencies
seems like it might feel nice to express the ways in which you’re modifying load order/dependencies once
nothing so glamorous, something like (mount/with-states {#’blah #’bloop})
(mount/with-deps {#’hello #’sir})
(mount/start)
(an alternative would be a start function that takes different kinds of modifications… state swaps, deps, hooks, etc)
I might sacrifice the idea of (mount/start-with)
taking swaps, and have it to just take a map. this is not exactly "persistent" (i.e. before a start is called), since I like it to stay atomic, but it should achieve the flexibility:
(mount/start-with {:swap {}
:only #{}
:except #{}
:with-deps {}})
another way I was thinking some time ago is:
(-> (with {#'app.nyse/db test-db
#'app.nyse/publisher test-publisher})
(without #{#'app/nrepl feed-listener})
(with-args args)
start)
but start-with
taking a map looks less confusing and "easier" to visualize / share / understand
yea, something like a map can find usages / be provided from many places: * REPL * boot task / lein profile * config * dev.clj * etc..
it's a bit shaky to break (mount/start-with)
though since people's tests depend on it.. but I don't think / hope it is not too late
hopefully this is something people read: https://github.com/tolitius/mount/blob/master/CHANGELOG.md
Mount-lite actually has a 'parallel' branch now: https://github.com/aroemers/mount-lite/tree/parallel
In it are both a automatically deduced state dependency graph, and a way to influence that graph.
(just like I hope to inspire a composable API for Mount, which you also discussed I see 😄)
@arnout: the compatibility is definitely a great idea :) I saw the parallel work, it may not work for ClojureScript though
the idea of building a graph of off vars don't really project well to cljs since, unless bootstrap is used, have no support for Clojure ns
API in :advanced
mode
simply following @wkf idea of providing the full graph in :with-deps
might solve it in use cases that need it
Heh, removing suspend
and resume
? Cool, I can then remove "I don't need suspending" from mount-lite's README 😉
Hmm, I think Mount is great, because of the implicit dependency "graph" it creates (whether a proper graph or sequential does not matter)
yea, I stumble upon these (suspend/resume) often enough to question their need. You saw it first :)
But do you want to globally store such a data structure, like set-dependencies
? Or do you want to specify it each time you do one of the many REPL actions (`start-with`, start-except
, etc.)?
@arnout: agree with the value of implicit graph, but am option to override it does seem like a valid feature
I would tend to do something like: https://github.com/tolitius/mount/issues/48
True, hence: https://github.com/aroemers/mount-lite/blob/8e949c1dbcea7076fe3625e1b3da3fee6e2ddd7b/src/mount/graph.clj#L49-L50
Boasting myself here, but that graph also makes for quite a nice :up-to
start/stop option. It only starts (or stops) the necessary states to start/stop the given "up-to" state.
And that :up-to
option is actually also used for the "cascading stop" on a redefinition; meaning never a running state that suddenly lost its dependency. Which can still be overridden of course by the :only
option.
Whenever you want to test a certain state for example. Just (start (up-to #'state/under-test))
and your good to go, as all its dependencies will have started as well, without needing any knowledge of what states that would be.
Or if you only want to stop part of your system, but some base states can keep running.
And, with the automatic "cascading stop", you can safely redefine a state. It will only stop the necessary part of the app, and after a (start)
everything is back up.
Yes, because those two require knowledge about the implicit state dependency sequence/graph.
I see. I tend to minimize the number of states.. so I don't have that many in a single app usually. Since I tend to create states for external resources, and usually there are not a lot of those. But I guess when apps have many, yea, it could be more convenient
thinking more about :with-deps
, and the proposed changes to starts-with
, and I think it’s more complicated than it needs to be
I’m thinking of a data structure like this:
(mount/start-with
{:states
[#'app.config/config
#'app.server/server]
:dependencies
{#'app.server/server [#'app.config/config]}})
{:states
{#’app.config/config #’app.config/config
#’app.server/server #’app.server/server}
…}
we could also come up with some well defined semantics for how the “natural system” could be merged with the provided system
under the hood, there could be some refactoring to implement the start*
functions in terms of this system data structure
hm.. if I understood you correctly start-with-merge
would mutate the running system?
what's the benefit of hiding intentions (i.e. :only
, :except
, ...) behind a vector / map?
I’m thinking of a data structure that would contain an exhaustive list of states and dependencies
if we had that data structure, it would be pretty straightforward to implement the stop/start behavior as it exists now
looks like you are talking about a https://github.com/tolitius/yurt
i.e.
dev=> (yurt/blueprint)
{:components
{"neo.conf/config" {:status :not-started},
"neo.db/db" {:status :not-started},
"neo.www/neo-app" {:status :not-started},
"neo.app/nrepl" {:status :not-started}},
:blueprint
{"neo.conf/config" {:order 1},
"neo.db/db" {:order 2},
"neo.www/neo-app" {:order 3},
"neo.app/nrepl" {:order 4}}}
a detached system which internally (by it's type), knows how to be started / started-with / stopped
right.. it still does not do lifecycle fns composition, since.. well, it is just 4 days old
it was really written to mostly show that mount design does not limit developers by a single(ton) system, and many more than one system can be created, bound locally and used in the same runtime
as to mount, I would like to keep it system transparent, and mostly worry about the meat of the app (that has nothing to do with mount). I see "composable lifecycle" as something that is mostly helpful in testing. I do however agree that "indirect dependencies" should be a core feature that is a lot more important to have
@wkf: In mount-lite, there are these start*
and stop*
functions you talk about. They take a single spec: {#'statevar {:start ... :stop ...}, ...}
. This spec is being created by supplying one or more maps containing :only
, :except
and :substitute
(and more mount-lite specific) keys to start
/`stop`. Whenever you supply this to start
(or stop
) it is munged into the simple spec that start*
expects, by starting with a complete spec, and processing the :only
, :except
etc options on it. This design has suited me well, by allowing me to add more options quite easily, without altering the current API. Is that what you meant?