Skip to content

Commit

Permalink
a new implementation: ->cache
Browse files Browse the repository at this point in the history
  • Loading branch information
darkleaf committed Nov 7, 2024
1 parent ced835c commit ecca961
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 113 deletions.
77 changes: 22 additions & 55 deletions src/darkleaf/di/core.clj
Original file line number Diff line number Diff line change
Expand Up @@ -867,59 +867,26 @@
(inspect-middleware))]
@components))

(defn collect-cache
"
;; должен быть последним в цепочке, чтобы закешировать все
"
[cache]
(fn [registry]
(swap! cache assoc :registry (fn [key]
(case key
::implicit-root nil
(registry key))))
(fn [key]
(let [factory (registry key)]
(reify p/Factory
(dependencies [_]
(p/dependencies factory))
(build [_ deps]
(let [obj (p/build factory deps)]
(swap! cache assoc
key {:dependencies deps :object obj})
obj))
(demolish [_ obj]
(swap! cache dissoc
:registry
key)
(p/demolish factory obj)))))))

(defn use-cache
"
;; должен быть первым, а после него идти переопределения
[(di/use-cache cache)
{::param :new-version}]
"
[cache]
(let [cache @cache]
(fn [downstream-registry]
(let [cached-registry (:registry cache)
registry (fn [key]
;; тут бы тест написать на порядок
;; в gmonit хороший пример с reitit и update-key conj routes
(?? (cached-registry key)
(downstream-registry key)))]
(fn [key]
(let [factory (registry key)
{cached-deps :dependencies
cached-obj :object} (cache key)]
(reify p/Factory
(dependencies [_]
(p/dependencies factory))
(build [_ deps]
(if (= cached-deps deps)
cached-obj
(p/build factory deps)))
(demolish [_ obj]
(when (not (identical? cached-obj obj))
(defn ->cache []
(let [cache (volatile! {})]
(fn [registry]
(fn [key]
(let [factory (registry key)]
(reify p/Factory
(dependencies [_]
(p/dependencies factory))
(build [owner deps]
(locking cache
(?? (get @cache [key deps])
(let [obj (p/build factory deps)]
(vswap! cache assoc
[key deps] obj
[key owner obj] deps)
obj))))
(demolish [owner obj]
(locking cache
(when-some [deps (get @cache [key owner obj])]
(vswap! cache dissoc
[key deps]
[key owner obj])
(p/demolish factory obj))))))))))
91 changes: 33 additions & 58 deletions test/darkleaf/di/cache_test.clj
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,6 @@

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

(t/deftest cache-stop-test
(let [cache (atom {})
system (di/start ::root
{::root :root}
(di/collect-cache cache))]
(t/is (not (empty? @cache)))
(di/stop system)
(t/is (empty? @cache))))

(defn- some+identical? [a b]
(and (some? a)
(some? b)
Expand All @@ -29,77 +20,75 @@
[{_ ::param}]
(Object.))


;; тут получается, что мы реестр идентичный передаем
;; но у себя мы используем функции, и реестр будет не идентичный
;; и именно по этому функа и называется `di/->cache`, т.е. новый делается
;; и ее нельзя использовать как `di/update-key` например.
;; А нужно сделать `(def cache (di/->cache))` и дальше юзать cache
;; Может как-то примеры переделать под это?

(t/deftest ok-test
(let [cache (atom {})]
(with-open [main (di/start `a
{::param (Object.)}
(di/collect-cache cache))
secondary (di/start `a
(di/use-cache cache))]
(let [registry [{::param (Object.)}
(di/->cache)]]
(with-open [main (di/start `a registry)
secondary (di/start `a registry)]
(t/is (some+identical? @main @secondary)))))

(t/deftest changed-not-identical-test
(let [cache (atom {})]
(with-open [main (di/start `a
{::param (Object.)}
(di/collect-cache cache))
secondary (di/start `a
(di/use-cache cache)
(let [registry [{::param (Object.)}
(di/->cache)]]
(with-open [main (di/start `a registry)
secondary (di/start `a registry
{::param (Object.)})]
(t/is (some+not-identical? @main @secondary)))))

(t/deftest changed-equal-and-identical-test
(let [cache (atom {})]
(with-open [main (di/start `a
{::param :equal-and-identical}
(di/collect-cache cache))
secondary (di/start `a
(di/use-cache cache)
(let [registry [{::param :equal-and-identical}
(di/->cache)]]
(with-open [main (di/start `a registry)
secondary (di/start `a registry
{::param :equal-and-identical})]
(t/is (some+identical? @main @secondary)))))


(t/deftest changed-equal-but-not-identical-test
(let [cache (atom {})]
(with-open [main (di/start `a
{::param 'equal-but-not-identical}
(di/collect-cache cache))
secondary (di/start `a
(di/use-cache cache)
(let [registry [{::param 'equal-but-not-identical}
(di/->cache)]]
(with-open [main (di/start `a registry)
secondary (di/start `a registry
{::param 'equal-but-not-identical})]
(t/is (some+identical? @main @secondary)))))

(t/deftest changed-equal-but-different-test
(let [cache (atom {})]
(with-open [main (di/start `a
{::param []}
(di/collect-cache cache))
secondary (di/start `a
(di/use-cache cache)
(let [registry [{::param []}
(di/->cache)]]
(with-open [main (di/start `a registry)
secondary (di/start `a registry
{::param '()})]
(t/is (some+identical? @main @secondary)))))


(t/deftest start-stop-order-test
(let [cache (atom {})
(let [registry [{::param :param}
(di/->cache)]
log (atom [])
callbacks (fn [system]
{:after-build! (fn [{:keys [key]}]
(swap! log conj [:start system key]))
:after-demolish! (fn [{:keys [key]}]
(swap! log conj [:stop system key]))})]
(with-open [_ (di/start `a
{::param :param}
(di/collect-cache cache)
registry
(di/log (callbacks :main)))
_ (di/start [::x `a]
{::x :x}
(di/log (callbacks :second))
(di/use-cache cache))
registry)
_ (di/start [::y `a]
{::y :y}
(di/log (callbacks :third))
(di/use-cache cache))])
registry)])

(t/is (= [[:start :main ::param]
[:start :main `a]
Expand All @@ -121,17 +110,3 @@
[:stop :main `a]
[:stop :main ::param]]
@log))))

(t/deftest cache-registry-test
(let [cache (atom {})]
(with-open [main (di/start ::root
{::root (di/template [(di/ref ::a) (di/ref ::b)])
::a :a
::b :b}
(di/update-key ::root conj :c)
(di/collect-cache cache))
second (di/start ::root
(di/use-cache cache)
{::a "a"})]
(t/is (= [:a :b :c] @main))
(t/is (= ["a" :b :c] @second)))))

0 comments on commit ecca961

Please sign in to comment.