Skip to content

Commit

Permalink
More specific error for components which are nil
Browse files Browse the repository at this point in the history
Before this change, a nil value in a system map would cause an error
::missing-component.

However, the most common cause of this error is a component which failed
to return a value from `start` or `stop`. We can distinguish this error
case from a component whose key was not in the system at all, and return
a more informative error message.

See also #17
  • Loading branch information
Stuart Sierra committed Feb 27, 2015
1 parent f31d8af commit fb89150
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 23 deletions.
57 changes: 34 additions & 23 deletions src/com/stuartsierra/component.clj
Expand Up @@ -46,6 +46,38 @@
:component component
:dependencies dependencies})))))

(defn- nil-component [system key]
(ex-info (str "Component " key " was nil in system; maybe it returned nil from start or stop")
{:reason ::nil-component
:system-key key
:system system}))

(defn- get-component [system key]
(let [component (get system key ::not-found)]
(when (nil? component)
(throw (nil-component system key)))
(when (= ::not-found component)
(throw (ex-info (str "Missing component " key " from system")
{:reason ::missing-component
:system-key key
:system system})))
component))

(defn- get-dependency [system system-key component dependency-key]
(let [component (get system system-key ::not-found)]
(when (nil? component)
(throw (nil-component system system-key)))
(when (= ::not-found component)
(throw (ex-info (str "Missing dependency " dependency-key
" of " (.getName (class component))
" expected in system at " system-key)
{:reason ::missing-dependency
:system-key key
:dependency-key dependency-key
:component component
:system system})))
component))

(defn system-using
"Associates dependency metadata with multiple components in the
system. dependency-map is a map of keys in the system to maps or
Expand All @@ -54,12 +86,7 @@
[system dependency-map]
(reduce-kv
(fn [system key dependencies]
(let [component (get system key)]
(when-not component
(throw (ex-info (str "Missing component " key " from system")
{:reason ::missing-component
:system-key key
:system system})))
(let [component (get-component system key)]
(assoc system key (using component dependencies))))
system
dependency-map))
Expand All @@ -77,16 +104,7 @@
(select-keys system component-keys)))

(defn- assoc-dependency [system component dependency-key system-key]
(let [dependency (get system system-key)]
(when-not dependency
(throw (ex-info (str "Missing dependency " dependency-key
" of " (.getName (class component))
" expected in system at " system-key)
{:reason ::missing-dependency
:system-key system-key
:dependency-key dependency-key
:component component
:system system})))
(let [dependency (get-dependency system system-key component dependency-key)]
(assoc component dependency-key dependency)))

(defn- assoc-dependencies [component system]
Expand All @@ -107,13 +125,6 @@
:system system}
t)))))

(defn- get-component [system key]
(or (get system key)
(throw (ex-info (str "Missing component " key " from system")
{:reason ::missing-component
:system-key key
:system system}))))

(defn update-system
"Invokes (apply f component args) on each of the components at
component-keys in the system, in dependency order. Before invoking
Expand Down
15 changes: 15 additions & 0 deletions test/com/stuartsierra/component_test.clj
Expand Up @@ -273,3 +273,18 @@
(let [c (->ComponentWithoutLifecycle nil)]
(is (= c (component/start c)))
(is (= c (component/stop c)))))

(defrecord ComponentReturningNil [state]
component/Lifecycle
(start [this]
nil)
(stop [this]
nil))

(deftest component-returning-nil
(let [a (->ComponentReturningNil nil)
s (component/system-map :a a :b (component-b))
e (try (component/start s)
false
(catch Exception e e))]
(is (= ::component/nil-component (:reason (ex-data e))))))

0 comments on commit fb89150

Please sign in to comment.