A possible implementation for the idea expressed in the previous post - https://github.com/stuartsierra/component/pull/25
On Wednesday, March 18, 2015 at 2:41:46 PM UTC+1, platon...@gmail.com wrote: > > I've also been investigating the nested system approach/problem. > > The primary use case that I have is composing subsystems which are mostly > independent modules using a higher order system to run in one process. The > modules themselves can be easily extracted into separate applications thus > becoming their own top level systems which makes it desirable to keep their > system maps intact. > > Components inside modules might depend on the *whole* modules, not their > constituent parts. This allows to have modules call each other through the > API's in-process as well as being easily replaced by remote endpoints when > separated into multiple processes. > > This mostly works except for the components depending on other > modules/systems, e.g.: > > (require '[com.stuartsierra.component :as cmp]) > > (defrecord X [x started] > cmp/Lifecycle > (start [this] (if started (println "Already started " x) (println > "Starting " x " " this)) (assoc this :started true)) > (stop [this] (println "Stopping " x " " this) this)) > > (def sys1 (cmp/system-map :x (cmp/using (X. "depends on dep" nil) [:dep]))) > (def sys2 (cmp/system-map :y (cmp/using (X. "depends on sys1" nil) > [:sys1]))) > (def hsys (cmp/system-map :sys1 (cmp/using sys1 [:dep]), :sys2 (cmp/using > sys2 [:sys1]) :dep (X. "dependency" nil))) > > (cmp/start hsys) > > Starting dependency #user.X{:x dependency, :started nil} > Already started dependency > Starting depends on dep #user.X{:x depends on dep, :started nil, :dep > #user.X{:x dependency, :started true}} > > clojure.lang.ExceptionInfo: Error in component :sys2 in system > com.stuartsierra.component.SystemMap calling > #'com.stuartsierra.component/start > clojure.lang.ExceptionInfo: Missing dependency :dep of > clojure.lang.Keyword expected in system at :dep > > This happens because of the following: > 1. Dependency :*dep* of *sys1* is started in *hsys* > 2. *sys1* is started (:*dep* is started again, so the start/stop should > be idempotent) > 3. Dependency :*sys1* of *sys2* is started in *hsys* > 4. :*sys1* cannot be started as it depends on :*dep* which isn't present > in *sys2* > > This scenario could be supported by the Component library in several ways: > > 1. introduce an IdempotentLifecycle protocol which will be respected by > the Component library. Implement the protocol for the SystemMap. > IdempotentLifecycles will not be started or stopped for the second time, > also their dependencies will not be updated if they are already started. > 2. do not fail if a component already has a dependency under the specified > key. This is a hack compared to the first solution, but I might go with it > in the short term. > > Stuart, what do you think about that? Would you consider a PR implementing > the first proposal? > > On Wednesday, March 18, 2015 at 10:18:36 AM UTC+1, Stuart Sierra wrote: >> >> >> On Tue, Mar 17, 2015 at 5:47 PM, James Gatannah <james.g...@gmail.com> >> wrote: >> >>> FWIW, we've been using something that smells an awful lot like nested >>> systems for months now. I never realized we weren't supposed to. >>> >> >> >> It's not that nested systems *never* work, but from what I've seen they >> cause more complications than they're worth. The 'component' model doesn't >> forbid it, but it does not support dependencies between components in >> different "subsystems." >> >> I've found it easier to keep system maps "flat" and use namespaced >> keywords to distinguish "subsystem" groups, even in large systems with 30+ >> components. >> >> –S >> >> -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups "Clojure" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.