remove sweeper thread threshold stuff

i'm not totally convinced that it is that useful? i feel like just
making the sweeper thread run less frequently would solve most of the
same problems that the threshold was (possibly?) intended to solve?
This commit is contained in:
Gered 2022-01-04 19:59:15 -05:00
parent 6550dc4450
commit 20b4067188
2 changed files with 9 additions and 53 deletions

View file

@ -73,7 +73,7 @@
(all-entries [store] (all-entries [store]
"Returns a map containing all entries currently in the session store.")) "Returns a map containing all entries currently in the session store."))
(defrecord MemoryAgingStore [session-atom thread ttl refresh-on-write refresh-on-read op-counter op-threshold on-removal] (defrecord MemoryAgingStore [session-atom thread ttl refresh-on-write refresh-on-read on-removal]
AgingStore AgingStore
(read-timestamp [_ key] (read-timestamp [_ key]
(get-in @session-atom [key :timestamp])) (get-in @session-atom [key :timestamp]))
@ -97,8 +97,6 @@
nil))))) nil)))))
(write-session [_ key data] (write-session [_ key data]
(if op-threshold
(swap! op-counter inc))
(let [key (or key (unique-id))] (let [key (or key (unique-id))]
(if on-removal (if on-removal
; when we have an on-removal listener, we need to check if we are overwriting an entry ; when we have an on-removal listener, we need to check if we are overwriting an entry
@ -128,13 +126,9 @@
(defn- sweeper-thread (defn- sweeper-thread
"Sweeper thread that watches the session and cleans it." "Sweeper thread that watches the session and cleans it."
[session-atom ttl op-counter op-threshold sweep-interval on-removal] [session-atom ttl sweep-interval on-removal]
(loop [] (loop []
(let [[old new] (if op-threshold (let [[old new] (swap-vals! session-atom sweep-session ttl)]
(when (>= @op-counter op-threshold)
(reset! op-counter 0)
(swap-vals! session-atom sweep-session ttl))
(swap-vals! session-atom sweep-session ttl))]
(if (and on-removal (if (and on-removal
(not= old new)) (not= old new))
; TODO: is there a faster way to get the keys difference? maybe this is fine ... ? ; TODO: is there a faster way to get the keys difference? maybe this is fine ... ?
@ -153,13 +147,12 @@
(def default-opts (def default-opts
{:refresh-on-write true {:refresh-on-write true
:refresh-on-read true :refresh-on-read true
:sweep-threshold nil
:sweep-interval 30}) :sweep-interval 30})
(defn aging-memory-store (defn aging-memory-store
"Creates an in-memory session storage engine where entries expire after the given ttl" "Creates an in-memory session storage engine where entries expire after the given ttl"
[ttl & [opts]] [ttl & [opts]]
(let [{:keys [session-atom refresh-on-write refresh-on-read sweep-threshold sweep-interval on-removal] :as opts} (let [{:keys [session-atom refresh-on-write refresh-on-read sweep-interval on-removal] :as opts}
(merge (merge
default-opts default-opts
{:session-atom (atom {})} {:session-atom (atom {})}
@ -170,15 +163,14 @@
; any of these times! (no, you don't really need a sweeper thread running multiple times per second ...) ; any of these times! (no, you don't really need a sweeper thread running multiple times per second ...)
sweep-interval (* 1000 sweep-interval) sweep-interval (* 1000 sweep-interval)
ttl (* 1000 ttl) ttl (* 1000 ttl)
op-counter (if sweep-threshold (atom 0))
thread (Thread. thread (Thread.
^Runnable ^Runnable
(fn [] (fn []
(try (try
(sweeper-thread session-atom ttl op-counter sweep-threshold sweep-interval on-removal) (sweeper-thread session-atom ttl sweep-interval on-removal)
(catch InterruptedException e)))) (catch InterruptedException e))))
store (MemoryAgingStore. store (MemoryAgingStore.
session-atom thread ttl refresh-on-write refresh-on-read op-counter sweep-threshold on-removal)] session-atom thread ttl refresh-on-write refresh-on-read on-removal)]
(.start thread) (.start thread)
store)) store))

View file

@ -11,7 +11,6 @@
(merge (merge
{:refresh-on-read true {:refresh-on-read true
:refresh-on-write true :refresh-on-write true
:sweep-threshold nil
:sweep-interval 15} :sweep-interval 15}
opts))) opts)))
@ -113,8 +112,7 @@
(testing "Individual session entries are expired appropriately when read, independently of the sweep thread." (testing "Individual session entries are expired appropriately when read, independently of the sweep thread."
(let [as (aging-memory-store (let [as (aging-memory-store
1 ; expire after 1 second 1 ; expire after 1 second
{:sweep-threshold 1 ; sweeper thread write threshold is after every single write {:sweep-interval 10 ; sweeper thread tries to run every 10 seconds
:sweep-interval 10 ; sweeper thread tries to run every 10 seconds
})] })]
(write-session as "mykey" {:foo 1}) (write-session as "mykey" {:foo 1})
(is (= (read-session as "mykey") {:foo 1}) (is (= (read-session as "mykey") {:foo 1})
@ -123,45 +121,12 @@
(is (nil? (read-session as "mykey")) (is (nil? (read-session as "mykey"))
"session entry should no longer be present")))) "session entry should no longer be present"))))
(deftest sweeper-thread-expires-entries-at-interval-only-when-threshold-reached (deftest sweeper-thread-expires-entries-at-interval
(testing "When a threshold is specified, the sweeper thread expires entries whenever it runs only when the operation (write) threshold is reached." (testing "Sweeper thread expires entries whenever it runs."
(let [as (aging-memory-store (let [as (aging-memory-store
1 ; expire after 1 second 1 ; expire after 1 second
{:refresh-on-read true {:refresh-on-read true
:refresh-on-write true :refresh-on-write true
:sweep-threshold 5 ; only trigger sweep after 5 writes
:sweep-interval 1 ; sweeper thread tries to run every 1 second
})]
(write-session as "mykey" {:foo 1})
(Thread/sleep 2000) ; wait long enough for session ttl to elapse
; key should still exist, even though it's expired (not enough writes have occurred)
(is (integer? (read-timestamp as "mykey"))
"session entry should still be present even though it has expired")
; key should exist for three more writes
(write-session as "other-key" {:foo 1})
(is (integer? (read-timestamp as "mykey"))
"session entry should still be present even though it has expired")
(write-session as "other-key" {:foo 1})
(is (integer? (read-timestamp as "mykey"))
"session entry should still be present even though it has expired")
(write-session as "other-key" {:foo 1})
(is (integer? (read-timestamp as "mykey"))
"session entry should still be present even though it has expired")
; on the fifth write and after 1 second, key should not exist
(write-session as "other-key" {:foo 1})
(Thread/sleep 2000) ; allow time for sweeper thread to run
(is (nil? (read-timestamp as "mykey"))
"session entry should have been removed now"))))
(deftest sweeper-thread-expires-entries-at-interval-with-no-threshold-set
(testing "When a threshold is NOT specified, the sweeper thread expires entries whenever it runs."
(let [as (aging-memory-store
1 ; expire after 1 second
{:refresh-on-read true
:refresh-on-write true
:sweep-threshold nil ; no sweeper thread threshold
:sweep-interval 1 ; sweeper thread tries to run every 1 second :sweep-interval 1 ; sweeper thread tries to run every 1 second
})] })]
(write-session as "mykey" {:foo 1}) (write-session as "mykey" {:foo 1})
@ -203,7 +168,6 @@
(let [as (aging-memory-store (let [as (aging-memory-store
1 ; expire after 1 second 1 ; expire after 1 second
{:refresh-on-read true {:refresh-on-read true
:sweep-threshold 1 ; sweep runs after every write
:sweep-interval 1 ; sweep thread tries to run every 1 second :sweep-interval 1 ; sweep thread tries to run every 1 second
})] })]
(is (nil? (read-session as "foo")) (is (nil? (read-session as "foo"))