stuartsierra/component

component self reflection

hiredman opened this issue · 4 comments

it would be nice if when running something over a system via update-system, a component could know its "name" in the system.

I am working on some code that uses component internally to organize things, and it operates off a distributed job queue type thing. the first step when it pulls a job is to sort of route it back in to the nice component world, because each job tells you the "name" of the component it is destined for. I have some generic behavior I would like to capture in a component (and of course have component wire in different dependencies to specify the behavior for different cases), when this behavior includes the component publishing work that should be routed to itself, this is challenging because the component doesn't know what name that specific instance of the generic component will have in the system.

it seems like a dynamic binding of the key in update-system would work well

it would be nice if when running something over a system via update-system, a component could know its "name" in the system.

A few weeks ago I wrote an easy add-meta-key component/update-system function using clojure.core/meta. Hoping that others system's customizations would need it, I split it in a separate project plus assoc-meta-who-to-deps function, that gives you the parent component-key

@tangrammer I don't entirely follow what you are saying, I am not sure what parent means in the context of components. I would like for there to be some way for a given component to determine what name it has in the system map which is useful if you have to do something that leaves the component echo system and then call back in to the same component (registering some kind of callback if you will)

@hiredman yes you're right, in the context of components I meant the dependant component that has the dependency. The behavior taking this system-example :

(assert (= :a  (-> started-system :a meta :bigbang/key)))
(assert (= :a  (-> started-system :b :a meta :bigbang/key)))
(assert (= :b  (-> started-system :b :a meta :bigbang/who)))
(assert (= :c  (-> started-system :c :a meta :bigbang/who)))

It is a goal of mine that a component should never need to know anything about the system of which it is a part, and that code should never have to "reach through" the system to get at a component. See also my comments on #18.

What you're describing sounds like a specialized way to construct a system. If you want to tell a component its name, just assoc it. Something like this should work:

(defn assoc-component-names
  "Assocs :system-key <key> into each component in the system, where
  <key> is the location of the component within the system. Call this
  before start."
  [system]
  (reduce (fn [system key]
            (assoc-in system [key :system-key] key))
    system
    (keys system)))