Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
99 changes: 49 additions & 50 deletions src/darkleaf/di/core.clj
Original file line number Diff line number Diff line change
Expand Up @@ -182,14 +182,12 @@
(registry key))))

(defn- apply-middleware [registry mw]
(->
(cond
(nil? mw) registry
(fn? mw) (mw registry)
(map? mw) (apply-map registry mw)
(instance? Function mw) (.apply ^Function mw registry)
:else (throw (IllegalArgumentException. "Wrong middleware kind")))
(with-meta {::idx (-> registry meta (::idx 0) inc)})))
(cond
(nil? mw) registry
(fn? mw) (mw registry)
(map? mw) (apply-map registry mw)
(instance? Function mw) (.apply ^Function mw registry)
:else (throw (IllegalArgumentException. "Wrong middleware kind"))))

(defn- apply-middlewares [registry middlewares]
(reduce apply-middleware
Expand Down Expand Up @@ -570,6 +568,9 @@
(stop [_]
(p/stop original))))))))))))

(defn- update-key-key [target idx suffix]
(symbol (str (symbol target) "+di-update-key#" idx "-" suffix)))

Comment on lines +571 to +573
Copy link
Owner Author

@darkleaf darkleaf Apr 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

что если тут использовать вектор вместо склеивания символа:
[::update-key target idx suffix ...] ?

(defn update-key
Copy link
Owner Author

@darkleaf darkleaf Apr 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

или вообще все упростить

f должен возвращать обернутый объект, который останавливается stop исходного.
Например, если исходный объект был AutoClosable, и stop вызывал close, то новый объект должен тоже реализовывать AutoClosable и просировать вызов в исходный close
И это как раз определение декоратоа, что интерфейс должен сохраняться

2ъ f, args - это фабрики, которые можно не останавливать, что у нас всегда так, это ref и template или plain object. Тогда можно их зависимости просто примешать в зависимости таргета.
Можем это по description проверять, и если не так, то падать

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ну или прокидывать

(build [_ deps add-to-stop-list]
  ....)

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#58

"A registry middleware for updating built objects.

Expand All @@ -588,48 +589,46 @@
[target f & args]
{:pre [(key? target)]}
(fn [registry]
(let [idx (-> registry meta ::idx)
prefix (str (symbol target) "+di-update-key#" idx)
new-key (symbol (str prefix "-target"))
f-key (symbol (str prefix "-f"))
arg-keys (for [i (-> args count range)]
(symbol (str prefix "-arg#" i)))
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)))
(demolish [_ _])
p/FactoryDescription
(description [_]
{::kind :middleware
:middleware ::update-key
:target target
:new-target new-key
:f f-key
:args arg-keys}))
f-factory (update-description f assoc
::update-key {:target target
:role :f})
arg-factories (for [arg args]
(update-description arg assoc
::update-key {:target target
:role :arg}))
own-registry (zipmap (cons f-key arg-keys)
(cons f-factory arg-factories))
target-factory* (registry target)
target-factory (update-description target-factory* assoc
::update-key {:target target
:role :target})]
(when (= undefined-factory target-factory*)
(throw (ex-info (str "Can't update non-existent key " target)
{:type ::non-existent-key
:key target})))
(let [target-factory (registry target)
_ (when (= undefined-factory target-factory)
(throw (ex-info (str "Can't update non-existent key " target)
{:type ::non-existent-key
:key target})))
idx (-> target-factory p/description (:idx 0))
new-key (update-key-key target idx "target")
idx (inc idx)
f-key (update-key-key target idx "f")
arg-keys (for [i (-> args count range)]
(update-key-key target idx (str "arg#" i)))
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)))
(demolish [_ _])
p/FactoryDescription
(description [_]
{::kind :middleware
:middleware ::update-key
:target target
:new-target new-key
:f f-key
:args arg-keys
:idx idx}))
f-factory (update-description f assoc
::update-key {:target target
:role :f})
arg-factories (for [arg args]
(update-description arg assoc
::update-key {:target target
:role :arg}))
own-registry (zipmap (cons f-key arg-keys)
(cons f-factory arg-factories))]
(fn [key]
(condp = key
new-key target-factory
Expand Down
34 changes: 28 additions & 6 deletions test/darkleaf/di/tutorial/x_inspect_test.clj
Original file line number Diff line number Diff line change
Expand Up @@ -207,18 +207,34 @@
(t/deftest update-key-test
(t/is (= [{:key `a
:dependencies {`a+di-update-key#1-target :optional
`a+di-update-key#2-f :optional}
:description {::di/kind :middleware
:middleware ::di/update-key
:idx 2
:target `a
:new-target `a+di-update-key#1-target
:f `a+di-update-key#2-f
:args []
::di/root true}}
{:key `a+di-update-key#1-target
:dependencies {`a+di-update-key#0-target :optional
`a+di-update-key#1-f :optional
`a+di-update-key#1-arg#0 :optional}
Comment on lines +220 to 222
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

должны зависеть от таргета с предыдущего шага, а он как раз на 1 меньше

:description {::di/kind :middleware
:middleware ::di/update-key
:idx 1
:target `a
:new-target `a+di-update-key#1-target
:new-target `a+di-update-key#0-target
:f `a+di-update-key#1-f
:args [`a+di-update-key#1-arg#0]
::di/root true}}
{:key `a+di-update-key#1-target
:args [`a+di-update-key#1-arg#0]}}

{:key `a+di-update-key#0-target
:description {::di/kind :trivial
:object :obj

;; тут вот расхождение с `:target`
;; нужно подумать над консистентностью
#_#_
Comment on lines +234 to +237
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

может сделать альяс, и сделать мапы плоскими?

::di/update-key {:target `a
:role :target}}}
{:key `a+di-update-key#1-f
Expand All @@ -230,10 +246,16 @@
:description {::di/kind :trivial
:object "arg"
::di/update-key {:target `a
:role :arg}}}]
:role :arg}}}
{:key `a+di-update-key#2-f
:description {::di/kind :trivial
:object identity
::di/update-key {:target `a
:role :f}}}]
(di/inspect `a
{`a :obj}
(di/update-key `a str "arg")))))
(di/update-key `a str "arg")
(di/update-key `a identity)))))


(t/deftest add-side-dependency-test
Expand Down