keep the sweeper thread inside MemoryAgingStore. add thread stop fn

this is a change for functionality that will almost never, ever be used
in practice. but i just didn't like the idea of the 'aging-memory-store'
function creating a thread that you then had no control over whatsoever
after it returns ... maybe someone, somewhere will benefit from this.
This commit is contained in:
Gered 2022-01-02 19:40:43 -05:00
parent f6aaf5e074
commit baecdaf136
2 changed files with 30 additions and 9 deletions

View file

@ -57,7 +57,7 @@
(read-timestamp [store key]
"Read a session from the store and return its timestamp. If no key exists, returns nil."))
(defrecord MemoryAgingStore [session-map ttl refresh-on-write refresh-on-read op-counter op-threshold]
(defrecord MemoryAgingStore [session-map thread ttl refresh-on-write refresh-on-read op-counter op-threshold]
AgingStore
(read-timestamp [_ key]
(get-in @session-map [key :timestamp]))
@ -86,7 +86,7 @@
(defn- sweeper-thread
"Sweeper thread that watches the session and cleans it."
[{:keys [ttl op-counter op-threshold session-map]} sweep-interval]
[session-map ttl op-counter op-threshold sweep-interval]
(loop []
(if op-threshold
(when (>= @op-counter op-threshold)
@ -96,11 +96,6 @@
(Thread/sleep sweep-interval)
(recur)))
(defn- in-thread
"Run a function in a thread."
[f]
(.start (Thread. ^Runnable f)))
(defn aging-memory-store
"Creates an in-memory session storage engine where entries expire after the given ttl"
[ttl & [opts]]
@ -116,7 +111,21 @@
sweep-interval (* 1000 sweep-interval)
ttl (* 1000 ttl)
op-counter (if sweep-threshold (atom 0))
store (MemoryAgingStore. session-atom ttl refresh-on-write refresh-on-read op-counter sweep-threshold)]
(in-thread #(sweeper-thread store sweep-interval))
thread (Thread.
^Runnable
(fn []
(try
(sweeper-thread session-atom ttl op-counter sweep-threshold sweep-interval)
(catch InterruptedException e))))
store (MemoryAgingStore. session-atom thread ttl refresh-on-write refresh-on-read op-counter sweep-threshold)]
(.start thread)
store))
(defn stop
"Stops the aging-memory-store. Currently only provided as a convenience for applications that need to restart their
web handler. This function should be used in such a case to stop the sweeper-thread. The vast majority of apps won't
need to call this ever."
[^MemoryAgingStore store]
(if store
(.interrupt ^Thread (.thread store))))

View file

@ -213,4 +213,16 @@
(is (nil? (read-session as "foo"))
"still no session entry present for this key"))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(deftest sweeper-thread-can-be-stopped
(let [as (->basic-aging-memory-store)]
(Thread/sleep 2000)
(is (.isAlive ^Thread (:thread as))
"sweeper thread is currently alive")
(stop as)
(Thread/sleep 1000)
(is (not (.isAlive ^Thread (:thread as)))
"sweeper thread is no longer alive")))
#_(run-tests)