Hello! I’m new to components
and would need a hand to understand some concepts. Given a database component like this one :
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 ?
Yes, it will have connection and db fields with nil
as their value. Is that answer your question?
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
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
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.
alright, I will it a try!
No. Sorry line 6
👍
@olfal Show us how you are creating and starting / stopping the component.
It sounds like you are passing the original (unstarted) component into the stop function?
(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!
@seancorfield exactly. It seems that the “auto-magical” system component is not updating the database component with the output of the start method
Clojure has immutable data structures. They don’t “update”.
absolutely
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
No.
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).
oh right!
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)
and that’s using #‘user/system
as a mutable global Var
that makes absolute sense! I was inferring too much magic 🙂
Clojure is already magic 🙂
thanks for your help
Any time!
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