Fork me on GitHub
#component
<
2017-02-28
>
olfal03:02:44

Hello! I’m new to components and would need a hand to understand some concepts. Given a database component like this one :

olfal03:02:39

if the start method is returning the component itself associated with the new connection and db, will my component have its new connection and db fields when the system stops all components ?

tap03:02:36

Yes, it will have connection and db fields with nil as their value. Is that answer your question?

olfal03:02:41

Almost! 🙂 The thing is, when I start my component, I add the connection and db fields (line 12) but when I try to stop the component, I get a null pointer on line 16 when trying to disconnect the database because the :connection field is apparently nil

olfal03:02:01

When starting the component, I can see that the component returned by the start method has a not nil connection and db field, but both of them are nil when using the stop method, so I was wondering how the whole system is updating the component with the value returned by start

tap03:02:06

I’m not fully understand how it work. I kind of had the same issue the other day. For me, adding connnection as a second argument on line 9 fixed the issue. You might want to give that a try.

olfal03:02:42

alright, I will it a try!

tap03:02:17

No. Sorry line 6

seancorfield03:02:17

@olfal Show us how you are creating and starting / stopping the component.

seancorfield03:02:59

It sounds like you are passing the original (unstarted) component into the stop function?

seancorfield03:02:10

(let [db (new-database-component my-url)]
      started-db (component/start db)]
  ;; do stuff with started-db
  (component/stop started-db)) ; make sure you pass the _result_ of the start call here!

olfal03:02:27

@seancorfield exactly. It seems that the “auto-magical” system component is not updating the database component with the output of the start method

seancorfield03:02:47

Clojure has immutable data structures. They don’t “update”.

olfal03:02:10

absolutely

olfal03:02:27

By looking at the doc of the component library, it seemed to me that the underlying component system is reusing the output of the start functions to update (maybe like an atom?) the component so the new fields are available when stopping

seancorfield03:02:53

If you put your component in a global Var and use alter-var-root then you are mutating it (but that’s meant to be a REPL convenience only and now how to use Component in a program).

olfal03:02:29

oh right!

seancorfield03:02:39

In a REPL session, I’ll do something like

user=> (def system (make-my-system {:some “config”}))
user=> (alter-var-root #‘system component/start)
;; do a bunch of stuff
user=> (alter-var-root #‘system component/stop)

seancorfield03:02:20

and that’s using #‘user/system as a mutable global Var

olfal03:02:17

that makes absolute sense! I was inferring too much magic 🙂

seancorfield03:02:33

Clojure is already magic 🙂

olfal03:02:44

thanks for your help

hiredman17:02:33

it seems like people infer that there are things in component, or that component does things it just doesn't do, so I wrote a minimal re-implementation of component to show just how little there is https://gist.github.com/hiredman/075b45eaeb01e4b526ce6f8854685487