001  (ns clj-activitypub.internal.thread-cache)
002  
003  (defn- current-time 
004    "Returns current time using UNIX epoch."
005    []
006    (System/currentTimeMillis))
007  
008  (defn- update-read-at [store k v]
009    (dosync
010     (commute store assoc k
011              (merge v {:read-at (current-time)}))))
012  
013  (defn make 
014    "Creates a thread-local cache."
015    ([] (make false))
016    ([cache-if-nil]
017     (let [store (ref {})]
018       (letfn [(cache-kv ([k v]
019                          (dosync
020                           (commute store assoc k
021                                    {:write-at (current-time) 
022                                     :read-at (current-time) 
023                                     :value v})
024                           v)))
025               (get-v ([k]
026                       (when-let [data (get @store k)]
027                         (update-read-at store k data)
028                         (:value data)))
029                      ([k compute-fn]
030                       (let [storage @store]
031                         (if (contains? storage k)
032                           (get-v k)
033                           (let [v (compute-fn)]
034                             (when (or (not (nil? v)) cache-if-nil)
035                               (cache-kv k v)
036                               (get-v k)))))))
037               (lru ([]
038                     (mapv
039                      (fn [[k v]] [k (:value v)])
040                      (sort-by #(-> % val :read-at) < @store))))]
041         {:cache-kv cache-kv 
042          :get-v get-v
043          :cache-if-nil cache-if-nil
044          :lru lru}))))