This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2016-05-20
Channels
- # beginners (49)
- # boot (139)
- # cider (10)
- # clojure (82)
- # clojure-belgium (59)
- # clojure-dusseldorf (5)
- # clojure-russia (11)
- # clojure-sanfrancisco (2)
- # clojure-uk (56)
- # clojurebridge (4)
- # clojurescript (138)
- # cursive (19)
- # datomic (8)
- # dirac (1)
- # editors (11)
- # emacs (18)
- # flambo (21)
- # hoplon (45)
- # jobs (1)
- # juxt (3)
- # keechma (1)
- # mount (43)
- # off-topic (2)
- # om (64)
- # om-next (1)
- # onyx (2)
- # other-languages (8)
- # re-frame (72)
- # reagent (99)
- # ring-swagger (7)
- # rum (3)
- # spacemacs (21)
- # specter (5)
- # untangled (42)
- # vim (4)
- # yada (7)
Heya guys .. i’m curious how people manage the ordering dependencies when using mount. For example, if I want to setup a websocket connection on mount/start, but other people need access to that connection when it becomes established, what’s a good way to handle this?
I cannot simply do defstate conn :start do-connection
and expect something in another namespace to be able to conn (:register #(… ))
for example. Given the way namespaces are loaded, I cannot have a ‘top level’ / ‘raw’ function that’s invoked immediately and expect conn to be available.
Is there a way to hook into a “the :start of this state is complete” -> now do something with state?
I figured that might be the case.. i will have to come up with some other mechanism I suppose
Imagine I only want one ws connection from my client -> server.. but many features might have to subscribe to various channels on that connection’s session. I don’t want a giant list of “when the connection is made hook up all these features”, but instead want the features to somehow be notified of the connection.
The more I type the more I realize this has nothing to do with mount, and I was just hoping mount might make the solution easier than it really is.
I'm not understanding why the features that use the connection wouldn't either be functions or other defstate
s.
They would, but figuring out a decoupled way to “hand the session over" to them and guarantee bootstrapping order, etc. is the real problem.
If it were me I would have those features take the connection as an argument, and have some defstate
call them with it as necessary.
@zane: I think I understand now. I can still guarantee ordering by making sure the feature that wants to use the connection also registers with mount.
(defstate core :start #(ws-namespace/ws-conn-state register-myself))
Where ws-conn-state
might return an api as opposed to data.For each feature that registers I maintain a seq of registerees, and upon a successful connection, let each one know.
Or you could do it the other way around where the features are defstate
s and refer directly to the defstate
with the connection in it.
I could, but that seems more coupling to me. I would prefer N unknown features requiring a connection, unless I’m misunderstanding you.
Hmm, doesnt seem like defstates are meant to ever be changed beyond :start? I can’t swap!
into one of them.
with mount it's expected that you declare your dependencies via require
s, what zane proposed:
(ns consumer
(:require [ws-connection :as ws]))
(defstate consumer :start (create-state ws/conn))
(defn do-something [] (... consumer ...))
if you have just one connection - this is not more coupled than having the consumer accept the connection as a parameter IMO@lwhorton: I was thinking about it.. https://github.com/tolitius/mount/issues/16 the simple solution has not come to me yet, but it will 🙂
for now, you can definitely do what @zane and @dm3 suggest: i.e. establish implicit dependencies via :require
another way you can think of approaching it would be running:
(mount/start #'ws/conn)
(mount/start)
which would start the connection before starting anything else, and then would bootstrap the appI dont mind ‘implicit dependencies’ as you say because, well, i dont think they’re that implicit
imo its no different than any other IoC I might write that does something like [:inject foo bar]
i guess you don’t get the luxury of other neat-o things like startable
and other runtime-pre-start configuration options
its a common pattern in most inversion of control containers — my favorite being https://github.com/castleproject/Windsor/blob/master/docs/README.md
it’s just a means to allow dynamic at-runtime configuration.. you can declare things like mixins, overrides, startable/stoppable, decorators, etc.
I haven’t found something similar in clojureland , but I also haven’t had the need (yet)
more than likely, but when you start talking about client-side guis where there is a lot of potential for reuse I found things like “on the fly” decorators to be amazing
dynamic at-runtime configuration
, in your use case (with ws conn
), can you share how you would solve it with a startable
?
sure, a fun lib I use in jsland https://github.com/mnichols/ankh provides an async startable implementation-