Skip to content

Commit

Permalink
save
Browse files Browse the repository at this point in the history
  • Loading branch information
darkleaf committed Jun 18, 2024
1 parent 62468ba commit 0b67af5
Show file tree
Hide file tree
Showing 2 changed files with 128 additions and 30 deletions.
145 changes: 123 additions & 22 deletions src/darkleaf/di/core.clj
Original file line number Diff line number Diff line change
Expand Up @@ -474,30 +474,131 @@
See `update`, `start`, `instrument`, `fmap`."
[target f & args]
{:pre [(or (key? f)
(ifn? f))
(every? key? args)]}
(let [own-keys (cond-> (set args)
(key? f) (conj f))]
(let [new-key (gensym "darkleaf.di.core/update-key-target#")
f-key (gensym "darkleaf.di.core/update-key-f#")
arg-keys (for [_ args] (gensym "darkleaf.di.core/update-key-arg#"))
new-factory (reify p/Factory
(dependencies [_]
(zipmap (concat [new-key f-key] arg-keys)
(repeat :optional)))
(build [_ deps]
(let [t (deps new-key)
f (deps f-key)
args (map deps arg-keys)]
(apply f t args))))
own-registry (zipmap (cons f-key arg-keys)
(cons f args))]
(fn [registry]
(fn [key]
(let [factory (registry key)]
(if (not= target key)
factory
(reify p/Factory
(dependencies [_]
(merge (p/dependencies factory)
(zipmap own-keys (repeat :required))))
(build [_ deps]
(let [f (deps f f)
args (map deps args)
original (p/build factory deps)
obj (apply f (p/unwrap original) args)]
(reify p/Stoppable
(unwrap [_]
obj)
(stop [_]
(p/stop original))))))))))))
(cond
(= new-key key)
(registry target)

(= target key)
new-factory

:else
(?? (own-registry key)
(registry key)))))))

#_(defn update-key
"A registry middleware for updating built objects.
target is a key to update.
f and args are keys.
Also f can be a function in term of `ifn?`.
f should not return a non-trivial instance of `p/Stoppable`.
```clojure
(def routes [])
(def subsystem-routes (di/template [[\"/posts\" (di/ref `handler)]]))
(di/start ::root (di/update-key `routes conj `subsystem-routes))
```
If you don't want to resolve keys like :some-name, you should use them in a in-place fn:
```clojure
(di/update-key `key #(assoc %1 :some-name %2) `some-value)
```
See `update`, `start`, `instrument`, `fmap`."
[target f & args]
(let [new-target-key (gensym "darkleaf.di.core/update-key-target#")
f-key (gensym "darkleaf.di.core/update-key-f#")
arg-keys (for [_ args] (gensym "darkleaf.di.core/update-key-arg#"))
own-registry (zipmap (cons f-key arg-keys)
(cons f args))]
(fn [registry]
(fn [key]
(let [factory (?? (own-registry key)
(registry key))]
(if (not= target key)
factory
(reify p/Factory
(dependencies [_]
(merge (p/dependencies factory)
(zipmap (keys own-registry)
(repeat :optional))))
(build [_ deps]
(let [f (deps f-key)
args (map deps arg-keys)
original (p/build factory deps)
obj (apply f (p/unwrap original) args)]
(reify p/Stoppable
(unwrap [_]
obj)
(stop [_]
(p/stop original))))))))))))


#_(defn update-key
"A registry middleware for updating built objects.
target is a key to update.
f and args are keys.
Also f can be a function in term of `ifn?`.
f should not return a non-trivial instance of `p/Stoppable`.
```clojure
(def routes [])
(def subsystem-routes (di/template [[\"/posts\" (di/ref `handler)]]))
(di/start ::root (di/update-key `routes conj `subsystem-routes))
```
If you don't want to resolve keys like :some-name, you should use them in a in-place fn:
```clojure
(di/update-key `key #(assoc %1 :some-name %2) `some-value)
```
See `update`, `start`, `instrument`, `fmap`."
[target f & args]
{:pre [(or (key? f)
(ifn? f))
(every? key? args)]}
(let [own-keys (cond-> (set args)
(key? f) (conj f))]
(fn [registry]
(fn [key]
(let [factory (registry key)]
(if (not= target key)
factory
(reify p/Factory
(dependencies [_]
(merge (p/dependencies factory)
(zipmap own-keys (repeat :required))))
(build [_ deps]
(let [f (deps f f)
args (map deps args)
original (p/build factory deps)
obj (apply f (p/unwrap original) args)]
(reify p/Stoppable
(unwrap [_]
obj)
(stop [_]
(p/stop original))))))))))))

(defn add-side-dependency
"A registry middleware for adding side dependencies.
Expand Down
13 changes: 5 additions & 8 deletions test/darkleaf/di/tutorial/x_update_key_test.clj
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,11 @@
[-deps]
["/a"])

(defn subsystem-b-route-data
{::di/kind :component}
[-deps]
["/b"])

(t/deftest update-key-test
(with-open [root (di/start `route-data
(di/update-key `route-data conj
`subsystem-a-route-data
`subsystem-b-route-data))]
(t/is (= [["/a"] ["/b"]] @root))))
(di/ref `subsystem-a-route-data)
["/b"]
nil)
{})]
(t/is (= [["/a"] ["/b"] nil] @root))))

0 comments on commit 0b67af5

Please sign in to comment.