mount

mostr 2016-02-29T19:32:12.000174Z

hey, mount newbie here. Do you use partially applied functions as states in mount? E.g. I have (defn find-user [db id] …) function and turn it into state that depends on db state like (defstate user-finder :start (partial find-user db)).

mostr 2016-02-29T19:32:41.000175Z

This works fine, but doesn’t obviously “react” properly when db state is stopped

mostr 2016-02-29T19:34:03.000176Z

I mean it still keeps the “running” version of db state. Is there a way to combine those two: partial application to avoid dragging all the “deps” as well as having “live-link” to db state? Gist here: https://gist.github.com/mostr/372f65ece0ad6ea218d1

tolitius 2016-02-29T20:52:09.000177Z

@mostr: welcome! :simple_smile:

tolitius 2016-02-29T20:52:17.000178Z

looks like you are missing a :stop

tolitius 2016-02-29T20:52:19.000179Z

(defstate db :start users)

tolitius 2016-02-29T20:52:36.000180Z

that's why it is not stopped when (mount/stop) is called

tolitius 2016-02-29T20:52:51.000181Z

try (defstate db :start users :stop #{})

tolitius 2016-02-29T20:52:59.000182Z

or whatever stop value makes more sense

tolitius 2016-02-29T20:53:12.000183Z

in reality it will be a real db disconnect

mostr 2016-02-29T21:00:46.000185Z

hm, so I did the following:

(defn stop []
  (prn "Stopping users db")
  #{})

(defstate db
          :start users
          :stop (stop))

mostr 2016-02-29T21:00:57.000186Z

but still get

Loading src/clj_sandbox/ms/users_db.clj... done
(mount/stop)
=> {:stopped []}
(mount/start)
=>
{:started ["#'clj-sandbox.ms.users-db/db"
           "#'clj-sandbox.ms.user-finder/user-finder"
           "#'clj-sandbox.ms.user-finder/user-finder2"]}
(user-finder 2)
=> {:id 2, :name "bar"}
(mount/stop #'clj-sandbox.ms.users-db/db)
"Stopping users db"
=> {:stopped ["#'clj-sandbox.ms.users-db/db"]}
(user-finder 2)
=> {:id 2, :name "bar”}

mostr 2016-02-29T21:02:29.000187Z

not sure if this is real-life case (stop db while running), but trying to understand how things work in mount

mostr 2016-02-29T21:07:16.000188Z

Actually this works as expected as there is (partial…) in user-finder state definition which just probably takes “current” value/reference to db and doesn’t care about state changes. But I wonder whether there is a way to combine these two things: partial application + being aware of state changes

tolitius 2016-02-29T21:45:32.000189Z

I'll check it out in a couple hours.. will let you know

mostr 2016-02-29T21:56:07.000190Z

sure, no worries :simple_smile:

tolitius 2016-02-29T23:01:47.000191Z

looking at it with less distractions... :simple_smile: yea, this is expected, here is just plain Clojure example:

boot.user=> (def db {:a 42})
#'boot.user/db
boot.user=> (def find-key (partial db))
#'boot.user/find-key
boot.user=> (find-key :a)
42
boot.user=> (def a {})
#'boot.user/a
boot.user=> (find-key :a)
42

tolitius 2016-02-29T23:03:55.000192Z

in case you are ok with closing state over in function, you can simply (:require [users-db :refer [db]]) in user-finder and use it within a function.

tolitius 2016-02-29T23:04:34.000193Z

you are of course have freedom of where to use defstate, but I found it is best used for resources, like db in this case

tolitius 2016-02-29T23:05:14.000194Z

and API, such as user-finder could just use it as functions, rather than be defstates themselves

tolitius 2016-02-29T23:06:01.000195Z

there you can choose whether to close over that db and pass it there directly

tolitius 2016-02-29T23:14:24.000196Z

for example, say you have your db API that have access to db state live in app.db namespace. then you can do:

(:require [app.db :as db])

(GET "/find-user" [user]
  (db/find-user user))
or, if you'd like to use your pure find-user function, you can do that too:
(:require [app.db :refer [db]])

(GET "/find-user" [user]
  (find-user db user))
you could notice that in the second example, a route closes over the db state. which is ok, since this is the edge of your application (i.e. no impact or coupling with business logic).