Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
darkleaf committed Oct 15, 2024
1 parent 9b36a26 commit b55ec97
Show file tree
Hide file tree
Showing 3 changed files with 212 additions and 0 deletions.
50 changes: 50 additions & 0 deletions src/darkleaf/di/core.clj
Original file line number Diff line number Diff line change
Expand Up @@ -780,3 +780,53 @@
~@body))
(finally
(.close resource#)))))))

;; может быть сделать 2 арности в одной функции вместо этих 2х функций?

(defn collect-cache []
(let [cache (atom {:started? true})]
(fn [registry]
(fn [key]
(if (= ::cache key)
(reify p/Factory
(dependencies [_]
nil)
(build [_ _]
cache)
(demolish [_ obj]
(reset! cache {:started? false})))
(let [factory (registry key)]
(reify p/Factory
(dependencies [_]
(p/dependencies factory))
(build [_ deps]
(let [obj (p/build factory deps)]
(when-not (contains? deps ::cache)
(swap! cache assoc
[:key->deps key] deps
[:key->obj key] obj))
obj))
(demolish [_ obj]
(p/demolish factory obj)))))))))

(defn use-cache [cache]
(fn [registry]
(fn [key]
(let [factory (registry key)
cache @cache
cached-deps (cache [:key->deps key])
cached-obj (cache [:key->obj key])]
(when-not (:started? cache)
(throw (IllegalStateException. "Invalid cache")))
(reify p/Factory
(dependencies [_]
(p/dependencies factory))
(build [_ deps]
(if (= cached-deps deps)
cached-obj
(p/build factory deps)))
(demolish [_ obj]
;;todo: add test
#_(if (identical? cached-obj obj)
nil
(p/demolish factory obj))))))))
109 changes: 109 additions & 0 deletions test/darkleaf/di/cache_test.clj
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
(ns darkleaf.di.cache-test
(:require
[clojure.test :as t]
[darkleaf.di.core :as di]))

(set! *warn-on-reflection* true)


;; мне надоело логгеры писать
;; может уже написать реестр, который логирует все действия?
;; только его нужно передавать извне
;; (atom [ [`key :started] [`key :stopped] ] )
(defn a
{::di/kind :component}
;; {::di/stop #(swap! (:log %))}

[]
[{log ::log}]
{:name :a
:obj (Object.)})

(t/deftest a-test
(di/with-open [[main cache] (di/start [`a ::di/cache]
(di/collect-cache))
[secondary] (di/start [`a]
(di/use-cache cache))]
(t/is (not= nil main secondary))
(t/is (identical? main secondary))))

(defn b
{::di/kind :component}
[{conf "B_CONF"}]
{:name :b
:conf conf
:obj (Object.)})

(t/deftest b-test
(di/with-open [[main cache] (di/start [`b ::di/cache]
{"B_CONF" "conf"}
;; должен быть последним в цепочке, чтобы закешировать все
(di/collect-cache))
[secondary] (di/start [`b]
(di/use-cache cache))]
(t/is (not= nil main secondary))
(t/is (identical? main secondary))))

(t/deftest b-changed-test
(di/with-open [[main cache] (di/start [`b ::di/cache]
{"B_CONF" "conf"}
(di/collect-cache))
[secondary] (di/start [`b]
;; должен быть первым, чтобы его можно было переопределять
(di/use-cache cache)
{"B_CONF" "changed"})]
(t/is (not= nil main secondary))
(t/is (not (identical? main secondary)))))

(defn c
{::di/kind :component}
[{a `a, b `b}]
{:name :c
:a a
:b b
:obj (Object.)})

(t/deftest c-test
(di/with-open [[main cache] (di/start [`c ::di/cache]
{"B_CONF" "conf"}
(di/collect-cache))
[secondary] (di/start [`c]
(di/use-cache cache))]
(t/is (not= nil main secondary))
(t/is (identical? main secondary))))

(t/deftest c-changed-test
(di/with-open [[main cache] (di/start [`c ::di/cache]
{"B_CONF" "conf"}
(di/collect-cache))
[secondary] (di/start [`c]
(di/use-cache cache)
{"B_CONF" "changed"})]
(t/is (not= nil main secondary))
(t/is (not (identical? main secondary)))
(t/is (= :c
(:name main)
(:name secondary)))
(t/is (identical? (:a main)
(:a secondary)))
(t/is (not (identical? (:b main)
(:b secondary))))
;; надо ли проверять?
(t/is (not (identical? (:obj main)
(:obj secondary))))))

(t/deftest invalid-cache-test
(let [[main cache :as system] (di/start [`c ::di/cache]
{"B_CONF" "conf"}
(di/collect-cache))
_ (di/stop system)]
(t/is (thrown? IllegalStateException
(di/start `c
(di/use-cache cache))))))

(t/deftest not-recursive-test
(di/with-open [[main cache] (di/start [`c ::di/cache]
{"B_CONF" "conf"}
(di/collect-cache))]
(t/try-expr "must not be recrusive"
(prn-str cache))))
53 changes: 53 additions & 0 deletions test/darkleaf/di/tutorial/z_memoize_test.clj
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
(ns darkleaf.di.tutorial.z-memoize-test ;;todo: name
(:require
[clojure.test :as t]
[darkleaf.di.core :as di]))

(defn connection
{::di/stop #(reset! % :stopped)}
[{url "CONNECTION_URL"}]
(atom :started))

(defn migrations
"A long running side effect"
{::di/kind :component}
[{connection `connection}]
#_
(when (= :stopped @connection)
(throw (IllegalStateException. "Connection is not started")))
(random-uuid))

(defn root
{::di/kind :component}
[{migrations `migrations}]
{:migrations migrations})

;; todo: check registry placement

(t/deftest ok
(let [[cache global-system :as root]
(di/start [::di/cache `root]
{"CONNECTION_URL" "1"}
(di/collect-cache))]

(with-open [local (di/start `root
(di/use-cache cache))]
(t/is (identical? global-system @local)))

(with-open [local (di/start `root
(di/use-cache cache)
{"CONNECTION_URL" "1"})]
(t/is (identical? global-system @local)))

(with-open [local (di/start `root
;; `use-cache` should be the first registry
(di/use-cache cache)
{"CONNECTION_URL" "2"})]
(t/is (not (identical? global-system @local))))


(di/stop root)

(t/is (thrown? IllegalStateException
(di/start `root
(di/use-cache cache))))))

0 comments on commit b55ec97

Please sign in to comment.