Fork me on GitHub
#beginners
<
2015-12-22
>
potetm00:12:20

@firinne: Are you defing a var that requires connecting to datomic?

firinne00:12:01

What should I do instead?

potetm00:12:32

I would recommend using https://github.com/stuartsierra/component to set your application up at run time.

potetm00:12:51

Then pass your conn information into any function that needs it

firinne00:12:52

yeah that seems to be the path

firinne00:12:17

but I’m having a little trouble figuring that out as well

potetm00:12:24

Yeah it’s a bit to figure out.

firinne00:12:46

is there an example (ideally with comments) of a system of components that JUST uses datomic and jetty

potetm00:12:59

Easier, but in the pejorative sense, would be to do something like:

(defonce datomic-uri (atom ""))

(defn get-conn [] (d/connect @datomic-uri))

firinne00:12:18

well then, simpler? 😉

potetm00:12:22

Yeah component

firinne00:12:57

ok so where might I look for the simplest example of a datomic/jetty set of components

firinne00:12:27

I can also paste in the component I wrote which is working less than ideally

potetm00:12:00

Working a little example up. One sec.

potetm00:12:14

(defprotocol IConnect
  (-connect [this]))

(defrecord Datomic [uri]
  IConnect
  (-connect [_]
    (d/connect uri)))

(component/system-map
  :datomic (->Datomic
             (get-in my-config [:datomic :uri])))

potetm00:12:06

You would initialize something like that^ in your -main, then you pass (:datomic system-map) into any function that needs to connect to datomic.

potetm00:12:51

And that function can look like:

(defn my-fn [datomic]
  (let [conn (-connect datomic)] …))

potetm00:12:57

(I would also recommend defining a function connect that just wraps -connect.)

potetm00:12:49

@firinne: That make sense?

firinne00:12:39

So I guess I’m missing a conceptual bridge between the problem and the solution. The problem as I understand it is that by having a (def conn (d/connect uri)), java is going to try to trigger the connection whenever I want to compile my app into an uberjar. What I am trying to do with a component is to hide that connection inside a protocol (which is sort of like an object..). The component returns a map with the connection, and then everywhere where In my query functions I would be calling ‘conn’ I instead reach into the component for the value of conn?

firinne00:12:28

@potem — is that basically what is going on?

firinne00:12:55

I guess the point where I’m confused is — if this mental model is right — why wouldn’t initializing the component in main still cause the same problems

potetm00:12:24

So I don’t have very long, but I’ll try to explain a bit. I try to bbl to answer any additional questions you have.

firinne00:12:43

yeah super grateful just for this so far

potetm00:12:09

So fundamentally you don’t want to have a connection attached to your namespace (via def).

potetm00:12:30

You can get around this by just calling d/connect everywhere you need a connection.

potetm00:12:45

Problem is, you need the URI to connect, so you have to pass that information around somehow.

potetm00:12:42

So one perfectly fine solution is the “easy” example above, where you defonce a URI, then call (get-conn) whenever you need a conn.

potetm00:12:48

So that’s one problem solved.

potetm00:12:42

But that kind of introduces another problem: what if you want to use a different URI? (e.g. you want to test something, or you have multiple databases)

potetm00:12:55

The URI in the namespace is the only one you can use.

firinne00:12:58

(def uri (str "datomic:free://" (env :dat-host) ":4334/guestbook"))

firinne00:12:05

wouldn’t that work?

potetm00:12:06

So that’s where component comes in.

firinne00:12:21

couldn’t I just change the string based on an environment variable?

firinne00:12:27

through environ

potetm00:12:51

yes, that would work

potetm00:12:04

but you still have the problem that I layed out above

potetm00:12:27

“what if you want to use a different URI” (e.g. for testing)

firinne00:12:53

then I’d only be able to do so by changing the environment variable being passed in

firinne00:12:10

so in repl it grabs dev, in test it grabs test

potetm00:12:33

Yes. And once it’s defined, there’s no clean way to re-define it.

firinne00:12:55

whereas with a component?

potetm00:12:01

So we can do better by defining the URI at the top-most level, then passing it down to anyone that needs to call connect.

potetm00:12:19

I gotta run to dinner. I’ll hopefully bbl simple_smile

firinne00:12:29

awesome. hey can’t thank you enough

firinne00:12:37

really really appreciate this

potetm02:12:26

@firinne: So everything making more sense?

potetm02:12:39

The protocols are just so you can have multiple implementations of a function. So you can have a (->TestDatomic) or something that has a completely different implementation.

potetm02:12:04

You don’t have to use them. You could just pass the URI around. But they do make it easier to have a completely different implementation of things.

potetm02:12:34

But if you’re not really familiar w/ protocols, you can pretty easily go without at first. Just remember when you hit a situation where things don’t quite fit or you feel like you need to use a switch, you should look into protocols.

trancehime04:12:41

Ugh, this is so frustrating

slipset14:12:24

If you're looking into a switch and protocols seem to be a bit hard to understand, multimethods are really nice