From 2f7273129d48f70b98358327f87c9fb2d5c80212 Mon Sep 17 00:00:00 2001 From: fogus Date: Fri, 23 May 2014 11:07:01 -0400 Subject: [PATCH 001/145] Updating POM file to latest format --- pom.xml | 146 ++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 95 insertions(+), 51 deletions(-) diff --git a/pom.xml b/pom.xml index 1c8f072..113c6ba 100644 --- a/pom.xml +++ b/pom.xml @@ -1,64 +1,108 @@ - - + 4.0.0 + core.cache core.cache - 0.6.4-SNAPSHOT - ${artifactId} - A cache library for Clojure jar - - - - Eclipse Public License 1.0 - http://opensource.org/licenses/eclipse-1.0.php - repo - - - - - org.clojure - pom.contrib - 0.1.2 - - - - - fogus - Fogus - http://fogus.me - - - - - - org.clojure - data.priority-map - 0.0.2 - - - - - jira - http://dev.clojure.org/jira/browse/CCACHE - - + 0.6.4-SNAPSHOT + core.cache + Cache library for Clojure. scm:git:git://github.com/clojure/core.cache.git - http://github.com/clojure/core.cache + scm:git:ssh://git@github.com/clojure/core.cache.git + dc1275950fb27439251e0719da9eff40c81f8006 + + https://github.com/clojure/core.cache - - - - sonatype-oss-snapshots - https://oss.sonatype.org/content/repositories/snapshots - - - + src/main/clojure + src/test/clojure - src/test/clojure + resources + + + dev-resources + + + resources + + + target + target/classes + + + central + http://repo1.maven.org/maven2/ + + false + + + true + + + + clojars + https://clojars.org/repo/ + + true + + + true + + + + sonatype-oss-public + https://oss.sonatype.org/content/groups/public/ + + true + + + true + + + + + + org.clojure + clojure + 1.6.0 + + + org.clojure + data.priority-map + 0.0.2 + + + org.clojure + tools.nrepl + 0.2.3 + + + org.clojure + clojure + + + test + + + clojure-complete + clojure-complete + 0.2.3 + + + org.clojure + clojure + + + test + + + + From 3c4cd6f2f51ae6cd84e5ae226c0407f47aefe3b5 Mon Sep 17 00:00:00 2001 From: fogus Date: Mon, 4 Aug 2014 09:23:28 -0400 Subject: [PATCH 002/145] Fixing up POM to remove unneeded repos --- pom.xml | 76 ++++++++++----------------------------------------------- 1 file changed, 13 insertions(+), 63 deletions(-) diff --git a/pom.xml b/pom.xml index 113c6ba..f230dcb 100644 --- a/pom.xml +++ b/pom.xml @@ -9,10 +9,21 @@ scm:git:git://github.com/clojure/core.cache.git scm:git:ssh://git@github.com/clojure/core.cache.git - dc1275950fb27439251e0719da9eff40c81f8006 - + dc1275950fb27439251e0719da9eff40c81f8006 https://github.com/clojure/core.cache + + + Eclipse Public License 1.0 + http://opensource.org/licenses/eclipse-1.0.php + repo + + + + org.clojure + pom.contrib + 0.1.2 + src/main/clojure src/test/clojure @@ -32,38 +43,6 @@ target target/classes - - - central - http://repo1.maven.org/maven2/ - - false - - - true - - - - clojars - https://clojars.org/repo/ - - true - - - true - - - - sonatype-oss-public - https://oss.sonatype.org/content/groups/public/ - - true - - - true - - - org.clojure @@ -75,34 +54,5 @@ data.priority-map 0.0.2 - - org.clojure - tools.nrepl - 0.2.3 - - - org.clojure - clojure - - - test - - - clojure-complete - clojure-complete - 0.2.3 - - - org.clojure - clojure - - - test - - - From 8a94a4dcee13959b87acc08bba682ec200ae0b7f Mon Sep 17 00:00:00 2001 From: fogus Date: Mon, 4 Aug 2014 09:24:23 -0400 Subject: [PATCH 003/145] Fixing up POM to include author info --- pom.xml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/pom.xml b/pom.xml index f230dcb..953cbd2 100644 --- a/pom.xml +++ b/pom.xml @@ -24,6 +24,13 @@ pom.contrib 0.1.2 + + + fogus + Michael Fogus + http://www.fogus.me + + src/main/clojure src/test/clojure From 02df3cc0e0e2a1d2609a3e5c984530853b1ecffc Mon Sep 17 00:00:00 2001 From: fogus Date: Mon, 4 Aug 2014 09:26:44 -0400 Subject: [PATCH 004/145] Fixing up POM to set name more generically --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 953cbd2..7a9dda8 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ core.cache jar 0.6.4-SNAPSHOT - core.cache + ${artifactId} Cache library for Clojure. scm:git:git://github.com/clojure/core.cache.git From ded016d33264ed1af142a8f34d9c8c2a1780dd33 Mon Sep 17 00:00:00 2001 From: Ambrose Bonnaire-Sergeant Date: Tue, 5 Aug 2014 04:40:35 +0800 Subject: [PATCH 005/145] CCACHE-34 - Update data.priority-map to 0.0.4 Eliminates reflection warnings. --- README.md | 2 ++ pom.xml | 2 +- project.clj | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 8ccd38e..2799765 100644 --- a/README.md +++ b/README.md @@ -84,6 +84,8 @@ Developer Information Change Log ==================== +* Release 0.6.4-SNAPSHOT + * [CCACHE-34](http://dev.clojure.org/jira/browse/CCACHE-34) bump tools.priority-map dependency to 0.0.4 * Release 0.6.3 on 2013.03.15 * Added through to encapsulate check logic * Release 0.6.2 on 2012.08.07 [more information](http://blog.fogus.me/?p=4527) diff --git a/pom.xml b/pom.xml index 7a9dda8..f507ec2 100644 --- a/pom.xml +++ b/pom.xml @@ -59,7 +59,7 @@ org.clojure data.priority-map - 0.0.2 + 0.0.4 diff --git a/project.clj b/project.clj index ac03f0a..ce9bac1 100644 --- a/project.clj +++ b/project.clj @@ -1,7 +1,7 @@ (defproject core.cache "0.6.4-SNAPSHOT" :description "Cache library for Clojure." :dependencies [[org.clojure/clojure "1.6.0"] - [org.clojure/data.priority-map "0.0.2"]] + [org.clojure/data.priority-map "0.0.4"]] :profiles {:1.2 {:dependencies [[org.clojure/clojure "1.2.0"]]} :1.2.1 {:dependencies [[org.clojure/clojure "1.2.1"]]} :1.3 {:dependencies [[org.clojure/clojure "1.3.0"]]} From 8aac045991a0486a68d7a653cb02cff27d27c574 Mon Sep 17 00:00:00 2001 From: Paul Stadig Date: Sat, 9 Feb 2013 07:01:28 -0500 Subject: [PATCH 006/145] CCACHE-28: fixes concurrency bug in has? We were allowing for another thread to add an item to the cache after we'd already tried to pull out the SoftReference. Since the SoftReference had been pulled out before the item was added, it was nil, but since contains? returned true, we assumed that it was not nil. Signed-off-by: Ambrose Bonnaire-Sergeant --- src/main/clojure/clojure/core/cache.clj | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/clojure/clojure/core/cache.clj b/src/main/clojure/clojure/core/cache.clj index 700ad0f..4584c6a 100644 --- a/src/main/clojure/clojure/core/cache.clj +++ b/src/main/clojure/clojure/core/cache.clj @@ -509,8 +509,7 @@ (has? [_ item] (let [item (or item ::nil) ^SoftReference cell (get cache item)] - (and (contains? cache item) - (not (nil? (.get cell)))))) + (and cell (.get cell)))) (hit [this item] (clear-soft-cache! cache rcache rq) this) From 3ca9f6f3b182c84cff1869adc85a21f40f93e276 Mon Sep 17 00:00:00 2001 From: Ambrose Bonnaire-Sergeant Date: Tue, 5 Aug 2014 04:58:52 +0800 Subject: [PATCH 007/145] Update change log with CCACHE-28 --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 2799765..780940f 100644 --- a/README.md +++ b/README.md @@ -86,6 +86,7 @@ Change Log * Release 0.6.4-SNAPSHOT * [CCACHE-34](http://dev.clojure.org/jira/browse/CCACHE-34) bump tools.priority-map dependency to 0.0.4 + * [CCACHE-28](http://dev.clojure.org/jira/browse/CCACHE-28) concurrency bug in has? for SoftCache * Release 0.6.3 on 2013.03.15 * Added through to encapsulate check logic * Release 0.6.2 on 2012.08.07 [more information](http://blog.fogus.me/?p=4527) From cb33a36b56f27ccdb274f320c4d47004cfa95b64 Mon Sep 17 00:00:00 2001 From: Ambrose Bonnaire-Sergeant Date: Tue, 5 Aug 2014 10:27:59 +0800 Subject: [PATCH 008/145] SoftReference returns nil if empty. --- src/main/clojure/clojure/core/cache.clj | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/clojure/clojure/core/cache.clj b/src/main/clojure/clojure/core/cache.clj index 4584c6a..09bd088 100644 --- a/src/main/clojure/clojure/core/cache.clj +++ b/src/main/clojure/clojure/core/cache.clj @@ -509,7 +509,9 @@ (has? [_ item] (let [item (or item ::nil) ^SoftReference cell (get cache item)] - (and cell (.get cell)))) + (boolean + (when cell + (not (nil? (.get cell))))))) (hit [this item] (clear-soft-cache! cache rcache rq) this) From 4fcd5fe52f6e896f6732942394ad624f460cdd25 Mon Sep 17 00:00:00 2001 From: Ambrose Bonnaire-Sergeant Date: Tue, 5 Aug 2014 11:17:58 +0800 Subject: [PATCH 009/145] Switch arguments to equiv so both caches always unwrap to their base --- src/main/clojure/clojure/core/cache.clj | 4 ++-- src/test/clojure/clojure/core/cache/tests.clj | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/main/clojure/clojure/core/cache.clj b/src/main/clojure/clojure/core/cache.clj index 09bd088..4b07a8b 100644 --- a/src/main/clojure/clojure/core/cache.clj +++ b/src/main/clojure/clojure/core/cache.clj @@ -90,8 +90,8 @@ (clojure.core/cons ~base-field elem#)) (empty [this#] (seed this# (empty ~base-field))) - (equiv [_# other#] - (clojure.lang.Util/equiv ~base-field other#)) + (equiv [this# other#] + (= other# ~base-field)) clojure.lang.Seqable (seq [_#] diff --git a/src/test/clojure/clojure/core/cache/tests.clj b/src/test/clojure/clojure/core/cache/tests.clj index 52812f1..422de0f 100644 --- a/src/test/clojure/clojure/core/cache/tests.clj +++ b/src/test/clojure/clojure/core/cache/tests.clj @@ -443,3 +443,7 @@ N non-resident HIR block (is (= :quux (.lookup old-soft-cache :foo3 :quux))) (is (not (.has? soft-cache :foo1))) (is (not (.has? old-soft-cache :foo1))))))) + +(deftest test-equiv + (is (= (fifo-cache-factory {:a 1 :c 3} :threshold 3) + (fifo-cache-factory {:a 1 :c 3} :threshold 3)))) From 19574f5da66b45f5fec0a9e2980559c52152f85e Mon Sep 17 00:00:00 2001 From: Ambrose Bonnaire-Sergeant Date: Tue, 5 Aug 2014 11:18:30 +0800 Subject: [PATCH 010/145] cons should implement conj, not c.c/cos --- src/main/clojure/clojure/core/cache.clj | 4 ++-- src/test/clojure/clojure/core/cache/tests.clj | 6 ++++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/main/clojure/clojure/core/cache.clj b/src/main/clojure/clojure/core/cache.clj index 4b07a8b..c84b1a2 100644 --- a/src/main/clojure/clojure/core/cache.clj +++ b/src/main/clojure/clojure/core/cache.clj @@ -86,8 +86,8 @@ (clojure.core/count ~base-field)) clojure.lang.IPersistentCollection - (cons [_# elem#] - (clojure.core/cons ~base-field elem#)) + (cons [this# elem#] + (seed this# (conj ~base-field elem#))) (empty [this#] (seed this# (empty ~base-field))) (equiv [this# other#] diff --git a/src/test/clojure/clojure/core/cache/tests.clj b/src/test/clojure/clojure/core/cache/tests.clj index 422de0f..2e25353 100644 --- a/src/test/clojure/clojure/core/cache/tests.clj +++ b/src/test/clojure/clojure/core/cache/tests.clj @@ -447,3 +447,9 @@ N non-resident HIR block (deftest test-equiv (is (= (fifo-cache-factory {:a 1 :c 3} :threshold 3) (fifo-cache-factory {:a 1 :c 3} :threshold 3)))) + +(deftest test-persistent-cons + (is (let [starts-with-a (fifo-cache-factory {:a 1} :threshold 3)] + (= (fifo-cache-factory {:a 1 :c 3} :threshold 3) + (conj starts-with-a [:c 3]) + (conj starts-with-a {:c 3}))))) From d56ff677caa680ec08114f9d7d126562b24e7882 Mon Sep 17 00:00:00 2001 From: Ambrose Bonnaire-Sergeant Date: Tue, 5 Aug 2014 11:18:41 +0800 Subject: [PATCH 011/145] Don't need to qualify here --- src/main/clojure/clojure/core/cache.clj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/clojure/clojure/core/cache.clj b/src/main/clojure/clojure/core/cache.clj index c84b1a2..e0181e0 100644 --- a/src/main/clojure/clojure/core/cache.clj +++ b/src/main/clojure/clojure/core/cache.clj @@ -83,7 +83,7 @@ clojure.lang.Counted (count [this#] - (clojure.core/count ~base-field)) + (count ~base-field)) clojure.lang.IPersistentCollection (cons [this# elem#] From ef35965cf835f8c927abc3e5da57651b9adb660e Mon Sep 17 00:00:00 2001 From: Ambrose Bonnaire-Sergeant Date: Tue, 5 Aug 2014 11:22:29 +0800 Subject: [PATCH 012/145] Add changelog --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 780940f..92caa94 100644 --- a/README.md +++ b/README.md @@ -84,9 +84,10 @@ Developer Information Change Log ==================== -* Release 0.6.4-SNAPSHOT +* Release 0.7.0-SNAPSHOT * [CCACHE-34](http://dev.clojure.org/jira/browse/CCACHE-34) bump tools.priority-map dependency to 0.0.4 * [CCACHE-28](http://dev.clojure.org/jira/browse/CCACHE-28) concurrency bug in has? for SoftCache + * [CCACHE-29](http://dev.clojure.org/jira/browse/CCACHE-29) fix conj implementation for caches * Release 0.6.3 on 2013.03.15 * Added through to encapsulate check logic * Release 0.6.2 on 2012.08.07 [more information](http://blog.fogus.me/?p=4527) From ce63e6a9cbec64d10c65ffa8d11716c533396094 Mon Sep 17 00:00:00 2001 From: Ambrose Bonnaire-Sergeant Date: Tue, 5 Aug 2014 11:44:53 +0800 Subject: [PATCH 013/145] make-reference shouldn't be dynamic --- README.md | 1 + src/main/clojure/clojure/core/cache.clj | 2 +- src/test/clojure/clojure/core/cache/tests.clj | 6 +++--- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 92caa94..9b8b4c0 100644 --- a/README.md +++ b/README.md @@ -88,6 +88,7 @@ Change Log * [CCACHE-34](http://dev.clojure.org/jira/browse/CCACHE-34) bump tools.priority-map dependency to 0.0.4 * [CCACHE-28](http://dev.clojure.org/jira/browse/CCACHE-28) concurrency bug in has? for SoftCache * [CCACHE-29](http://dev.clojure.org/jira/browse/CCACHE-29) fix conj implementation for caches + * [CCACHE-30](http://dev.clojure.org/jira/browse/CCACHE-30) make-reference need not be dynamic * Release 0.6.3 on 2013.03.15 * Added through to encapsulate check logic * Release 0.6.2 on 2012.08.07 [more information](http://blog.fogus.me/?p=4527) diff --git a/src/main/clojure/clojure/core/cache.clj b/src/main/clojure/clojure/core/cache.clj index e0181e0..bdc2e74 100644 --- a/src/main/clojure/clojure/core/cache.clj +++ b/src/main/clojure/clojure/core/cache.clj @@ -486,7 +486,7 @@ (.remove rcache r) (recur (.poll rq))))) -(defn ^{:dynamic true} make-reference [v rq] +(defn make-reference [v rq] (if (nil? v) (SoftReference. ::nil rq) (SoftReference. v rq))) diff --git a/src/test/clojure/clojure/core/cache/tests.clj b/src/test/clojure/clojure/core/cache/tests.clj index 2e25353..61b11d0 100644 --- a/src/test/clojure/clojure/core/cache/tests.clj +++ b/src/test/clojure/clojure/core/cache/tests.clj @@ -426,9 +426,9 @@ N non-resident HIR block (deftest test-soft-cache (let [ref (atom nil) old-make-reference make-reference] - (binding [make-reference (fn [& args] - (reset! ref (apply old-make-reference args)) - @ref)] + (with-redefs [make-reference (fn [& args] + (reset! ref (apply old-make-reference args)) + @ref)] (let [old-soft-cache (soft-cache-factory {:foo1 :bar}) r @ref soft-cache (assoc old-soft-cache :foo2 :baz)] From 6a5583555fa288266562ab3f427ea91349b61649 Mon Sep 17 00:00:00 2001 From: Ambrose Bonnaire-Sergeant Date: Tue, 5 Aug 2014 11:45:25 +0800 Subject: [PATCH 014/145] Bump dev version, perhaps this will please Hudson. --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index f507ec2..8ef02db 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ core.cache core.cache jar - 0.6.4-SNAPSHOT + 0.7.0-SNAPSHOT ${artifactId} Cache library for Clojure. From a77b003d6593f7bde2f27f03ec52310b68aa0ea6 Mon Sep 17 00:00:00 2001 From: Ambrose Bonnaire-Sergeant Date: Tue, 5 Aug 2014 12:10:26 +0800 Subject: [PATCH 015/145] Only update LRU usage map if cache contains the lookup key --- src/main/clojure/clojure/core/cache.clj | 4 +++- src/test/clojure/clojure/core/cache/tests.clj | 14 +++++++++++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/main/clojure/clojure/core/cache.clj b/src/main/clojure/clojure/core/cache.clj index bdc2e74..01a9c7f 100644 --- a/src/main/clojure/clojure/core/cache.clj +++ b/src/main/clojure/clojure/core/cache.clj @@ -210,7 +210,9 @@ (hit [_ item] (let [tick+ (inc tick)] (LRUCache. cache - (assoc lru item tick+) + (if (contains? cache item) + (assoc lru item tick+) + lru) tick+ limit))) (miss [_ item result] diff --git a/src/test/clojure/clojure/core/cache/tests.clj b/src/test/clojure/clojure/core/cache/tests.clj index 61b11d0..40dcfaa 100644 --- a/src/test/clojure/clojure/core/cache/tests.clj +++ b/src/test/clojure/clojure/core/cache/tests.clj @@ -181,7 +181,19 @@ (assoc :a 1) (assoc :b 2) (assoc :b 3) - .cache))))) + .cache)))) + + (is (= {:d 4 :e 5} + (-> (lru-cache-factory {} :threshold 2) + (hit :x) + (hit :y) + (hit :z) + (assoc :a 1) + (assoc :b 2) + (assoc :c 3) + (assoc :d 4) + (assoc :e 5) + .cache)))) (defn sleepy [e t] (Thread/sleep t) e) From 0901a24bd7dba6898464684920e0105079296cb9 Mon Sep 17 00:00:00 2001 From: Ambrose Bonnaire-Sergeant Date: Tue, 5 Aug 2014 12:11:24 +0800 Subject: [PATCH 016/145] Update changelog --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 9b8b4c0..3eff261 100644 --- a/README.md +++ b/README.md @@ -89,6 +89,7 @@ Change Log * [CCACHE-28](http://dev.clojure.org/jira/browse/CCACHE-28) concurrency bug in has? for SoftCache * [CCACHE-29](http://dev.clojure.org/jira/browse/CCACHE-29) fix conj implementation for caches * [CCACHE-30](http://dev.clojure.org/jira/browse/CCACHE-30) make-reference need not be dynamic + * [CCACHE-26](http://dev.clojure.org/jira/browse/CCACHE-26) hit function in LRU cache can give funny results * Release 0.6.3 on 2013.03.15 * Added through to encapsulate check logic * Release 0.6.2 on 2012.08.07 [more information](http://blog.fogus.me/?p=4527) From f4e387580f29c7d767e756e8059ee84dcbf0b05a Mon Sep 17 00:00:00 2001 From: Nicola Mometto Date: Tue, 5 Aug 2014 10:13:47 +0200 Subject: [PATCH 017/145] fix pom.xml Signed-off-by: Ambrose Bonnaire-Sergeant --- pom.xml | 36 ++++++++---------------------------- 1 file changed, 8 insertions(+), 28 deletions(-) diff --git a/pom.xml b/pom.xml index 8ef02db..593c0c0 100644 --- a/pom.xml +++ b/pom.xml @@ -1,17 +1,18 @@ - + + 4.0.0 - core.cache core.cache - jar 0.7.0-SNAPSHOT ${artifactId} Cache library for Clojure. + scm:git:git://github.com/clojure/core.cache.git scm:git:ssh://git@github.com/clojure/core.cache.git - dc1275950fb27439251e0719da9eff40c81f8006 + HEAD https://github.com/clojure/core.cache + Eclipse Public License 1.0 @@ -19,11 +20,13 @@ repo + org.clojure pom.contrib 0.1.2 + fogus @@ -31,31 +34,8 @@ http://www.fogus.me - - src/main/clojure - src/test/clojure - - - resources - - - - - dev-resources - - - resources - - - target - target/classes - + - - org.clojure - clojure - 1.6.0 - org.clojure data.priority-map From 0621528d7eab8ac04e0a3c421aeed0269ed74dfc Mon Sep 17 00:00:00 2001 From: Ambrose Bonnaire-Sergeant Date: Tue, 5 Aug 2014 22:53:45 +0800 Subject: [PATCH 018/145] Next release will be 0.6.4 --- README.md | 2 +- pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 3eff261..4ced204 100644 --- a/README.md +++ b/README.md @@ -84,7 +84,7 @@ Developer Information Change Log ==================== -* Release 0.7.0-SNAPSHOT +* Release 0.6.4-SNAPSHOT * [CCACHE-34](http://dev.clojure.org/jira/browse/CCACHE-34) bump tools.priority-map dependency to 0.0.4 * [CCACHE-28](http://dev.clojure.org/jira/browse/CCACHE-28) concurrency bug in has? for SoftCache * [CCACHE-29](http://dev.clojure.org/jira/browse/CCACHE-29) fix conj implementation for caches diff --git a/pom.xml b/pom.xml index 593c0c0..dc9aad3 100644 --- a/pom.xml +++ b/pom.xml @@ -2,7 +2,7 @@ 4.0.0 core.cache - 0.7.0-SNAPSHOT + 0.6.4-SNAPSHOT ${artifactId} Cache library for Clojure. From 10e4c452ac2fab7b69623cbf1e67fb840a9652d0 Mon Sep 17 00:00:00 2001 From: "Hudson @ build.clojure.org" Date: Tue, 5 Aug 2014 17:06:46 -0500 Subject: [PATCH 019/145] [maven-release-plugin] prepare release core.cache-0.6.4 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index dc9aad3..ae7f85c 100644 --- a/pom.xml +++ b/pom.xml @@ -2,14 +2,14 @@ 4.0.0 core.cache - 0.6.4-SNAPSHOT + 0.6.4 ${artifactId} Cache library for Clojure. scm:git:git://github.com/clojure/core.cache.git scm:git:ssh://git@github.com/clojure/core.cache.git - HEAD + core.cache-0.6.4 https://github.com/clojure/core.cache From 184b94a363b62c0fb2d9f621fa590fb9cc345efe Mon Sep 17 00:00:00 2001 From: "Hudson @ build.clojure.org" Date: Tue, 5 Aug 2014 17:06:47 -0500 Subject: [PATCH 020/145] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index ae7f85c..e18cfa4 100644 --- a/pom.xml +++ b/pom.xml @@ -2,14 +2,14 @@ 4.0.0 core.cache - 0.6.4 + 0.6.5-SNAPSHOT ${artifactId} Cache library for Clojure. scm:git:git://github.com/clojure/core.cache.git scm:git:ssh://git@github.com/clojure/core.cache.git - core.cache-0.6.4 + HEAD https://github.com/clojure/core.cache From 7b99e1dd3f0044d61a18a011832b2ca774f8751b Mon Sep 17 00:00:00 2001 From: Ambrose Bonnaire-Sergeant Date: Wed, 6 Aug 2014 11:20:51 +0800 Subject: [PATCH 021/145] Thank our contributors --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 4ced204..6467d6e 100644 --- a/README.md +++ b/README.md @@ -85,6 +85,7 @@ Change Log ==================== * Release 0.6.4-SNAPSHOT + * Thanks to Paul Stadig and Nicola Mometto who contributed patches for this release * [CCACHE-34](http://dev.clojure.org/jira/browse/CCACHE-34) bump tools.priority-map dependency to 0.0.4 * [CCACHE-28](http://dev.clojure.org/jira/browse/CCACHE-28) concurrency bug in has? for SoftCache * [CCACHE-29](http://dev.clojure.org/jira/browse/CCACHE-29) fix conj implementation for caches From 65857f6a8c114f73c10f8b0f99ed1c5d1f06d54f Mon Sep 17 00:00:00 2001 From: Ambrose Bonnaire-Sergeant Date: Wed, 6 Aug 2014 11:49:29 +0800 Subject: [PATCH 022/145] Bump core.cache versions --- README.md | 6 +++--- project.clj | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 6467d6e..8313189 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ core.cache is based on an old library named Clache that has been thouroughly dep Releases and Dependency Information ======================================== -Latest stable release: 0.6.3 +Latest stable release: 0.6.4 * [All Released Versions](http://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22org.clojure%22%20AND%20a%3A%22core.cache%22) @@ -33,14 +33,14 @@ Latest stable release: 0.6.3 [Leiningen](https://github.com/technomancy/leiningen) dependency information: - [org.clojure/core.cache "0.6.3"] + [org.clojure/core.cache "0.6.4"] [Maven](http://maven.apache.org/) dependency information: org.clojure core.cache - 0.6.3 + 0.6.4 diff --git a/project.clj b/project.clj index ce9bac1..5d5191d 100644 --- a/project.clj +++ b/project.clj @@ -1,4 +1,4 @@ -(defproject core.cache "0.6.4-SNAPSHOT" +(defproject core.cache "0.6.5-SNAPSHOT" :description "Cache library for Clojure." :dependencies [[org.clojure/clojure "1.6.0"] [org.clojure/data.priority-map "0.0.4"]] From 6f19778348a347427c08521500d8eb02b7fff329 Mon Sep 17 00:00:00 2001 From: Ambrose Bonnaire-Sergeant Date: Wed, 6 Aug 2014 11:50:35 +0800 Subject: [PATCH 023/145] Date 0.6.4 --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 8313189..6742e6d 100644 --- a/README.md +++ b/README.md @@ -84,7 +84,7 @@ Developer Information Change Log ==================== -* Release 0.6.4-SNAPSHOT +* Release 0.6.4 on 2014.08.06 * Thanks to Paul Stadig and Nicola Mometto who contributed patches for this release * [CCACHE-34](http://dev.clojure.org/jira/browse/CCACHE-34) bump tools.priority-map dependency to 0.0.4 * [CCACHE-28](http://dev.clojure.org/jira/browse/CCACHE-28) concurrency bug in has? for SoftCache From f9f79611e88dcd5ef2ba50cc45314e983754235d Mon Sep 17 00:00:00 2001 From: Fogus Date: Thu, 7 Aug 2014 10:17:45 -0400 Subject: [PATCH 024/145] Update README.md Added missing closing paren. I fail at LISP --- README.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 6742e6d..21bef60 100644 --- a/README.md +++ b/README.md @@ -51,17 +51,17 @@ Example Usage ```clojure (require '[clojure.core.cache :as cache]) - (def C (cache/fifo-cache-factory {:a 1, :b 2}) + (def C (cache/fifo-cache-factory {:a 1, :b 2})) - (if (cache/has? C :c) - (cache/hit C :c) - (cache/miss C :c 42)) + (if (cache/has? C :c) + (cache/hit C :c) + (cache/miss C :c 42)) - ;=> {:a 1, :b 2, :c 42} + ;=> {:a 1, :b 2, :c 42} - (cache/evict C :b) + (cache/evict C :b) - ;=> {:a 1} + ;=> {:a 1} ``` Refer to docstrings in the `clojure.core.cache` namespace, or the [autogenerated API documentation](http://clojure.github.com/core.cache/) for additional documentation From cdda4dedf96377ca63d9a6e55f02e276682219ba Mon Sep 17 00:00:00 2001 From: Alex Miller Date: Thu, 11 Dec 2014 11:05:42 -0600 Subject: [PATCH 025/145] Add missing end parens --- docs/Using.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/Using.md b/docs/Using.md index ba2792e..e5a7f66 100644 --- a/docs/Using.md +++ b/docs/Using.md @@ -13,7 +13,7 @@ To use the cache implementations or extend the core.cache protocols you first ne Next you should create an instance of a specific cache type, optionally seeded: ```clojure -(def C (cache/fifo-cache-factory {:a 1, :b 2}) +(def C (cache/fifo-cache-factory {:a 1, :b 2})) ``` To find a value in a map by its key you have a couple choices: From 5e9d67cf0351de5fe65b85ccd9f483cb2452b528 Mon Sep 17 00:00:00 2001 From: puredanger Date: Tue, 22 Mar 2016 10:40:52 -0500 Subject: [PATCH 026/145] CACHE-37 fix typo in docstring --- src/main/clojure/clojure/core/cache.clj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/clojure/clojure/core/cache.clj b/src/main/clojure/clojure/core/cache.clj index 01a9c7f..c7a37e4 100644 --- a/src/main/clojure/clojure/core/cache.clj +++ b/src/main/clojure/clojure/core/cache.clj @@ -590,7 +590,7 @@ (clojure.core.cache/seed (LRUCache. {} (clojure.data.priority-map/priority-map) 0 threshold) base)) (defn ttl-cache-factory - "Returns a TTL cache with the cache and expiration-table initialied to `base` -- + "Returns a TTL cache with the cache and expiration-table initialized to `base` -- each with the same time-to-live. This function also allows an optional `:ttl` argument that defines the default From aab34676929c0d08eeb28e66d1233333c1a78aec Mon Sep 17 00:00:00 2001 From: gigasquid Date: Fri, 25 Mar 2016 13:36:08 -0400 Subject: [PATCH 027/145] avoid uses = to check for contained key to avoid unpredictable Java object comparison. If used with :not-found, make sure the not found key is used first to short-circuit Signed-off-by: fogus --- src/main/clojure/clojure/core/cache.clj | 39 +++++++++---------- src/test/clojure/clojure/core/cache/tests.clj | 8 ++++ 2 files changed, 26 insertions(+), 21 deletions(-) diff --git a/src/main/clojure/clojure/core/cache.clj b/src/main/clojure/clojure/core/cache.clj index c7a37e4..4e57bd3 100644 --- a/src/main/clojure/clojure/core/cache.clj +++ b/src/main/clojure/clojure/core/cache.clj @@ -123,7 +123,7 @@ (f (get cache item))) (lookup [_ item not-found] (let [ret (get cache item not-found)] - (if (= ret not-found) + (if (= not-found ret) not-found (f ret)))) (has? [_ item] @@ -176,12 +176,11 @@ (concat qq [item]) limit))) (evict [this key] - (let [v (get cache key ::miss)] - (if (= v ::miss) - this - (FIFOCache. (dissoc cache key) - (prune-queue q key) - limit)))) + (if (contains? cache key) + (FIFOCache. (dissoc cache key) + (prune-queue q key) + limit) + this)) (seed [_ base] (let [{dropping :dropping q :queue} (describe-layout base limit)] @@ -229,13 +228,12 @@ tick+ limit)))) (evict [this key] - (let [v (get cache key ::miss)] - (if (= v ::miss) - this - (LRUCache. (dissoc cache key) - (dissoc lru key) - (inc tick) - limit)))) + (if (contains? cache key) + (LRUCache. (dissoc cache key) + (dissoc lru key) + (inc tick) + limit) + this)) (seed [_ base] (LRUCache. base (build-leastness-queue base limit 0) @@ -256,7 +254,7 @@ CacheProtocol (lookup [this item] (let [ret (lookup this item ::nope)] - (when-not (= ret ::nope) ret))) + (when-not (= ::nope ret) ret))) (lookup [this item not-found] (if (has? this item) (get cache item) @@ -309,12 +307,11 @@ (assoc lu item 0) limit))) (evict [this key] - (let [v (get cache key ::miss)] - (if (= v ::miss) - this - (LUCache. (dissoc cache key) - (dissoc lu key) - limit)))) + (if (contains? this key) + (LUCache. (dissoc cache key) + (dissoc lu key) + limit) + this)) (seed [_ base] (LUCache. base (build-leastness-queue base limit 0) diff --git a/src/test/clojure/clojure/core/cache/tests.clj b/src/test/clojure/clojure/core/cache/tests.clj index 40dcfaa..c5428b9 100644 --- a/src/test/clojure/clojure/core/cache/tests.clj +++ b/src/test/clojure/clojure/core/cache/tests.clj @@ -465,3 +465,11 @@ N non-resident HIR block (= (fifo-cache-factory {:a 1 :c 3} :threshold 3) (conj starts-with-a [:c 3]) (conj starts-with-a {:c 3}))))) + +(deftest evict-with-object-exception + (let [thing (proxy [Object] [] + (equals [obj] (throw (new Exception "Boom!"))))] + (are [x y] (= x y) + {:b 2} (-> (lru-cache-factory {:a thing, :b 2}) (evict :a) (.cache)) + {:b 2} (-> (lu-cache-factory {:a thing, :b 2}) (evict :a) (.cache)) + {:b 2} (-> (fifo-cache-factory {:a thing, :b 2}) (evict :a) (.cache))))) From f4bc19e71d1ad637006fc5e4eb6f5e7ebf20caf5 Mon Sep 17 00:00:00 2001 From: fogus Date: Fri, 25 Mar 2016 15:24:52 -0400 Subject: [PATCH 028/145] Updating to latest version of pri-map. --- pom.xml | 2 +- project.clj | 8 +++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index e18cfa4..c569bf2 100644 --- a/pom.xml +++ b/pom.xml @@ -39,7 +39,7 @@ org.clojure data.priority-map - 0.0.4 + 0.0.7 diff --git a/project.clj b/project.clj index 5d5191d..3d25514 100644 --- a/project.clj +++ b/project.clj @@ -1,13 +1,15 @@ (defproject core.cache "0.6.5-SNAPSHOT" :description "Cache library for Clojure." - :dependencies [[org.clojure/clojure "1.6.0"] - [org.clojure/data.priority-map "0.0.4"]] + :dependencies [[org.clojure/clojure "1.8.0"] + [org.clojure/data.priority-map "0.0.7"]] :profiles {:1.2 {:dependencies [[org.clojure/clojure "1.2.0"]]} :1.2.1 {:dependencies [[org.clojure/clojure "1.2.1"]]} :1.3 {:dependencies [[org.clojure/clojure "1.3.0"]]} :1.4 {:dependencies [[org.clojure/clojure "1.4.0"]]} :1.5 {:dependencies [[org.clojure/clojure "1.5.0"]]} - :1.5.1 {:dependencies [[org.clojure/clojure "1.5.1"]]}} + :1.5.1 {:dependencies [[org.clojure/clojure "1.5.1"]]} + :1.6 {:dependencies [[org.clojure/clojure "1.6.0"]]} + :1.7 {:dependencies [[org.clojure/clojure "1.7.0"]]}} :plugins [[lein-swank "1.4.4"] [lein-marginalia "0.7.1"]] :repositories {"sonatype-oss-public" "https://oss.sonatype.org/content/groups/public/"} From 2b3c780d48113f82700e6fb4b68814dac352aa99 Mon Sep 17 00:00:00 2001 From: puredanger Date: Mon, 28 Mar 2016 09:04:08 -0500 Subject: [PATCH 029/145] update gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index b3bd55c..1729ae5 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ target lib multi-lib .nrepl-port +.idea From fe6f587cedb6b8f3723e7dcda972093be03d35d6 Mon Sep 17 00:00:00 2001 From: puredanger Date: Mon, 28 Mar 2016 09:06:17 -0500 Subject: [PATCH 030/145] CCACHE-41 Implement required superinterface Iterable in defcache --- src/main/clojure/clojure/core/cache.clj | 7 ++++++- src/test/clojure/clojure/core/cache/tests.clj | 4 ++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/main/clojure/clojure/core/cache.clj b/src/main/clojure/clojure/core/cache.clj index 4e57bd3..2151b7a 100644 --- a/src/main/clojure/clojure/core/cache.clj +++ b/src/main/clojure/clojure/core/cache.clj @@ -56,7 +56,8 @@ (defmacro defcache [type-name fields & specifics] - (let [[base-field & _] fields] + (let [[base & _] fields + base-field (with-meta base {:tag 'clojure.lang.IPersistentMap})] `(deftype ~type-name [~@fields] ~@specifics @@ -68,6 +69,10 @@ (lookup this# key#) not-found#)) + java.lang.Iterable + (iterator [_#] + (.iterator ~base-field)) + clojure.lang.IPersistentMap (assoc [this# k# v#] (miss this# k# v#)) diff --git a/src/test/clojure/clojure/core/cache/tests.clj b/src/test/clojure/clojure/core/cache/tests.clj index c5428b9..56869ce 100644 --- a/src/test/clojure/clojure/core/cache/tests.clj +++ b/src/test/clojure/clojure/core/cache/tests.clj @@ -473,3 +473,7 @@ N non-resident HIR block {:b 2} (-> (lru-cache-factory {:a thing, :b 2}) (evict :a) (.cache)) {:b 2} (-> (lu-cache-factory {:a thing, :b 2}) (evict :a) (.cache)) {:b 2} (-> (fifo-cache-factory {:a thing, :b 2}) (evict :a) (.cache))))) + +(deftest test-cache-iterable + (let [c (fifo-cache-factory {:a 1 :b 2} :threshold 10)] + (is (= #{:a :b} (set (iterator-seq (.iterator (keys c)))))))) \ No newline at end of file From ff428ddc8903b24bb40590f3241367273416629d Mon Sep 17 00:00:00 2001 From: "Hudson @ build.clojure.org" Date: Mon, 28 Mar 2016 09:12:44 -0500 Subject: [PATCH 031/145] [maven-release-plugin] prepare release core.cache-0.6.5 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index c569bf2..5d3af0b 100644 --- a/pom.xml +++ b/pom.xml @@ -2,14 +2,14 @@ 4.0.0 core.cache - 0.6.5-SNAPSHOT + 0.6.5 ${artifactId} Cache library for Clojure. scm:git:git://github.com/clojure/core.cache.git scm:git:ssh://git@github.com/clojure/core.cache.git - HEAD + core.cache-0.6.5 https://github.com/clojure/core.cache From 337a6583528c7147207e10370dbea9bd28a97a6c Mon Sep 17 00:00:00 2001 From: "Hudson @ build.clojure.org" Date: Mon, 28 Mar 2016 09:12:44 -0500 Subject: [PATCH 032/145] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 5d3af0b..a4de904 100644 --- a/pom.xml +++ b/pom.xml @@ -2,14 +2,14 @@ 4.0.0 core.cache - 0.6.5 + 0.6.6-SNAPSHOT ${artifactId} Cache library for Clojure. scm:git:git://github.com/clojure/core.cache.git scm:git:ssh://git@github.com/clojure/core.cache.git - core.cache-0.6.5 + HEAD https://github.com/clojure/core.cache From 4f0e3f9280a203ec5ff59bbdab4a13d5aef6cac8 Mon Sep 17 00:00:00 2001 From: puredanger Date: Mon, 28 Mar 2016 09:19:07 -0500 Subject: [PATCH 033/145] update readme with latest version --- README.md | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 21bef60..052b6ad 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ core.cache is based on an old library named Clache that has been thouroughly dep Releases and Dependency Information ======================================== -Latest stable release: 0.6.4 +Latest stable release: 0.6.5 * [All Released Versions](http://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22org.clojure%22%20AND%20a%3A%22core.cache%22) @@ -33,14 +33,14 @@ Latest stable release: 0.6.4 [Leiningen](https://github.com/technomancy/leiningen) dependency information: - [org.clojure/core.cache "0.6.4"] + [org.clojure/core.cache "0.6.5"] [Maven](http://maven.apache.org/) dependency information: org.clojure core.cache - 0.6.4 + 0.6.5 @@ -84,6 +84,11 @@ Developer Information Change Log ==================== +* Release 0.6.5 on 2016.03.28 + * Bump tools.priority-map dependency to 0.0.7 + * [CCACHE-41](http://dev.clojure.org/jira/browse/CCACHE-41) Implement Iterable in defcache + * [CCACHE-44](http://dev.clojure.org/jira/browse/CCACHE-44) Avoid equals comparison on cache miss + * [CCACHE-37](http://dev.clojure.org/jira/browse/CCACHE-37) Fix typo in docstring * Release 0.6.4 on 2014.08.06 * Thanks to Paul Stadig and Nicola Mometto who contributed patches for this release * [CCACHE-34](http://dev.clojure.org/jira/browse/CCACHE-34) bump tools.priority-map dependency to 0.0.4 From a08efaa0e99fa5492419c217405a86fdc6453dd6 Mon Sep 17 00:00:00 2001 From: Alex Miller Date: Sat, 6 Aug 2016 07:41:46 -0500 Subject: [PATCH 034/145] Fixed typo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 052b6ad..8fd7497 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ core.cache is a new Clojure contrib library providing the following features: * Factory functions for each existing cache type -core.cache is based on an old library named Clache that has been thouroughly deprecated. +core.cache is based on an old library named Clache that has been thoroughly deprecated. Releases and Dependency Information From 7d33e22f67d622936c0da0aaac55ade9c4c04a64 Mon Sep 17 00:00:00 2001 From: Alex Miller Date: Tue, 13 Dec 2016 08:41:28 -0600 Subject: [PATCH 035/145] Update parent pom version --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index a4de904..bec7d46 100644 --- a/pom.xml +++ b/pom.xml @@ -24,7 +24,7 @@ org.clojure pom.contrib - 0.1.2 + 0.2.0 From 58795c2b687fc0d5c48f564a3d98fc3e6ad1b5b9 Mon Sep 17 00:00:00 2001 From: Alex Miller Date: Tue, 13 Dec 2016 11:48:42 -0600 Subject: [PATCH 036/145] Fix project name --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index bec7d46..b7febef 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ 4.0.0 core.cache 0.6.6-SNAPSHOT - ${artifactId} + core.cache Cache library for Clojure. From a47d8b17f16dd327dd0a0e0ad16fc177fe0e6e0b Mon Sep 17 00:00:00 2001 From: Alex Miller Date: Tue, 21 Mar 2017 21:53:08 -0500 Subject: [PATCH 037/145] Update parent pom --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index b7febef..dd81c64 100644 --- a/pom.xml +++ b/pom.xml @@ -24,7 +24,7 @@ org.clojure pom.contrib - 0.2.0 + 0.2.2 From 3aeb8010f35a2b0e7184623c0d44239a64156e4b Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Fri, 1 Sep 2017 12:51:23 -0700 Subject: [PATCH 038/145] Fix typo --- docs/LRU.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/LRU.md b/docs/LRU.md index d72af62..1c60f6f 100644 --- a/docs/LRU.md +++ b/docs/LRU.md @@ -64,7 +64,7 @@ There are a few reasons why you might want to use a LRU cache: ### Disadvantages to using an LRU cache - * Tends to perform poorly when elements files are accessed occassionally but consistently while other elements are accessed very frequently for a short duration and never accessed again + * Tends to perform poorly when elements files are accessed occasionally but consistently while other elements are accessed very frequently for a short duration and never accessed again * It requires more historical data to operate * It requires a larger cache to increase efficiency From 63a58ae01cdf5a998090a75d42ae344d54c2d284 Mon Sep 17 00:00:00 2001 From: Alex Miller Date: Fri, 5 Jan 2018 11:24:49 -0600 Subject: [PATCH 039/145] add deps.edn --- .gitignore | 1 + deps.edn | 2 ++ 2 files changed, 3 insertions(+) create mode 100644 deps.edn diff --git a/.gitignore b/.gitignore index 1729ae5..6100cb8 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ lib multi-lib .nrepl-port .idea +.cpcache/ diff --git a/deps.edn b/deps.edn new file mode 100644 index 0000000..3ec880a --- /dev/null +++ b/deps.edn @@ -0,0 +1,2 @@ +{:paths ["src/main/clojure"] + :deps {org.clojure/data.priority-map {:mvn/version "0.0.7"}}} From 05b74d719cada9e0e8410e67aaf9e52dbfd63850 Mon Sep 17 00:00:00 2001 From: Ivan Kryvoruchko Date: Sat, 11 Mar 2017 13:44:17 +0200 Subject: [PATCH 040/145] Ensure TTL cache doesn't contain values removed from the underlying cache Signed-off-by: Sean Corfield --- src/main/clojure/clojure/core/cache.clj | 9 +++++---- src/test/clojure/clojure/core/cache/tests.clj | 6 +++++- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/main/clojure/clojure/core/cache.clj b/src/main/clojure/clojure/core/cache.clj index 2151b7a..12991f0 100644 --- a/src/main/clojure/clojure/core/cache.clj +++ b/src/main/clojure/clojure/core/cache.clj @@ -265,10 +265,11 @@ (get cache item) not-found)) (has? [_ item] - (let [t (get ttl item (- ttl-ms))] - (< (- (System/currentTimeMillis) - t) - ttl-ms))) + (and (let [t (get ttl item (- ttl-ms))] + (< (- (System/currentTimeMillis) + t) + ttl-ms)) + (contains? cache item))) (hit [this item] this) (miss [this item result] (let [now (System/currentTimeMillis) diff --git a/src/test/clojure/clojure/core/cache/tests.clj b/src/test/clojure/clojure/core/cache/tests.clj index 56869ce..d64cdca 100644 --- a/src/test/clojure/clojure/core/cache/tests.clj +++ b/src/test/clojure/clojure/core/cache/tests.clj @@ -223,7 +223,11 @@ {:c 3} (-> C (assoc :a 1) (assoc :b 2) (sleepy 700) (assoc :c 3) .cache)))) (testing "TTL cache does not return a value that has expired." (let [C (ttl-cache-factory {} :ttl 500)] - (is (nil? (-> C (assoc :a 1) (sleepy 700) (lookup :a))))))) + (is (nil? (-> C (assoc :a 1) (sleepy 700) (lookup :a)))))) + (testing "TTL cache does not contain a value that was removed from underlying cache." + (let [underlying-cache (lru-cache-factory {} :threshold 1) + C (ttl-cache-factory underlying-cache :ttl 360000)] + (is (not (-> C (assoc :a 1) (assoc :b 2) (has? :a))))))) (deftest test-lu-cache-ilookup (testing "that the LUCache can lookup via keywords" From 2174fec31f94c15a42e122c0af3b80aabdc4ac64 Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Wed, 28 Feb 2018 20:48:11 -0800 Subject: [PATCH 041/145] CCACHE-46 update project.clj test versions; document fix --- README.md | 12 +++++++----- project.clj | 18 +++++++++++------- 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 8fd7497..3f41fc5 100644 --- a/README.md +++ b/README.md @@ -50,17 +50,17 @@ Example Usage ```clojure (require '[clojure.core.cache :as cache]) - + (def C (cache/fifo-cache-factory {:a 1, :b 2})) - + (if (cache/has? C :c) (cache/hit C :c) (cache/miss C :c 42)) - + ;=> {:a 1, :b 2, :c 42} - + (cache/evict C :b) - + ;=> {:a 1} ``` @@ -84,6 +84,8 @@ Developer Information Change Log ==================== +* Release next in progress + * [CCACHE-46](http://dev.clojure.org/jira/browse/CCACHE-46) Fix TTLCache when wrapped around another cache (Ivan Kryvoruchko) * Release 0.6.5 on 2016.03.28 * Bump tools.priority-map dependency to 0.0.7 * [CCACHE-41](http://dev.clojure.org/jira/browse/CCACHE-41) Implement Iterable in defcache diff --git a/project.clj b/project.clj index 3d25514..69f0fba 100644 --- a/project.clj +++ b/project.clj @@ -1,17 +1,21 @@ -(defproject core.cache "0.6.5-SNAPSHOT" +(defproject core.cache "0.6.6-SNAPSHOT" :description "Cache library for Clojure." - :dependencies [[org.clojure/clojure "1.8.0"] + :dependencies [[org.clojure/clojure "1.9.0"] [org.clojure/data.priority-map "0.0.7"]] - :profiles {:1.2 {:dependencies [[org.clojure/clojure "1.2.0"]]} - :1.2.1 {:dependencies [[org.clojure/clojure "1.2.1"]]} - :1.3 {:dependencies [[org.clojure/clojure "1.3.0"]]} + :profiles {:1.3 {:dependencies [[org.clojure/clojure "1.3.0"]]} :1.4 {:dependencies [[org.clojure/clojure "1.4.0"]]} :1.5 {:dependencies [[org.clojure/clojure "1.5.0"]]} :1.5.1 {:dependencies [[org.clojure/clojure "1.5.1"]]} :1.6 {:dependencies [[org.clojure/clojure "1.6.0"]]} - :1.7 {:dependencies [[org.clojure/clojure "1.7.0"]]}} + :1.7 {:dependencies [[org.clojure/clojure "1.7.0"]]} + :1.8 {:dependencies [[org.clojure/clojure "1.8.0"]]} + :1.9 {:dependencies [[org.clojure/clojure "1.9.0"]]} + :1.10 {:dependencies [[org.clojure/clojure "1.10.0-master-SNAPSHOT"]]}} :plugins [[lein-swank "1.4.4"] [lein-marginalia "0.7.1"]] :repositories {"sonatype-oss-public" "https://oss.sonatype.org/content/groups/public/"} :source-paths ["src/main/clojure"] - :test-paths ["src/test/clojure"]) + :test-paths ["src/test/clojure"] + :aliases {"test-all" ["with-profile" + "1.3:1.4:1.5:1.5.1:1.6:1.7:1.8:1.9:1.10" + "test"]}) From b20ccd6647e81d27f8252b1fe0733f7ae51968bd Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Wed, 28 Feb 2018 21:28:14 -0800 Subject: [PATCH 042/145] CCACHE-39 fix FIFO evict/miss queue handling --- README.md | 1 + src/main/clojure/clojure/core/cache.clj | 16 +++++++--------- src/test/clojure/clojure/core/cache/tests.clj | 11 ++++++++--- 3 files changed, 16 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 3f41fc5..9e20e19 100644 --- a/README.md +++ b/README.md @@ -86,6 +86,7 @@ Change Log * Release next in progress * [CCACHE-46](http://dev.clojure.org/jira/browse/CCACHE-46) Fix TTLCache when wrapped around another cache (Ivan Kryvoruchko) + * [CCACHE-39](http://dev.clojure.org/jira/browse/CCACHE-39) Fix FIFOCache evict/miss queue handling * Release 0.6.5 on 2016.03.28 * Bump tools.priority-map dependency to 0.0.7 * [CCACHE-41](http://dev.clojure.org/jira/browse/CCACHE-41) Implement Iterable in defcache diff --git a/src/main/clojure/clojure/core/cache.clj b/src/main/clojure/clojure/core/cache.clj index 12991f0..44b611c 100644 --- a/src/main/clojure/clojure/core/cache.clj +++ b/src/main/clojure/clojure/core/cache.clj @@ -50,9 +50,9 @@ ([cache item] (through default-wrapper-fn identity cache item)) ([value-fn cache item] (through default-wrapper-fn value-fn cache item)) ([wrap-fn value-fn cache item] - (if (clojure.core.cache/has? cache item) - (clojure.core.cache/hit cache item) - (clojure.core.cache/miss cache item (wrap-fn #(value-fn %) item))))) + (if (clojure.core.cache/has? cache item) + (clojure.core.cache/hit cache item) + (clojure.core.cache/miss cache item (wrap-fn #(value-fn %) item))))) (defmacro defcache [type-name fields & specifics] @@ -160,7 +160,7 @@ m)) (defn- prune-queue [q k] - (remove #{k} q)) + (cons ::free (remove #{k} q))) (defcache FIFOCache [cache q limit] CacheProtocol @@ -304,8 +304,8 @@ (miss [_ item result] (if (>= (count lu) limit) ;; need to evict? (let [min-key (if (contains? lu item) - ::nope - (first (peek lu))) ;; maybe evict case + ::nope + (first (peek lu))) ;; maybe evict case c (-> cache (dissoc min-key) (assoc item result)) l (-> lu (dissoc min-key) (update-in [item] (fnil inc 0)))] (LUCache. c l limit)) @@ -647,7 +647,5 @@ ;; wait 5 seconds - (assoc C :d 138) + (assoc C :d 138)) ;;=> {:d 138} - -) diff --git a/src/test/clojure/clojure/core/cache/tests.clj b/src/test/clojure/clojure/core/cache/tests.clj index d64cdca..6fa6371 100644 --- a/src/test/clojure/clojure/core/cache/tests.clj +++ b/src/test/clojure/clojure/core/cache/tests.clj @@ -53,7 +53,7 @@ (get c :e 0) 0 (get c :b 0) 2 (get c :f 0) nil - + (get-in c [:c :e]) 4 (get-in c '(:c :e)) 4 (get-in c [:c :x]) nil @@ -62,7 +62,7 @@ (get-in c [:h]) nil (get-in c []) c (get-in c nil) c - + (get-in c [:c :e] 0) 4 (get-in c '(:c :e) 0) 4 (get-in c [:c :x] 0) 0 @@ -480,4 +480,9 @@ N non-resident HIR block (deftest test-cache-iterable (let [c (fifo-cache-factory {:a 1 :b 2} :threshold 10)] - (is (= #{:a :b} (set (iterator-seq (.iterator (keys c)))))))) \ No newline at end of file + (is (= #{:a :b} (set (iterator-seq (.iterator (keys c)))))))) + +(deftest test-fifo-miss-does-not-drop-ccache-39 + (let [c (fifo-cache-factory {:a 1 :b 2} :threshold 2)] + (is (= #{:a :c} (set (-> c (evict :b) (miss :c 42) (.q))))) + (is (= #{:c :d} (set (-> c (evict :b) (miss :c 42) (miss :d 43) (.q))))))) From 0f7ef2294c76284949e681e4b620f07c7dbc1f06 Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Wed, 28 Feb 2018 22:08:20 -0800 Subject: [PATCH 043/145] CCACHE-40 rewrite FIFOCache to use a PersistentQueue Manually tested in the REPL with a threshold of 10,000. --- README.md | 1 + src/main/clojure/clojure/core/cache.clj | 22 ++++++++++------------ 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 9e20e19..0faaba0 100644 --- a/README.md +++ b/README.md @@ -86,6 +86,7 @@ Change Log * Release next in progress * [CCACHE-46](http://dev.clojure.org/jira/browse/CCACHE-46) Fix TTLCache when wrapped around another cache (Ivan Kryvoruchko) + * [CCACHE-40](http://dev.clojure.org/jira/browse/CCACHE-40) Fix FIFOCache stack overflow on large threshold (uses PersistentQueue now instead of concat and list) * [CCACHE-39](http://dev.clojure.org/jira/browse/CCACHE-39) Fix FIFOCache evict/miss queue handling * Release 0.6.5 on 2016.03.28 * Bump tools.priority-map dependency to 0.0.7 diff --git a/src/main/clojure/clojure/core/cache.clj b/src/main/clojure/clojure/core/cache.clj index 44b611c..46ae43d 100644 --- a/src/main/clojure/clojure/core/cache.clj +++ b/src/main/clojure/clojure/core/cache.clj @@ -151,16 +151,14 @@ {:dropping dropping :keeping keeping :queue - (concat (repeat (- limit (count keeping)) ::free) - (take limit keeping))})) - -(defn- dissoc-keys [m ks] - (if ks - (recur (dissoc m (first ks)) (next ks)) - m)) + (-> clojure.lang.PersistentQueue/EMPTY + (into (repeat (- limit (count keeping)) ::free)) + (into (take limit keeping)))})) (defn- prune-queue [q k] - (cons ::free (remove #{k} q))) + (reduce (fn [q e] (if (#{k} e) q (conj q e))) + (conj clojure.lang.PersistentQueue/EMPTY ::free) + q)) (defcache FIFOCache [cache q limit] CacheProtocol @@ -173,12 +171,12 @@ (hit [this item] this) (miss [_ item result] - (let [[kache qq] (let [k (first q)] + (let [[kache qq] (let [k (peek q)] (if (>= (count cache) limit) - [(dissoc cache k) (rest q)] - [cache (rest q)]))] + [(dissoc cache k) (pop q)] + [cache (pop q)]))] (FIFOCache. (assoc kache item result) - (concat qq [item]) + (conj qq item) limit))) (evict [this key] (if (contains? cache key) From 20eca6b879870e1bbd042f3fd59cea4515a81acc Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Wed, 28 Feb 2018 22:54:09 -0800 Subject: [PATCH 044/145] CCACHE-43 add through-cache --- README.md | 1 + src/main/clojure/clojure/core/cache.clj | 10 ++++++++++ 2 files changed, 11 insertions(+) diff --git a/README.md b/README.md index 0faaba0..0847be8 100644 --- a/README.md +++ b/README.md @@ -86,6 +86,7 @@ Change Log * Release next in progress * [CCACHE-46](http://dev.clojure.org/jira/browse/CCACHE-46) Fix TTLCache when wrapped around another cache (Ivan Kryvoruchko) + * [CCACHE-43](http://dev.clojure.org/jira/browse/CCACHE-43) Add `through-cache` to provide a version of `through` that plays nice with `swap!` etc. * [CCACHE-40](http://dev.clojure.org/jira/browse/CCACHE-40) Fix FIFOCache stack overflow on large threshold (uses PersistentQueue now instead of concat and list) * [CCACHE-39](http://dev.clojure.org/jira/browse/CCACHE-39) Fix FIFOCache evict/miss queue handling * Release 0.6.5 on 2016.03.28 diff --git a/src/main/clojure/clojure/core/cache.clj b/src/main/clojure/clojure/core/cache.clj index 46ae43d..703aca9 100644 --- a/src/main/clojure/clojure/core/cache.clj +++ b/src/main/clojure/clojure/core/cache.clj @@ -54,6 +54,16 @@ (clojure.core.cache/hit cache item) (clojure.core.cache/miss cache item (wrap-fn #(value-fn %) item))))) +(defn through-cache + "The basic hit/miss logic for the cache system. Like through but always has + the cache argument in the first position for easier use with swap! etc." + ([cache item] (through-cache cache item default-wrapper-fn identity)) + ([cache item value-fn] (through-cache cache item default-wrapper-fn value-fn)) + ([cache item wrap-fn value-fn] + (if (clojure.core.cache/has? cache item) + (clojure.core.cache/hit cache item) + (clojure.core.cache/miss cache item (wrap-fn #(value-fn %) item))))) + (defmacro defcache [type-name fields & specifics] (let [[base & _] fields From c5da6a8f8e02c686e99a83bec7440916df4df467 Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Wed, 28 Feb 2018 23:20:53 -0800 Subject: [PATCH 045/145] CCACHE-20 updated README with atom/swap! examples --- README.md | 42 +++++++++++++++++++++++++++++++++++------- 1 file changed, 35 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 0847be8..7683d09 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ clojure.core.cache ======================================== -core.cache is a new Clojure contrib library providing the following features: +core.cache is a Clojure contrib library providing the following features: * An underlying `CacheProtocol` used as the base abstraction for implementing new synchronous caches @@ -19,6 +19,8 @@ core.cache is a new Clojure contrib library providing the following features: * Factory functions for each existing cache type +* Caches are generally immutable and should be used in conjunction with Clojure's state management, such as `atom`. SoftCache is the exception here, built on top of mutable Java collections, but it can be treated as an immutable cache as well. + core.cache is based on an old library named Clache that has been thoroughly deprecated. @@ -51,17 +53,42 @@ Example Usage ```clojure (require '[clojure.core.cache :as cache]) - (def C (cache/fifo-cache-factory {:a 1, :b 2})) + (def C1 (cache/fifo-cache-factory {:a 1, :b 2})) - (if (cache/has? C :c) - (cache/hit C :c) - (cache/miss C :c 42)) + (if (cache/has? C1 :c) + (cache/hit C1 :c) + (cache/miss C1 :c 42)) ;=> {:a 1, :b 2, :c 42} - (cache/evict C :b) + (cache/get C1 :c) + + ;=> 42 + + ;; a shorthand for the above conditional... + (cache/through-cache C1 :c (constantly 42)) + ;; ...which uses a value to compute the result from the key... + (cache/through-cache C1 my-key (partial jdbc/get-by-id db-spec :storage)) + ;; ...so you could fetch values from a database if they're not in cache... + + (cache/evict C1 :b) ;=> {:a 1} + + ;; since the caches are immutable, you would normally wrap them in an atom + (def C2 (atom (cache/fifo-cache-factory {:a 1, :b 2}))) + + (swap! C2 cache/through-cache :d (constantly 13)) + + ;=> {:a 1, :b 3, :d 13} + + (swap! C2 cache/evict :b) + + ;=> {:a 1, :d} + + (get @C2 :a) + + ;=> 1 ``` Refer to docstrings in the `clojure.core.cache` namespace, or the [autogenerated API documentation](http://clojure.github.com/core.cache/) for additional documentation @@ -86,9 +113,10 @@ Change Log * Release next in progress * [CCACHE-46](http://dev.clojure.org/jira/browse/CCACHE-46) Fix TTLCache when wrapped around another cache (Ivan Kryvoruchko) - * [CCACHE-43](http://dev.clojure.org/jira/browse/CCACHE-43) Add `through-cache` to provide a version of `through` that plays nice with `swap!` etc. + * [CCACHE-43](http://dev.clojure.org/jira/browse/CCACHE-43) Add `through-cache` to provide a version of `through` that plays nice with `swap!` etc * [CCACHE-40](http://dev.clojure.org/jira/browse/CCACHE-40) Fix FIFOCache stack overflow on large threshold (uses PersistentQueue now instead of concat and list) * [CCACHE-39](http://dev.clojure.org/jira/browse/CCACHE-39) Fix FIFOCache evict/miss queue handling + * [CCACHE-20](http://dev.clojure.org/jira/browse/CCACHE-20) Updated README to clarify that caches are immutable and provide examples of use with `atom` etc * Release 0.6.5 on 2016.03.28 * Bump tools.priority-map dependency to 0.0.7 * [CCACHE-41](http://dev.clojure.org/jira/browse/CCACHE-41) Implement Iterable in defcache From e7a55529b973eaa263157131cc20201434a39e0a Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Thu, 1 Mar 2018 01:24:02 -0800 Subject: [PATCH 046/145] Make LIRSCache and SoftCache seed calls use fully-qualified name This matches all the other factory calls (not sure why they all do that but at least it's consistent). --- src/main/clojure/clojure/core/cache.clj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/clojure/clojure/core/cache.clj b/src/main/clojure/clojure/core/cache.clj index 703aca9..51cbc05 100644 --- a/src/main/clojure/clojure/core/cache.clj +++ b/src/main/clojure/clojure/core/cache.clj @@ -630,7 +630,7 @@ {:pre [(number? s-history-limit) (< 0 s-history-limit) (number? q-history-limit) (< 0 q-history-limit) (map? base)]} - (seed (LIRSCache. {} {} {} 0 s-history-limit q-history-limit) base)) + (clojure.core.cache/seed (LIRSCache. {} {} {} 0 s-history-limit q-history-limit) base)) (defn soft-cache-factory "Returns a SoftReference cache. Cached values will be referred to with @@ -641,7 +641,7 @@ ConcurrentHashMap." [base] {:pre [(map? base)]} - (seed (SoftCache. (ConcurrentHashMap.) (ConcurrentHashMap.) (ReferenceQueue.)) + (clojure.core.cache/seed (SoftCache. (ConcurrentHashMap.) (ConcurrentHashMap.) (ReferenceQueue.)) base)) (comment From 8c9fbec7592531372f1e7e6ef32f5ae254fe287e Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Thu, 1 Mar 2018 23:21:10 -0800 Subject: [PATCH 047/145] CCACHE-15 implement TTL with a queue for efficiency Drop support for pre-1.6 Clojure --- README.md | 4 +- docs/Composing.md | 6 +-- docs/TTL.md | 14 +++--- pom.xml | 6 ++- project.clj | 10 ++-- src/main/clojure/clojure/core/cache.clj | 50 ++++++++++++------- src/test/clojure/clojure/core/cache/tests.clj | 35 ++++++------- 7 files changed, 68 insertions(+), 57 deletions(-) diff --git a/README.md b/README.md index 7683d09..4624027 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ core.cache is a Clojure contrib library providing the following features: - First-in-first-out (FIFOCache) - Least-recently-used (LRUCache) - Least-used (LUCache -- sometimes called Least Frequently Used) - - Time-to-live (TTLCache) + - Time-to-live (TTLCacheQ) - Naive cache (BasicCache) - Naive cache backed with soft references (SoftCache) @@ -117,6 +117,8 @@ Change Log * [CCACHE-40](http://dev.clojure.org/jira/browse/CCACHE-40) Fix FIFOCache stack overflow on large threshold (uses PersistentQueue now instead of concat and list) * [CCACHE-39](http://dev.clojure.org/jira/browse/CCACHE-39) Fix FIFOCache evict/miss queue handling * [CCACHE-20](http://dev.clojure.org/jira/browse/CCACHE-20) Updated README to clarify that caches are immutable and provide examples of use with `atom` etc + * [CCACHE-15](http://dev.clojure.org/jira/browse/CCACHE-15) Added queue and generation logic to reduce `miss` cost and make `evict` O(1) (Kevin Downey) + * Drop support for Clojure 1.3/1.4/1.5 * Release 0.6.5 on 2016.03.28 * Bump tools.priority-map dependency to 0.0.7 * [CCACHE-41](http://dev.clojure.org/jira/browse/CCACHE-41) Implement Iterable in defcache diff --git a/docs/Composing.md b/docs/Composing.md index 91975da..ac6cd3c 100644 --- a/docs/Composing.md +++ b/docs/Composing.md @@ -8,14 +8,14 @@ Put in simpler terms, to create a cache instance composed of the seed data `{:a (ttl-cache-factory :ttl 5000))) ;; used right away - + (assoc C :c 42) ;;=> {:b 2, :c 42} - + ;; used after 5 seconds (assoc C :d 138) ;;=> {:d 138} ``` -What the code above does is to simply use a `FIFOCache` instance, seeded with `{:a 1, :b 2}` as the seed for a `TTLCache` instance. As shown, within the TTL window, the cache evicts its elements using a FIFO policy. However, once a TTL window has expired the expired elements are also evicted. +What the code above does is to simply use a `FIFOCache` instance, seeded with `{:a 1, :b 2}` as the seed for a `TTLCacheQ` instance. As shown, within the TTL window, the cache evicts its elements using a FIFO policy. However, once a TTL window has expired the expired elements are also evicted. diff --git a/docs/TTL.md b/docs/TTL.md index a8c7f64..b1981d0 100644 --- a/docs/TTL.md +++ b/docs/TTL.md @@ -8,14 +8,14 @@ The time-to-live cache is one that evicts items that are older than a time-to-li General usage ------------- -To create a core.cache `TTLCache` instance you should *always* use its associated constructor function `ttl-cache-factory` with an optional `:ttl` parameter: +To create a core.cache `TTLCacheQ` instance you should *always* use its associated constructor function `ttl-cache-factory` with an optional `:ttl` parameter: ```clojure - (ns your.lib + (ns your.lib (:require [clojure.core.cache :as cache])) - + (def C (cache/ttl-cache-factory {} :ttl 1000)) - + (-> C (assoc :a 1) (assoc :b 2)) ;=> {:a 1, :b 2} ``` @@ -26,8 +26,8 @@ At this point the cache is fresh and younger than one second (that is, depending ```clojure (def sleepy #(do (Thread/sleep %2) %)) - - (-> C (assoc :a 1) + + (-> C (assoc :a 1) (assoc :b 2) (sleepy 1500) (assoc :c 3)) @@ -55,5 +55,5 @@ There are a few reasons why you might want to use a TTL cache: * It requires more historical data to operate * Cache size does not generally help its efficiency - + As always, you should measure your system's characteristics to determine the best eviction strategy for your purposes. diff --git a/pom.xml b/pom.xml index dd81c64..de15f7c 100644 --- a/pom.xml +++ b/pom.xml @@ -2,7 +2,7 @@ 4.0.0 core.cache - 0.6.6-SNAPSHOT + 0.7.0-SNAPSHOT core.cache Cache library for Clojure. @@ -35,6 +35,10 @@ + + 1.6.0 + + org.clojure diff --git a/project.clj b/project.clj index 69f0fba..5355100 100644 --- a/project.clj +++ b/project.clj @@ -1,12 +1,8 @@ -(defproject core.cache "0.6.6-SNAPSHOT" +(defproject core.cache "0.7.0-SNAPSHOT" :description "Cache library for Clojure." :dependencies [[org.clojure/clojure "1.9.0"] [org.clojure/data.priority-map "0.0.7"]] - :profiles {:1.3 {:dependencies [[org.clojure/clojure "1.3.0"]]} - :1.4 {:dependencies [[org.clojure/clojure "1.4.0"]]} - :1.5 {:dependencies [[org.clojure/clojure "1.5.0"]]} - :1.5.1 {:dependencies [[org.clojure/clojure "1.5.1"]]} - :1.6 {:dependencies [[org.clojure/clojure "1.6.0"]]} + :profiles {:1.6 {:dependencies [[org.clojure/clojure "1.6.0"]]} :1.7 {:dependencies [[org.clojure/clojure "1.7.0"]]} :1.8 {:dependencies [[org.clojure/clojure "1.8.0"]]} :1.9 {:dependencies [[org.clojure/clojure "1.9.0"]]} @@ -17,5 +13,5 @@ :source-paths ["src/main/clojure"] :test-paths ["src/test/clojure"] :aliases {"test-all" ["with-profile" - "1.3:1.4:1.5:1.5.1:1.6:1.7:1.8:1.9:1.10" + "1.6:1.7:1.8:1.9:1.10" "test"]}) diff --git a/src/main/clojure/clojure/core/cache.clj b/src/main/clojure/clojure/core/cache.clj index 51cbc05..5d7f362 100644 --- a/src/main/clojure/clojure/core/cache.clj +++ b/src/main/clojure/clojure/core/cache.clj @@ -257,13 +257,19 @@ (str cache \, \space lru \, \space tick \, \space limit))) -(defn- key-killer - [ttl expiry now] - (let [ks (map key (filter #(> (- now (val %)) expiry) ttl))] - #(apply dissoc % ks))) - - -(defcache TTLCache [cache ttl ttl-ms] +(defn- key-killer-q + [ttl q expiry now] + (let [[ks q'] (reduce (fn [[ks q] [k g t]] + (if (> (- now t) expiry) + (if (= g (first (get ttl k))) + [(conj ks k) (pop q)] + [ks (pop q)]) + (reduced [ks q]))) + [[] q] + q)] + [#(apply dissoc % ks) q'])) + +(defcache TTLCacheQ [cache ttl q gen ttl-ms] CacheProtocol (lookup [this item] (let [ret (lookup this item ::nope)] @@ -273,7 +279,7 @@ (get cache item) not-found)) (has? [_ item] - (and (let [t (get ttl item (- ttl-ms))] + (and (let [[_ t] (get ttl item [0 (- ttl-ms)])] (< (- (System/currentTimeMillis) t) ttl-ms)) @@ -281,19 +287,25 @@ (hit [this item] this) (miss [this item result] (let [now (System/currentTimeMillis) - kill-old (key-killer ttl ttl-ms now)] - (TTLCache. (assoc (kill-old cache) item result) - (assoc (kill-old ttl) item now) - ttl-ms))) + [kill-old q'] (key-killer-q ttl q ttl-ms now)] + (TTLCacheQ. (assoc (kill-old cache) item result) + (assoc (kill-old ttl) item [gen now]) + (conj q' [item gen now]) + (unchecked-inc gen) + ttl-ms))) (seed [_ base] (let [now (System/currentTimeMillis)] - (TTLCache. base - (into {} (for [x base] [(key x) now])) - ttl-ms))) + (TTLCacheQ. base + (into {} (for [x base] [(key x) [gen now]])) + q + gen + ttl-ms))) (evict [_ key] - (TTLCache. (dissoc cache key) - (dissoc ttl key) - ttl-ms)) + (TTLCacheQ. (dissoc cache key) + (dissoc ttl key) + q + gen + ttl-ms)) Object (toString [_] (str cache \, \space ttl \, \space ttl-ms))) @@ -609,7 +621,7 @@ [base & {ttl :ttl :or {ttl 2000}}] {:pre [(number? ttl) (<= 0 ttl) (map? base)]} - (clojure.core.cache/seed (TTLCache. {} {} ttl) base)) + (clojure.core.cache/seed (TTLCacheQ. {} {} clojure.lang.PersistentQueue/EMPTY 0 ttl) base)) (defn lu-cache-factory "Returns an LU cache with the cache and usage-table initialied to `base`. diff --git a/src/test/clojure/clojure/core/cache/tests.clj b/src/test/clojure/clojure/core/cache/tests.clj index 6fa6371..fdaf353 100644 --- a/src/test/clojure/clojure/core/cache/tests.clj +++ b/src/test/clojure/clojure/core/cache/tests.clj @@ -11,7 +11,7 @@ clojure.core.cache.tests (:use [clojure.core.cache] :reload-all) (:use [clojure.test]) - (:import (clojure.core.cache BasicCache FIFOCache LRUCache TTLCache LUCache + (:import (clojure.core.cache BasicCache FIFOCache LRUCache TTLCacheQ LUCache LIRSCache) (java.lang.ref ReferenceQueue SoftReference) (java.util.concurrent ConcurrentHashMap))) @@ -198,22 +198,19 @@ (defn sleepy [e t] (Thread/sleep t) e) (deftest test-ttl-cache-ilookup - (let [five-secs (+ 5000 (System/currentTimeMillis)) - big-time (into {} (for [[k _] big-map] [k five-secs])) - small-time (into {} (for [[k _] small-map] [k five-secs]))] - (testing "that the TTLCache can lookup via keywords" - (do-ilookup-tests (TTLCache. small-map small-time 2000))) - (testing "that the TTLCache can lookup via keywords" - (do-dot-lookup-tests (TTLCache. small-map small-time 2000))) - (testing "assoc and dissoc for TTLCache" - (do-assoc (TTLCache. {} {} 2000)) - (do-dissoc (TTLCache. {:a 1 :b 2} {:a five-secs :b five-secs} 2000))) - (testing "that get and cascading gets work for TTLCache" - (do-getting (TTLCache. big-map big-time 2000))) - (testing "that finding works for TTLCache" - (do-finding (TTLCache. small-map small-time 2000))) - (testing "that contains? works for TTLCache" - (do-contains (TTLCache. small-map small-time 2000))))) + (testing "that the TTLCacheQ can lookup via keywords" + (do-ilookup-tests (ttl-cache-factory small-map))) + (testing "that the TTLCacheQ can lookup via keywords" + (do-dot-lookup-tests (ttl-cache-factory small-map))) + (testing "assoc and dissoc for TTLCacheQ" + (do-assoc (ttl-cache-factory {})) + (do-dissoc (ttl-cache-factory {:a 1 :b 2}))) + (testing "that get and cascading gets work for TTLCacheQ" + (do-getting (ttl-cache-factory big-map))) + (testing "that finding works for TTLCacheQ" + (do-finding (ttl-cache-factory small-map))) + (testing "that contains? works for TTLCacheQ" + (do-contains (ttl-cache-factory small-map)))) (deftest test-ttl-cache (testing "TTL-ness with empty cache" @@ -429,13 +426,13 @@ N non-resident HIR block (.put :foo ref)) rcache (doto (ConcurrentHashMap.) (.put ref :foo)) - soft-cache (clear-soft-cache! cache rcache rq)] + _ (clear-soft-cache! cache rcache rq)] (is (contains? cache :foo) (str cache)) (is (contains? rcache ref) (str rcache)) (.clear ref) (.enqueue ref) (is (not (.get ref))) - (let [soft-cache (clear-soft-cache! cache rcache rq)] + (let [_ (clear-soft-cache! cache rcache rq)] (is (not (contains? cache :foo))) (is (not (contains? rcache ref)))))) From 8b1198048581b1d8adf6158683c74476284b1603 Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Thu, 1 Mar 2018 23:28:40 -0800 Subject: [PATCH 048/145] Prep for 0.7.0 --- README.md | 8 ++++---- project.clj | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 4624027..4bc2ac9 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ core.cache is based on an old library named Clache that has been thoroughly depr Releases and Dependency Information ======================================== -Latest stable release: 0.6.5 +Latest stable release: 0.7.0 * [All Released Versions](http://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22org.clojure%22%20AND%20a%3A%22core.cache%22) @@ -35,14 +35,14 @@ Latest stable release: 0.6.5 [Leiningen](https://github.com/technomancy/leiningen) dependency information: - [org.clojure/core.cache "0.6.5"] + [org.clojure/core.cache "0.7.0"] [Maven](http://maven.apache.org/) dependency information: org.clojure core.cache - 0.6.5 + 0.7.0 @@ -111,7 +111,7 @@ Developer Information Change Log ==================== -* Release next in progress +* Release 0.7.0 on 2018.03.01 * [CCACHE-46](http://dev.clojure.org/jira/browse/CCACHE-46) Fix TTLCache when wrapped around another cache (Ivan Kryvoruchko) * [CCACHE-43](http://dev.clojure.org/jira/browse/CCACHE-43) Add `through-cache` to provide a version of `through` that plays nice with `swap!` etc * [CCACHE-40](http://dev.clojure.org/jira/browse/CCACHE-40) Fix FIFOCache stack overflow on large threshold (uses PersistentQueue now instead of concat and list) diff --git a/project.clj b/project.clj index 5355100..c9eb7b8 100644 --- a/project.clj +++ b/project.clj @@ -1,4 +1,4 @@ -(defproject core.cache "0.7.0-SNAPSHOT" +(defproject core.cache "0.7.0" :description "Cache library for Clojure." :dependencies [[org.clojure/clojure "1.9.0"] [org.clojure/data.priority-map "0.0.7"]] From 2a68392a973b8764cc3d4826b6703690c2e46d1f Mon Sep 17 00:00:00 2001 From: "Hudson @ build.clojure.org" Date: Fri, 2 Mar 2018 01:32:56 -0600 Subject: [PATCH 049/145] [maven-release-plugin] prepare release core.cache-0.7.0 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index de15f7c..a6043d5 100644 --- a/pom.xml +++ b/pom.xml @@ -2,14 +2,14 @@ 4.0.0 core.cache - 0.7.0-SNAPSHOT + 0.7.0 core.cache Cache library for Clojure. scm:git:git://github.com/clojure/core.cache.git scm:git:ssh://git@github.com/clojure/core.cache.git - HEAD + core.cache-0.7.0 https://github.com/clojure/core.cache From e45b9f42b6a087965de0b282eb40b019a6f2e17e Mon Sep 17 00:00:00 2001 From: "Hudson @ build.clojure.org" Date: Fri, 2 Mar 2018 01:32:56 -0600 Subject: [PATCH 050/145] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index a6043d5..e5aa21b 100644 --- a/pom.xml +++ b/pom.xml @@ -2,14 +2,14 @@ 4.0.0 core.cache - 0.7.0 + 0.7.1-SNAPSHOT core.cache Cache library for Clojure. scm:git:git://github.com/clojure/core.cache.git scm:git:ssh://git@github.com/clojure/core.cache.git - core.cache-0.7.0 + HEAD https://github.com/clojure/core.cache From 1d9c40a206e573e15c7e8a9e7981a2de0f8485d9 Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Fri, 2 Mar 2018 09:22:20 -0800 Subject: [PATCH 051/145] Advise of TTL cache seed bug --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 4bc2ac9..59c3918 100644 --- a/README.md +++ b/README.md @@ -111,6 +111,8 @@ Developer Information Change Log ==================== +* Release 0.7.1 in progress + * To fix bug in TTL cache with seed * Release 0.7.0 on 2018.03.01 * [CCACHE-46](http://dev.clojure.org/jira/browse/CCACHE-46) Fix TTLCache when wrapped around another cache (Ivan Kryvoruchko) * [CCACHE-43](http://dev.clojure.org/jira/browse/CCACHE-43) Add `through-cache` to provide a version of `through` that plays nice with `swap!` etc From 9ac1a304c8b1839a3b3edafc7ac3c63641ad3a18 Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Fri, 2 Mar 2018 10:48:46 -0800 Subject: [PATCH 052/145] CCACHE-49 Fix TTLCacheQ seed function Also expands tests for TTLCacheQ to verify internals are consistent --- README.md | 12 ++-- src/main/clojure/clojure/core/cache.clj | 6 +- src/test/clojure/clojure/core/cache/tests.clj | 58 ++++++++++++++----- 3 files changed, 52 insertions(+), 24 deletions(-) diff --git a/README.md b/README.md index 59c3918..7ffd1fb 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ core.cache is based on an old library named Clache that has been thoroughly depr Releases and Dependency Information ======================================== -Latest stable release: 0.7.0 +Latest stable release: 0.7.1 * [All Released Versions](http://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22org.clojure%22%20AND%20a%3A%22core.cache%22) @@ -35,14 +35,14 @@ Latest stable release: 0.7.0 [Leiningen](https://github.com/technomancy/leiningen) dependency information: - [org.clojure/core.cache "0.7.0"] + [org.clojure/core.cache "0.7.1"] [Maven](http://maven.apache.org/) dependency information: org.clojure core.cache - 0.7.0 + 0.7.1 @@ -111,15 +111,15 @@ Developer Information Change Log ==================== -* Release 0.7.1 in progress - * To fix bug in TTL cache with seed +* Release 0.7.1 on 2018.03.02 + * [CCACHE-49](http://dev.clojure.org/jira/browse/CCACHE-49) Fix TTLCacheQ `seed` function and expand tests on TTLCacheQ * Release 0.7.0 on 2018.03.01 * [CCACHE-46](http://dev.clojure.org/jira/browse/CCACHE-46) Fix TTLCache when wrapped around another cache (Ivan Kryvoruchko) * [CCACHE-43](http://dev.clojure.org/jira/browse/CCACHE-43) Add `through-cache` to provide a version of `through` that plays nice with `swap!` etc * [CCACHE-40](http://dev.clojure.org/jira/browse/CCACHE-40) Fix FIFOCache stack overflow on large threshold (uses PersistentQueue now instead of concat and list) * [CCACHE-39](http://dev.clojure.org/jira/browse/CCACHE-39) Fix FIFOCache evict/miss queue handling * [CCACHE-20](http://dev.clojure.org/jira/browse/CCACHE-20) Updated README to clarify that caches are immutable and provide examples of use with `atom` etc - * [CCACHE-15](http://dev.clojure.org/jira/browse/CCACHE-15) Added queue and generation logic to reduce `miss` cost and make `evict` O(1) (Kevin Downey) + * [CCACHE-15](http://dev.clojure.org/jira/browse/CCACHE-15) Added queue and generation logic to reduce `miss` cost and make `evict` O(1); rename TTLCache -> TTLCacheQ (Kevin Downey) * Drop support for Clojure 1.3/1.4/1.5 * Release 0.6.5 on 2016.03.28 * Bump tools.priority-map dependency to 0.0.7 diff --git a/src/main/clojure/clojure/core/cache.clj b/src/main/clojure/clojure/core/cache.clj index 5d7f362..fb3e7c2 100644 --- a/src/main/clojure/clojure/core/cache.clj +++ b/src/main/clojure/clojure/core/cache.clj @@ -296,9 +296,11 @@ (seed [_ base] (let [now (System/currentTimeMillis)] (TTLCacheQ. base + ;; we seed the cache all at gen, but subsequent entries + ;; will get gen+1, gen+2 etc (into {} (for [x base] [(key x) [gen now]])) - q - gen + (into q (for [x base] [(key x) gen now])) + (unchecked-inc gen) ttl-ms))) (evict [_ key] (TTLCacheQ. (dissoc cache key) diff --git a/src/test/clojure/clojure/core/cache/tests.clj b/src/test/clojure/clojure/core/cache/tests.clj index fdaf353..62d1f31 100644 --- a/src/test/clojure/clojure/core/cache/tests.clj +++ b/src/test/clojure/clojure/core/cache/tests.clj @@ -198,26 +198,52 @@ (defn sleepy [e t] (Thread/sleep t) e) (deftest test-ttl-cache-ilookup - (testing "that the TTLCacheQ can lookup via keywords" - (do-ilookup-tests (ttl-cache-factory small-map))) - (testing "that the TTLCacheQ can lookup via keywords" - (do-dot-lookup-tests (ttl-cache-factory small-map))) - (testing "assoc and dissoc for TTLCacheQ" - (do-assoc (ttl-cache-factory {})) - (do-dissoc (ttl-cache-factory {:a 1 :b 2}))) - (testing "that get and cascading gets work for TTLCacheQ" - (do-getting (ttl-cache-factory big-map))) - (testing "that finding works for TTLCacheQ" - (do-finding (ttl-cache-factory small-map))) - (testing "that contains? works for TTLCacheQ" - (do-contains (ttl-cache-factory small-map)))) + (let [five-secs (+ 5000 (System/currentTimeMillis)) + big-time (into {} (for [[k _] big-map] [k [0 five-secs]])) + big-q (into clojure.lang.PersistentQueue/EMPTY + (for [[k _] big-map] [k 0 five-secs])) + small-time (into {} (for [[k _] small-map] [k [0 five-secs]])) + small-q (into clojure.lang.PersistentQueue/EMPTY + (for [[k _] small-map] [k 0 five-secs]))] + (testing "that the TTLCacheQ can lookup via keywords" + (do-ilookup-tests (TTLCacheQ. small-map small-time small-q 1 2000))) + (testing "that the TTLCacheQ can lookup via keywords" + (do-dot-lookup-tests (TTLCacheQ. small-map small-time small-q 1 2000))) + (testing "assoc and dissocQ for TTLCacheQ" + (do-assoc (TTLCacheQ. {} {} clojure.lang.PersistentQueue/EMPTY 1 2000)) + (do-dissoc (TTLCacheQ. {:a 1 :b 2} + {:a [0 five-secs] :b [0 five-secs]} + (into clojure.lang.PersistentQueue/EMPTY + [[:a 0 five-secs] [:b 0 five-secs]]) + 1 + 2000))) + (testing "that get and cascading gets work for TTLCacheQ" + (do-getting (TTLCacheQ. big-map big-time big-q 1 2000))) + (testing "that finding works for TTLCacheQ" + (do-finding (TTLCacheQ. small-map small-time small-q 1 2000))) + (testing "that contains? works for TTLCacheQ" + (do-contains (TTLCacheQ. small-map small-time small-q 1 2000))))) + +(defn- ttl-q-check + [start nap [k g t]] + [k g (<= start (+ start nap) t (+ start nap 10))]) (deftest test-ttl-cache (testing "TTL-ness with empty cache" - (let [C (ttl-cache-factory {} :ttl 500)] + (let [start (System/currentTimeMillis) + C (ttl-cache-factory {} :ttl 500) + C' (-> C (assoc :a 1) (assoc :b 2))] (are [x y] (= x y) - {:a 1, :b 2} (-> C (assoc :a 1) (assoc :b 2) .cache) - {:c 3} (-> C (assoc :a 1) (assoc :b 2) (sleepy 700) (assoc :c 3) .cache)))) + [[:a 1 true], [:b 2 true]] (map (partial ttl-q-check start 0) (.q C')) + {:a 1, :b 2} (.cache C') + 3 (.gen C'))) + (let [start (System/currentTimeMillis) + C (ttl-cache-factory {} :ttl 500) + C' (-> C (assoc :a 1) (assoc :b 2) (sleepy 700) (assoc :c 3))] + (are [x y] (= x y) + [[:c 3 true]] (map (partial ttl-q-check start 700) (.q C')) + {:c 3} (.cache C') + 4 (.gen C')))) (testing "TTL cache does not return a value that has expired." (let [C (ttl-cache-factory {} :ttl 500)] (is (nil? (-> C (assoc :a 1) (sleepy 700) (lookup :a)))))) From e2e5ef7cbd75717255dd62e810a1ee61311be868 Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Fri, 2 Mar 2018 10:49:26 -0800 Subject: [PATCH 053/145] Bump project.clj version for consistency --- project.clj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project.clj b/project.clj index c9eb7b8..fa6f41e 100644 --- a/project.clj +++ b/project.clj @@ -1,4 +1,4 @@ -(defproject core.cache "0.7.0" +(defproject core.cache "0.7.1" :description "Cache library for Clojure." :dependencies [[org.clojure/clojure "1.9.0"] [org.clojure/data.priority-map "0.0.7"]] From 0f84219155c22b7fec42f75ddca00b9d52914329 Mon Sep 17 00:00:00 2001 From: "Hudson @ build.clojure.org" Date: Fri, 2 Mar 2018 12:58:49 -0600 Subject: [PATCH 054/145] [maven-release-plugin] prepare release core.cache-0.7.1 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index e5aa21b..3bdbf57 100644 --- a/pom.xml +++ b/pom.xml @@ -2,14 +2,14 @@ 4.0.0 core.cache - 0.7.1-SNAPSHOT + 0.7.1 core.cache Cache library for Clojure. scm:git:git://github.com/clojure/core.cache.git scm:git:ssh://git@github.com/clojure/core.cache.git - HEAD + core.cache-0.7.1 https://github.com/clojure/core.cache From 76a551d6a6e8d0a673d7cc781aea39bc13c298ef Mon Sep 17 00:00:00 2001 From: "Hudson @ build.clojure.org" Date: Fri, 2 Mar 2018 12:58:49 -0600 Subject: [PATCH 055/145] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 3bdbf57..5ce4b9f 100644 --- a/pom.xml +++ b/pom.xml @@ -2,14 +2,14 @@ 4.0.0 core.cache - 0.7.1 + 0.7.2-SNAPSHOT core.cache Cache library for Clojure. scm:git:git://github.com/clojure/core.cache.git scm:git:ssh://git@github.com/clojure/core.cache.git - core.cache-0.7.1 + HEAD https://github.com/clojure/core.cache From 13e041ed29327e2e1d1538c9cc24b2ea4095ec19 Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Fri, 2 Mar 2018 11:22:38 -0800 Subject: [PATCH 056/145] Make TTLCacheQ less time-sensitive CI test matrix was a bit flappy with only a 10ms window -- expanded to 100ms. --- project.clj | 2 +- src/test/clojure/clojure/core/cache/tests.clj | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/project.clj b/project.clj index fa6f41e..760f750 100644 --- a/project.clj +++ b/project.clj @@ -1,4 +1,4 @@ -(defproject core.cache "0.7.1" +(defproject core.cache "0.7.2-SNAPSHOT" :description "Cache library for Clojure." :dependencies [[org.clojure/clojure "1.9.0"] [org.clojure/data.priority-map "0.0.7"]] diff --git a/src/test/clojure/clojure/core/cache/tests.clj b/src/test/clojure/clojure/core/cache/tests.clj index 62d1f31..3bd67ea 100644 --- a/src/test/clojure/clojure/core/cache/tests.clj +++ b/src/test/clojure/clojure/core/cache/tests.clj @@ -226,7 +226,7 @@ (defn- ttl-q-check [start nap [k g t]] - [k g (<= start (+ start nap) t (+ start nap 10))]) + [k g (<= start (+ start nap) t (+ start nap 100))]) (deftest test-ttl-cache (testing "TTL-ness with empty cache" From 1f76bdf7321bce7c5d8c1424943afeccff0fb6d5 Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Sat, 3 Mar 2018 14:57:03 -0800 Subject: [PATCH 057/145] Use cli/test-runner instead of lein Adds :test, :runner, and version aliases to deps.edn. Add run-tests.sh multi-version test script. Move and rename tests to reflect more standard -test namespace approach. --- .gitignore | 1 + deps.edn | 20 ++++++++++++++++++- project.clj | 17 ---------------- run-tests.sh | 14 +++++++++++++ .../core/{cache/tests.clj => cache_test.clj} | 4 +++- 5 files changed, 37 insertions(+), 19 deletions(-) delete mode 100644 project.clj create mode 100755 run-tests.sh rename src/test/clojure/clojure/core/{cache/tests.clj => cache_test.clj} (99%) diff --git a/.gitignore b/.gitignore index 6100cb8..4bae240 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ multi-lib .nrepl-port .idea .cpcache/ +/build.boot diff --git a/deps.edn b/deps.edn index 3ec880a..568bf36 100644 --- a/deps.edn +++ b/deps.edn @@ -1,2 +1,20 @@ +;; You can run clojure.core.cache tests with: clj -A:test:runner +;; You can also specify an alias to select which version of Clojure to test +;; against: :1.6 :1.7 :1.8 :1.9 :master + {:paths ["src/main/clojure"] - :deps {org.clojure/data.priority-map {:mvn/version "0.0.7"}}} + :deps {org.clojure/data.priority-map {:mvn/version "0.0.7"}} + :aliases {:test + {:extra-paths ["src/test/clojure"] + :extra-deps {org.clojure/test.check {:mvn/version "0.9.0"}}} + :1.6 {:override-deps {org.clojure/clojure {:mvn/version "1.6.0"}}} + :1.7 {:override-deps {org.clojure/clojure {:mvn/version "1.7.0"}}} + :1.8 {:override-deps {org.clojure/clojure {:mvn/version "1.8.0"}}} + :1.9 {:override-deps {org.clojure/clojure {:mvn/version "1.9.0"}}} + :master {:override-deps {org.clojure/clojure {:mvn/version "1.10.0-master-SNAPSHOT"}}} + :runner + {:extra-deps {com.cognitect/test-runner + {:git/url "https://github.com/cognitect-labs/test-runner" + :sha "5f2b5c2efb444df76fb5252102b33f542ebf7f58"}} + :main-opts ["-m" "cognitect.test-runner" + "-d" "src/test/clojure"]}}} diff --git a/project.clj b/project.clj deleted file mode 100644 index 760f750..0000000 --- a/project.clj +++ /dev/null @@ -1,17 +0,0 @@ -(defproject core.cache "0.7.2-SNAPSHOT" - :description "Cache library for Clojure." - :dependencies [[org.clojure/clojure "1.9.0"] - [org.clojure/data.priority-map "0.0.7"]] - :profiles {:1.6 {:dependencies [[org.clojure/clojure "1.6.0"]]} - :1.7 {:dependencies [[org.clojure/clojure "1.7.0"]]} - :1.8 {:dependencies [[org.clojure/clojure "1.8.0"]]} - :1.9 {:dependencies [[org.clojure/clojure "1.9.0"]]} - :1.10 {:dependencies [[org.clojure/clojure "1.10.0-master-SNAPSHOT"]]}} - :plugins [[lein-swank "1.4.4"] - [lein-marginalia "0.7.1"]] - :repositories {"sonatype-oss-public" "https://oss.sonatype.org/content/groups/public/"} - :source-paths ["src/main/clojure"] - :test-paths ["src/test/clojure"] - :aliases {"test-all" ["with-profile" - "1.6:1.7:1.8:1.9:1.10" - "test"]}) diff --git a/run-tests.sh b/run-tests.sh new file mode 100755 index 0000000..97d1c0e --- /dev/null +++ b/run-tests.sh @@ -0,0 +1,14 @@ +#!/bin/sh +# +# We don't auto-test against Clojure 1.6 because the Cognitect test runner +# requires at least 1.7, so we run those tests manually: + +time clj -A:1.6:test -e \ +"(require 'clojure.core.cache-test)\ + (clojure.test/run-tests 'clojure.core.cache-test)" + +versions="1.7 1.8 1.9 master" +for v in $versions +do + time clj -A:test:runner:$v +done diff --git a/src/test/clojure/clojure/core/cache/tests.clj b/src/test/clojure/clojure/core/cache_test.clj similarity index 99% rename from src/test/clojure/clojure/core/cache/tests.clj rename to src/test/clojure/clojure/core/cache_test.clj index 3bd67ea..377c7d9 100644 --- a/src/test/clojure/clojure/core/cache/tests.clj +++ b/src/test/clojure/clojure/core/cache_test.clj @@ -8,7 +8,7 @@ (ns ^{:doc "A caching library for Clojure." :author "Fogus"} - clojure.core.cache.tests + clojure.core.cache-test (:use [clojure.core.cache] :reload-all) (:use [clojure.test]) (:import (clojure.core.cache BasicCache FIFOCache LRUCache TTLCacheQ LUCache @@ -16,6 +16,8 @@ (java.lang.ref ReferenceQueue SoftReference) (java.util.concurrent ConcurrentHashMap))) +(println "\nTesting with Clojure" (clojure-version)) + (deftest test-basic-cache-lookup (testing "that the BasicCache can lookup as expected" (is (= :robot (lookup (miss (BasicCache. {}) '(servo) :robot) '(servo)))))) From 291472b6791d77b936725342bd54b179925505d7 Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Sat, 3 Mar 2018 21:31:26 -0800 Subject: [PATCH 058/145] Bump to latest test-runner and simplify run-tests.sh --- deps.edn | 2 +- run-tests.sh | 9 +-------- 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/deps.edn b/deps.edn index 568bf36..d7aeb2a 100644 --- a/deps.edn +++ b/deps.edn @@ -15,6 +15,6 @@ :runner {:extra-deps {com.cognitect/test-runner {:git/url "https://github.com/cognitect-labs/test-runner" - :sha "5f2b5c2efb444df76fb5252102b33f542ebf7f58"}} + :sha "76568540e7f40268ad2b646110f237a60295fa3c"}} :main-opts ["-m" "cognitect.test-runner" "-d" "src/test/clojure"]}}} diff --git a/run-tests.sh b/run-tests.sh index 97d1c0e..ac187bc 100755 --- a/run-tests.sh +++ b/run-tests.sh @@ -1,13 +1,6 @@ #!/bin/sh -# -# We don't auto-test against Clojure 1.6 because the Cognitect test runner -# requires at least 1.7, so we run those tests manually: -time clj -A:1.6:test -e \ -"(require 'clojure.core.cache-test)\ - (clojure.test/run-tests 'clojure.core.cache-test)" - -versions="1.7 1.8 1.9 master" +versions="1.6 1.7 1.8 1.9 master" for v in $versions do time clj -A:test:runner:$v From f3dd1f2ee34e08a95bff5d4172a20fd87e3df3f1 Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Wed, 28 Mar 2018 09:54:39 -0700 Subject: [PATCH 059/145] Correct README example code --- README.md | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 7ffd1fb..7abb536 100644 --- a/README.md +++ b/README.md @@ -55,18 +55,22 @@ Example Usage (def C1 (cache/fifo-cache-factory {:a 1, :b 2})) - (if (cache/has? C1 :c) - (cache/hit C1 :c) - (cache/miss C1 :c 42)) + (def C1' (if (cache/has? C1 :c) + (cache/hit C1 :c) + (cache/miss C1 :c 42))) ;=> {:a 1, :b 2, :c 42} - (cache/get C1 :c) + (cache/lookup C1' :c) + + ;=> 42 + + (get C1' :c) ; cache/lookup is implemented as get ;=> 42 ;; a shorthand for the above conditional... - (cache/through-cache C1 :c (constantly 42)) + (def C1' (cache/through-cache C1 :c (constantly 42))) ;; ...which uses a value to compute the result from the key... (cache/through-cache C1 my-key (partial jdbc/get-by-id db-spec :storage)) ;; ...so you could fetch values from a database if they're not in cache... From 8fd37130ccc574ce3c9e1de460808e7d628c1d81 Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Mon, 29 Oct 2018 17:57:17 -0700 Subject: [PATCH 060/145] Add Pull Request Template --- .github/PULL_REQUEST_TEMPLATE | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 .github/PULL_REQUEST_TEMPLATE diff --git a/.github/PULL_REQUEST_TEMPLATE b/.github/PULL_REQUEST_TEMPLATE new file mode 100644 index 0000000..0a5c486 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE @@ -0,0 +1,14 @@ +Hi! Thanks for your interest in contributing to this project. + +Clojure contrib projects do not use GitHub issues or pull requests, and +require a signed Contributor Agreement. If you would like to contribute, +please read more about the CA and sign that first (this can be done online). + +Then go to this project's issue tracker in JIRA to create tickets, update +tickets, or submit patches. For help in creating tickets and patches, +please see: + +- Signing the CA: https://dev.clojure.org/display/community/Contributing+FAQ +- Creating Tickets: https://dev.clojure.org/display/community/Creating+Tickets +- Developing Patches: https://dev.clojure.org/display/community/Developing+Patches +- Contributing FAQ: https://dev.clojure.org/display/community/Contributing+FAQ From 39867425e21d8c97a8b39163f3005048a8aad432 Mon Sep 17 00:00:00 2001 From: Neil Prosser Date: Thu, 29 Nov 2018 10:05:09 +0000 Subject: [PATCH 061/145] Only get result once during lookup Signed-off-by: Sean Corfield --- src/main/clojure/clojure/core/cache.clj | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/main/clojure/clojure/core/cache.clj b/src/main/clojure/clojure/core/cache.clj index fb3e7c2..2cb2fa7 100644 --- a/src/main/clojure/clojure/core/cache.clj +++ b/src/main/clojure/clojure/core/cache.clj @@ -522,9 +522,10 @@ CacheProtocol (lookup [_ item] (when-let [^SoftReference r (get cache (or item ::nil))] - (if (= ::nil (.get r)) - nil - (.get r)))) + (let [v (.get r)] + (if (= ::nil v) + nil + v)))) (lookup [_ item not-found] (if-let [^SoftReference r (get cache (or item ::nil))] (if-let [v (.get r)] From 99bc595c9baa71b67c67ef9f5669632da361d29b Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Sun, 6 Jan 2019 14:19:00 -0800 Subject: [PATCH 062/145] Update to test against Clojure 1.10, 1.11 (master) --- deps.edn | 5 +++-- run-tests.sh | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/deps.edn b/deps.edn index d7aeb2a..2f1cae0 100644 --- a/deps.edn +++ b/deps.edn @@ -1,6 +1,6 @@ ;; You can run clojure.core.cache tests with: clj -A:test:runner ;; You can also specify an alias to select which version of Clojure to test -;; against: :1.6 :1.7 :1.8 :1.9 :master +;; against: :1.6 :1.7 :1.8 :1.9 :1.10 :master {:paths ["src/main/clojure"] :deps {org.clojure/data.priority-map {:mvn/version "0.0.7"}} @@ -11,7 +11,8 @@ :1.7 {:override-deps {org.clojure/clojure {:mvn/version "1.7.0"}}} :1.8 {:override-deps {org.clojure/clojure {:mvn/version "1.8.0"}}} :1.9 {:override-deps {org.clojure/clojure {:mvn/version "1.9.0"}}} - :master {:override-deps {org.clojure/clojure {:mvn/version "1.10.0-master-SNAPSHOT"}}} + :1.10 {:override-deps {org.clojure/clojure {:mvn/version "1.10.0"}}} + :master {:override-deps {org.clojure/clojure {:mvn/version "1.11.0-master-SNAPSHOT"}}} :runner {:extra-deps {com.cognitect/test-runner {:git/url "https://github.com/cognitect-labs/test-runner" diff --git a/run-tests.sh b/run-tests.sh index ac187bc..d0674d4 100755 --- a/run-tests.sh +++ b/run-tests.sh @@ -1,6 +1,6 @@ #!/bin/sh -versions="1.6 1.7 1.8 1.9 master" +versions="1.6 1.7 1.8 1.9 1.10 master" for v in $versions do time clj -A:test:runner:$v From 5b8474a532a7f12ca1a1fbbf8f82a6f816c16b29 Mon Sep 17 00:00:00 2001 From: Neil Prosser Date: Thu, 29 Nov 2018 09:44:13 +0000 Subject: [PATCH 063/145] Fix SoftCache NPE Signed-off-by: Sean Corfield --- src/main/clojure/clojure/core/cache.clj | 3 ++- src/test/clojure/clojure/core/cache_test.clj | 11 +++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/main/clojure/clojure/core/cache.clj b/src/main/clojure/clojure/core/cache.clj index 2cb2fa7..8337ac0 100644 --- a/src/main/clojure/clojure/core/cache.clj +++ b/src/main/clojure/clojure/core/cache.clj @@ -509,7 +509,8 @@ (defn clear-soft-cache! [^java.util.Map cache ^java.util.Map rcache ^ReferenceQueue rq] (loop [r (.poll rq)] (when r - (.remove cache (get rcache r)) + (when-let [item (get rcache r)] + (.remove cache item)) (.remove rcache r) (recur (.poll rq))))) diff --git a/src/test/clojure/clojure/core/cache_test.clj b/src/test/clojure/clojure/core/cache_test.clj index 377c7d9..39c0ba4 100644 --- a/src/test/clojure/clojure/core/cache_test.clj +++ b/src/test/clojure/clojure/core/cache_test.clj @@ -485,6 +485,17 @@ N non-resident HIR block (is (not (.has? soft-cache :foo1))) (is (not (.has? old-soft-cache :foo1))))))) +(deftest test-soft-cache-eviction-handling + (let [ref (atom nil) + old-make-reference make-reference] + (with-redefs [make-reference (fn [& args] + (reset! ref (apply old-make-reference args)) + @ref)] + (let [cache (soft-cache-factory {})] + (miss cache :foo "foo") + (.enqueue @ref) + (evict cache :foo))))) + (deftest test-equiv (is (= (fifo-cache-factory {:a 1 :c 3} :threshold 3) (fifo-cache-factory {:a 1 :c 3} :threshold 3)))) From ad76dc922031d6d85075f51666ae22ad1a5cc0e3 Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Sun, 6 Jan 2019 14:31:55 -0800 Subject: [PATCH 064/145] Prep for 0.7.2 release --- README.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 7abb536..93703ea 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ core.cache is based on an old library named Clache that has been thoroughly depr Releases and Dependency Information ======================================== -Latest stable release: 0.7.1 +Latest stable release: 0.7.2 * [All Released Versions](http://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22org.clojure%22%20AND%20a%3A%22core.cache%22) @@ -35,7 +35,7 @@ Latest stable release: 0.7.1 [Leiningen](https://github.com/technomancy/leiningen) dependency information: - [org.clojure/core.cache "0.7.1"] + [org.clojure/core.cache "0.7.2"] [Maven](http://maven.apache.org/) dependency information: @@ -115,6 +115,9 @@ Developer Information Change Log ==================== +* Release 0.7.2 on 2019-01-06 + * [CCACHE-53](http://dev.clojure.org/jira/browse/CCACHE-53) Remove unnecessary/additional `.get` call (Neil Prosser) + * [CCACHE-52](http://dev.clojure.org/jira/browse/CCACHE-52) Fix NPE in SoftCache (Neil Prosser) * Release 0.7.1 on 2018.03.02 * [CCACHE-49](http://dev.clojure.org/jira/browse/CCACHE-49) Fix TTLCacheQ `seed` function and expand tests on TTLCacheQ * Release 0.7.0 on 2018.03.01 From 6ceea2341ca111e31e8fc79dcd8fd8fa2c6994f7 Mon Sep 17 00:00:00 2001 From: "Hudson @ build.clojure.org" Date: Sun, 6 Jan 2019 16:45:22 -0600 Subject: [PATCH 065/145] [maven-release-plugin] prepare release core.cache-0.7.2 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 5ce4b9f..723e237 100644 --- a/pom.xml +++ b/pom.xml @@ -2,14 +2,14 @@ 4.0.0 core.cache - 0.7.2-SNAPSHOT + 0.7.2 core.cache Cache library for Clojure. scm:git:git://github.com/clojure/core.cache.git scm:git:ssh://git@github.com/clojure/core.cache.git - HEAD + core.cache-0.7.2 https://github.com/clojure/core.cache From 49703e0358f95c6e5eff9ac14efcf044a8336422 Mon Sep 17 00:00:00 2001 From: "Hudson @ build.clojure.org" Date: Sun, 6 Jan 2019 16:45:22 -0600 Subject: [PATCH 066/145] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 723e237..248be35 100644 --- a/pom.xml +++ b/pom.xml @@ -2,14 +2,14 @@ 4.0.0 core.cache - 0.7.2 + 0.7.3-SNAPSHOT core.cache Cache library for Clojure. scm:git:git://github.com/clojure/core.cache.git scm:git:ssh://git@github.com/clojure/core.cache.git - core.cache-0.7.2 + HEAD https://github.com/clojure/core.cache From 8b965d9e0ec8fc2e05d8dd46d4392351908bacff Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Sun, 28 Apr 2019 15:08:04 -0700 Subject: [PATCH 067/145] Update links in PR template --- .github/PULL_REQUEST_TEMPLATE | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/PULL_REQUEST_TEMPLATE b/.github/PULL_REQUEST_TEMPLATE index 0a5c486..686625a 100644 --- a/.github/PULL_REQUEST_TEMPLATE +++ b/.github/PULL_REQUEST_TEMPLATE @@ -1,6 +1,6 @@ Hi! Thanks for your interest in contributing to this project. -Clojure contrib projects do not use GitHub issues or pull requests, and +Clojure contrib projects do not use GitHub issues or pull requests, and require a signed Contributor Agreement. If you would like to contribute, please read more about the CA and sign that first (this can be done online). @@ -8,7 +8,7 @@ Then go to this project's issue tracker in JIRA to create tickets, update tickets, or submit patches. For help in creating tickets and patches, please see: -- Signing the CA: https://dev.clojure.org/display/community/Contributing+FAQ -- Creating Tickets: https://dev.clojure.org/display/community/Creating+Tickets -- Developing Patches: https://dev.clojure.org/display/community/Developing+Patches -- Contributing FAQ: https://dev.clojure.org/display/community/Contributing+FAQ +- Signing the CA: https://clojure.org/community/contributing +- Creating Tickets: https://clojure.org/community/creating_tickets +- Developing Patches: https://clojure.org/community/developing_patches +- Contributing FAQ: https://clojure.org/community/contributing From b118a6f56ad6ea40e91e0766bb9c7eb4a651e2e8 Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Sun, 28 Apr 2019 15:31:43 -0700 Subject: [PATCH 068/145] Update links in CONTRIBUTING.md --- CONTRIBUTING.md | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 8cadea7..cf103c4 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -3,12 +3,10 @@ This is a [Clojure contrib] project. Under the Clojure contrib [guidelines], this project cannot accept pull requests. All patches must be submitted via [JIRA]. -See [Contributing] and the [FAQ] on the Clojure development [wiki] for +See [Contributing] on the Clojure website for more information on how to contribute. -[Clojure contrib]: http://dev.clojure.org/display/doc/Clojure+Contrib -[Contributing]: http://dev.clojure.org/display/community/Contributing -[FAQ]: http://dev.clojure.org/display/community/Contributing+FAQ +[Clojure contrib]: https://clojure.org/community/contrib_libs +[Contributing]: https://clojure.org/community/contributing [JIRA]: http://dev.clojure.org/jira/browse/CCACHE -[guidelines]: http://dev.clojure.org/display/community/Guidelines+for+Clojure+Contrib+committers -[wiki]: http://dev.clojure.org/ +[guidelines]: https://clojure.org/community/contrib_howto From e0c665805be6e6d6cbee971770dfc9062216302d Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Sat, 18 May 2019 12:19:53 -0700 Subject: [PATCH 069/145] JIRA migration --- CONTRIBUTING.md | 2 +- README.md | 36 +++++++++++------------ docs/README.md | 2 +- docs/release-notes/release-0.5.0.markdown | 2 +- docs/release-notes/release-0.6.1.markdown | 2 +- docs/release-notes/release-0.6.2.markdown | 2 +- 6 files changed, 23 insertions(+), 23 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index cf103c4..17e4617 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -8,5 +8,5 @@ more information on how to contribute. [Clojure contrib]: https://clojure.org/community/contrib_libs [Contributing]: https://clojure.org/community/contributing -[JIRA]: http://dev.clojure.org/jira/browse/CCACHE +[JIRA]: http://clojure.atlassian.net/browse/CCACHE [guidelines]: https://clojure.org/community/contrib_howto diff --git a/README.md b/README.md index 93703ea..6dd517a 100644 --- a/README.md +++ b/README.md @@ -104,7 +104,7 @@ Developer Information * [GitHub project](https://github.com/clojure/core.cache) -* [Bug Tracker](http://dev.clojure.org/jira/browse/CCACHE) +* [Bug Tracker](http://clojure.atlassian.net/browse/CCACHE) * [Continuous Integration](http://build.clojure.org/job/core.cache/) @@ -116,30 +116,30 @@ Change Log ==================== * Release 0.7.2 on 2019-01-06 - * [CCACHE-53](http://dev.clojure.org/jira/browse/CCACHE-53) Remove unnecessary/additional `.get` call (Neil Prosser) - * [CCACHE-52](http://dev.clojure.org/jira/browse/CCACHE-52) Fix NPE in SoftCache (Neil Prosser) + * [CCACHE-53](http://clojure.atlassian.net/browse/CCACHE-53) Remove unnecessary/additional `.get` call (Neil Prosser) + * [CCACHE-52](http://clojure.atlassian.net/browse/CCACHE-52) Fix NPE in SoftCache (Neil Prosser) * Release 0.7.1 on 2018.03.02 - * [CCACHE-49](http://dev.clojure.org/jira/browse/CCACHE-49) Fix TTLCacheQ `seed` function and expand tests on TTLCacheQ + * [CCACHE-49](http://clojure.atlassian.net/browse/CCACHE-49) Fix TTLCacheQ `seed` function and expand tests on TTLCacheQ * Release 0.7.0 on 2018.03.01 - * [CCACHE-46](http://dev.clojure.org/jira/browse/CCACHE-46) Fix TTLCache when wrapped around another cache (Ivan Kryvoruchko) - * [CCACHE-43](http://dev.clojure.org/jira/browse/CCACHE-43) Add `through-cache` to provide a version of `through` that plays nice with `swap!` etc - * [CCACHE-40](http://dev.clojure.org/jira/browse/CCACHE-40) Fix FIFOCache stack overflow on large threshold (uses PersistentQueue now instead of concat and list) - * [CCACHE-39](http://dev.clojure.org/jira/browse/CCACHE-39) Fix FIFOCache evict/miss queue handling - * [CCACHE-20](http://dev.clojure.org/jira/browse/CCACHE-20) Updated README to clarify that caches are immutable and provide examples of use with `atom` etc - * [CCACHE-15](http://dev.clojure.org/jira/browse/CCACHE-15) Added queue and generation logic to reduce `miss` cost and make `evict` O(1); rename TTLCache -> TTLCacheQ (Kevin Downey) + * [CCACHE-46](http://clojure.atlassian.net/browse/CCACHE-46) Fix TTLCache when wrapped around another cache (Ivan Kryvoruchko) + * [CCACHE-43](http://clojure.atlassian.net/browse/CCACHE-43) Add `through-cache` to provide a version of `through` that plays nice with `swap!` etc + * [CCACHE-40](http://clojure.atlassian.net/browse/CCACHE-40) Fix FIFOCache stack overflow on large threshold (uses PersistentQueue now instead of concat and list) + * [CCACHE-39](http://clojure.atlassian.net/browse/CCACHE-39) Fix FIFOCache evict/miss queue handling + * [CCACHE-20](http://clojure.atlassian.net/browse/CCACHE-20) Updated README to clarify that caches are immutable and provide examples of use with `atom` etc + * [CCACHE-15](http://clojure.atlassian.net/browse/CCACHE-15) Added queue and generation logic to reduce `miss` cost and make `evict` O(1); rename TTLCache -> TTLCacheQ (Kevin Downey) * Drop support for Clojure 1.3/1.4/1.5 * Release 0.6.5 on 2016.03.28 * Bump tools.priority-map dependency to 0.0.7 - * [CCACHE-41](http://dev.clojure.org/jira/browse/CCACHE-41) Implement Iterable in defcache - * [CCACHE-44](http://dev.clojure.org/jira/browse/CCACHE-44) Avoid equals comparison on cache miss - * [CCACHE-37](http://dev.clojure.org/jira/browse/CCACHE-37) Fix typo in docstring + * [CCACHE-41](http://clojure.atlassian.net/browse/CCACHE-41) Implement Iterable in defcache + * [CCACHE-44](http://clojure.atlassian.net/browse/CCACHE-44) Avoid equals comparison on cache miss + * [CCACHE-37](http://clojure.atlassian.net/browse/CCACHE-37) Fix typo in docstring * Release 0.6.4 on 2014.08.06 * Thanks to Paul Stadig and Nicola Mometto who contributed patches for this release - * [CCACHE-34](http://dev.clojure.org/jira/browse/CCACHE-34) bump tools.priority-map dependency to 0.0.4 - * [CCACHE-28](http://dev.clojure.org/jira/browse/CCACHE-28) concurrency bug in has? for SoftCache - * [CCACHE-29](http://dev.clojure.org/jira/browse/CCACHE-29) fix conj implementation for caches - * [CCACHE-30](http://dev.clojure.org/jira/browse/CCACHE-30) make-reference need not be dynamic - * [CCACHE-26](http://dev.clojure.org/jira/browse/CCACHE-26) hit function in LRU cache can give funny results + * [CCACHE-34](http://clojure.atlassian.net/browse/CCACHE-34) bump tools.priority-map dependency to 0.0.4 + * [CCACHE-28](http://clojure.atlassian.net/browse/CCACHE-28) concurrency bug in has? for SoftCache + * [CCACHE-29](http://clojure.atlassian.net/browse/CCACHE-29) fix conj implementation for caches + * [CCACHE-30](http://clojure.atlassian.net/browse/CCACHE-30) make-reference need not be dynamic + * [CCACHE-26](http://clojure.atlassian.net/browse/CCACHE-26) hit function in LRU cache can give funny results * Release 0.6.3 on 2013.03.15 * Added through to encapsulate check logic * Release 0.6.2 on 2012.08.07 [more information](http://blog.fogus.me/?p=4527) diff --git a/docs/README.md b/docs/README.md index 3f931c2..31b80c3 100644 --- a/docs/README.md +++ b/docs/README.md @@ -42,6 +42,6 @@ core.cache is a Clojure contrib library providing the following features: ## Places * [Source code](https://github.com/clojure/core.cache) -* [Ticket system](http://dev.clojure.org/jira/browse/CCACHE) +* [Ticket system](http://clojure.atlassian.net/browse/CCACHE) * [Announcement](http://groups.google.com/group/clojure/browse_frm/thread/69d08572ab265dc7) * [Examples and documentation](http://github.com/clojure/core.cache/wiki) \ No newline at end of file diff --git a/docs/release-notes/release-0.5.0.markdown b/docs/release-notes/release-0.5.0.markdown index 98c604e..b07d756 100644 --- a/docs/release-notes/release-0.5.0.markdown +++ b/docs/release-notes/release-0.5.0.markdown @@ -43,7 +43,7 @@ Places ------ * [Source code](https://github.com/clojure/core.cache) -* [Ticket system](http://dev.clojure.org/jira/browse/CCACHE) +* [Ticket system](http://clojure.atlassian.net/browse/CCACHE) * [Announcement](http://groups.google.com/group/clojure/browse_frm/thread/69d08572ab265dc7) * Examples and documentation -- in progress diff --git a/docs/release-notes/release-0.6.1.markdown b/docs/release-notes/release-0.6.1.markdown index 5fc65ea..f5fadd5 100644 --- a/docs/release-notes/release-0.6.1.markdown +++ b/docs/release-notes/release-0.6.1.markdown @@ -41,7 +41,7 @@ Places ------ * [Source code](https://github.com/clojure/core.cache) -* [Ticket system](http://dev.clojure.org/jira/browse/CCACHE) +* [Ticket system](http://clojure.atlassian.net/browse/CCACHE) * [Announcement](http://groups.google.com/group/clojure/browse_frm/thread/69d08572ab265dc7) * [API Reference](https://clojure.github.com/core.cache) * [Examples and documentation](https://github.com/clojure/core.cache/wiki) (work in progress) diff --git a/docs/release-notes/release-0.6.2.markdown b/docs/release-notes/release-0.6.2.markdown index dc2d1c9..c2729e5 100644 --- a/docs/release-notes/release-0.6.2.markdown +++ b/docs/release-notes/release-0.6.2.markdown @@ -41,7 +41,7 @@ Places ------ * [Source code](https://github.com/clojure/core.cache) -* [Ticket system](http://dev.clojure.org/jira/browse/CCACHE) +* [Ticket system](http://clojure.atlassian.net/browse/CCACHE) * [Announcement](http://groups.google.com/group/clojure/browse_frm/thread/69d08572ab265dc7) * [API Reference](https://clojure.github.com/core.cache) * [Examples and documentation](https://github.com/clojure/core.cache/wiki) (work in progress) From 78640c1d6abe52890d091060d3c9e09b2384ac30 Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Thu, 22 Aug 2019 14:52:04 -0700 Subject: [PATCH 070/145] Fix missing value in map --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 6dd517a..8b52eaa 100644 --- a/README.md +++ b/README.md @@ -88,7 +88,7 @@ Example Usage (swap! C2 cache/evict :b) - ;=> {:a 1, :d} + ;=> {:a 1, :d 13} (get @C2 :a) From 54cb90529d68d6d762f872016bb5550c7f8293c5 Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Sat, 24 Aug 2019 15:28:12 -0700 Subject: [PATCH 071/145] Prep for 0.8.0 with addition of clojure.core.cache.wrapped API --- README.md | 42 ++++- .../clojure/clojure/core/cache/wrapped.clj | 178 ++++++++++++++++++ .../clojure/core/cache/wrapped_test.clj | 27 +++ 3 files changed, 241 insertions(+), 6 deletions(-) create mode 100644 src/main/clojure/clojure/core/cache/wrapped.clj create mode 100644 src/test/clojure/clojure/core/cache/wrapped_test.clj diff --git a/README.md b/README.md index 6dd517a..f20c3f0 100644 --- a/README.md +++ b/README.md @@ -21,13 +21,16 @@ core.cache is a Clojure contrib library providing the following features: * Caches are generally immutable and should be used in conjunction with Clojure's state management, such as `atom`. SoftCache is the exception here, built on top of mutable Java collections, but it can be treated as an immutable cache as well. +The `clojure.core.cache` namespace contains the immutable caches themselves. +The `clojure.core.cache.wrapped` namespace contains the same API operating on caches wrapped in atoms, which is the "normal" use in the wild (introduced in 0.8.0). + core.cache is based on an old library named Clache that has been thoroughly deprecated. Releases and Dependency Information ======================================== -Latest stable release: 0.7.2 +Latest stable release: 0.8.0 * [All Released Versions](http://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22org.clojure%22%20AND%20a%3A%22core.cache%22) @@ -35,14 +38,14 @@ Latest stable release: 0.7.2 [Leiningen](https://github.com/technomancy/leiningen) dependency information: - [org.clojure/core.cache "0.7.2"] + [org.clojure/core.cache "0.8.0"] [Maven](http://maven.apache.org/) dependency information: org.clojure core.cache - 0.7.1 + 0.8.0 @@ -88,15 +91,40 @@ Example Usage (swap! C2 cache/evict :b) - ;=> {:a 1, :d} + ;=> {:a 1, :d 13} (get @C2 :a) ;=> 1 -``` -Refer to docstrings in the `clojure.core.cache` namespace, or the [autogenerated API documentation](http://clojure.github.com/core.cache/) for additional documentation + ;; or use the wrapped API instead: + (require '[clojure.core.cache.wrapped :as c]) + + (def C3 (c/fifo-cache-factory {:a 1, :b 2})) + + (c/through-cache C3 :d (constantly 13)) ; returns updated cache + + ;=> {:a 1, :b 3, :d 13} + + (c/evict C3 :b) + + ;=> {:a 1, :d 13} + + (c/lookup C3 :a) ; or (get @C3 :a) + + ;=> 1 + + ;; unique to the wrapped API: + (c/lookup-or-miss C3 :b (constantly 42)) + + ;=> 42 + + @C3 + + ;=> {:a 1, :d 13, :b 42} +``` +Refer to docstrings in the `clojure.core.cache` or `clojure.core.cache.wrapped` namespaces, or the [autogenerated API documentation](http://clojure.github.com/core.cache/) for additional documentation. Developer Information @@ -115,6 +143,8 @@ Developer Information Change Log ==================== +* Release 0.8.0 on 2019-08-24 + * [CCACHE-50](http://clojure.atlassian.net/browse/CCACHE-50) Add `clojure.core.cache.wrapped` namespace with atom-wrapped caches for a more convenient API that adds `lookup-or-miss` which avoids the possibility of cache stampede * Release 0.7.2 on 2019-01-06 * [CCACHE-53](http://clojure.atlassian.net/browse/CCACHE-53) Remove unnecessary/additional `.get` call (Neil Prosser) * [CCACHE-52](http://clojure.atlassian.net/browse/CCACHE-52) Fix NPE in SoftCache (Neil Prosser) diff --git a/src/main/clojure/clojure/core/cache/wrapped.clj b/src/main/clojure/clojure/core/cache/wrapped.clj new file mode 100644 index 0000000..02012e3 --- /dev/null +++ b/src/main/clojure/clojure/core/cache/wrapped.clj @@ -0,0 +1,178 @@ +; Copyright (c) Rich Hickey. All rights reserved. +; The use and distribution terms for this software are covered by the +; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) +; which can be found in the file epl-v10.html at the root of this distribution. +; By using this software in any fashion, you are agreeing to be bound by +; the terms of this license. +; You must not remove this notice, or any other, from this software. + +(ns clojure.core.cache.wrapped + "A higher level way to use clojure.core.cache that assumes the immutable + cache is wrapped in an atom. + + The API is (almost) the same as clojure.core.cache -- including the factory + functions -- but instead of accepting immutable caches, the functions + here accept atoms containing those caches. The factory functions return + new atoms containing the newly created cache. + + In addition, lookup-or-miss provides a safe, atomic way to retrieve a + value from a cache or compute it if it is missing, without risking a + cache stampede." + (:require [clojure.core.cache :as c])) + +(set! *warn-on-reflection* true) + +(defn lookup + "Retrieve the value associated with `e` if it exists, else `nil` in + the 2-arg case. Retrieve the value associated with `e` if it exists, + else `not-found` in the 3-arg case. + + Reads from the current version of the atom." + ([cache-atom e] + (c/lookup @cache-atom e)) + ([cache-atom e not-found] + (c/lookup @cache-atom e not-found))) + +(def ^{:private true} default-wrapper-fn #(%1 %2)) + +(defn lookup-or-miss + "Retrieve the value associated with `e` if it exists, else compute the + value (using value-fn, and optionally wrap-fn), update the cache for `e` + and then perform the lookup again. + + value-fn (and wrap-fn) will only be called (at most) once even in the + case of retries, so there is no risk of cache stampede." + ([cache-atom e value-fn] + (lookup-or-miss cache-atom e default-wrapper-fn value-fn)) + ([cache-atom e wrap-fn value-fn] + (let [d-new-value (delay (wrap-fn value-fn e))] + (c/lookup (swap! cache-atom + c/through-cache e default-wrapper-fn (fn [_] @d-new-value)) + e)))) + +(defn has? + "Checks if the cache contains a value associated with `e`. + + Reads from the current version of the atom." + [cache-atom e] + (c/has? @cache-atom e)) + +(defn hit + "Is meant to be called if the cache is determined to contain a value + associated with `e`. + + Returns the updated cache from the atom. Provided for completeness." + [cache-atom e] + (swap! cache-atom c/hit e)) + +(defn miss + "Is meant to be called if the cache is determined to **not** contain a + value associated with `e`. + + Returns the updated cache from the atom. Provided for completeness." + [cache-atom e ret] + (swap! cache-atom c/miss cache-atom e ret)) + +(defn evict + "Removes an entry from the cache. + + Returns the updated cache from the atom." + [cache-atom e] + (swap! cache-atom c/evict e)) + +(defn seed + "Is used to signal that the cache should be created with a seed. + The contract is that said cache should return an instance of its + own type. + + Returns the updated cache from the atom. Provided for completeness." + [cache-atom base] + (swap! cache-atom c/seed base)) + +(defn through + "The basic hit/miss logic for the cache system. Expects a wrap function and + value function. The wrap function takes the value function and the item in question + and is expected to run the value function with the item whenever a cache + miss occurs. The intent is to hide any cache-specific cells from leaking + into the cache logic itelf." + ([cache-atom item] (through default-wrapper-fn identity cache-atom item)) + ([value-fn cache-atom item] (through default-wrapper-fn value-fn cache-atom item)) + ([wrap-fn value-fn cache-atom item] + (swap! cache-atom c/through-cache item wrap-fn value-fn))) + +(defn through-cache + "The basic hit/miss logic for the cache system. Like through but always has + the cache argument in the first position." + ([cache-atom item] (through-cache cache-atom item default-wrapper-fn identity)) + ([cache-atom item value-fn] (through-cache cache-atom item default-wrapper-fn value-fn)) + ([cache-atom item wrap-fn value-fn] + (swap! cache-atom c/through-cache item wrap-fn value-fn))) + +(defn basic-cache-factory + "Returns a pluggable basic cache initialied to `base`" + [base] + (atom (c/basic-cache-factory base))) + +(defn fifo-cache-factory + "Returns a FIFO cache with the cache and FIFO queue initialized to `base` -- + the queue is filled as the values are pulled out of `base`. If the associative + structure can guarantee ordering, then the said ordering will define the + eventual eviction order. Otherwise, there are no guarantees for the eventual + eviction ordering. + + This function takes an optional `:threshold` argument that defines the maximum number + of elements in the cache before the FIFO semantics apply (default is 32). + + If the number of elements in `base` is greater than the limit then some items + in `base` will be dropped from the resulting cache. If the associative + structure used as `base` can guarantee sorting, then the last `limit` elements + will be used as the cache seed values. Otherwise, there are no guarantees about + the elements in the resulting cache." + [base & {threshold :threshold :or {threshold 32}}] + (atom (c/fifo-cache-factory base :threshold threshold))) + +(defn lru-cache-factory + "Returns an LRU cache with the cache and usage-table initialied to `base` -- + each entry is initialized with the same usage value. + + This function takes an optional `:threshold` argument that defines the maximum number + of elements in the cache before the LRU semantics apply (default is 32)." + [base & {threshold :threshold :or {threshold 32}}] + (atom (c/lru-cache-factory base :threshold threshold))) + +(defn ttl-cache-factory + "Returns a TTL cache with the cache and expiration-table initialized to `base` -- + each with the same time-to-live. + + This function also allows an optional `:ttl` argument that defines the default + time in milliseconds that entries are allowed to reside in the cache." + [base & {ttl :ttl :or {ttl 2000}}] + (atom (c/ttl-cache-factory :ttl ttl))) + +(defn lu-cache-factory + "Returns an LU cache with the cache and usage-table initialied to `base`. + + This function takes an optional `:threshold` argument that defines the maximum number + of elements in the cache before the LU semantics apply (default is 32)." + [base & {threshold :threshold :or {threshold 32}}] + (atom (c/lu-cache-factory base :threshold threshold))) + +(defn lirs-cache-factory + "Returns an LIRS cache with the S & R LRU lists set to the indicated + limits." + [base & {:keys [s-history-limit q-history-limit] + :or {s-history-limit 32 + q-history-limit 32}}] + (atom (c/lirs-cache-factory base + :s-history-limit s-history-limit + :q-history-limit q-history-limit))) + +(defn soft-cache-factory + "Returns a SoftReference cache. Cached values will be referred to with + SoftReferences, allowing the values to be garbage collected when there is + memory pressure on the JVM. + + SoftCache is a mutable cache, since it is always based on a + ConcurrentHashMap." + [base] + (atom (c/soft-cache-factory base))) diff --git a/src/test/clojure/clojure/core/cache/wrapped_test.clj b/src/test/clojure/clojure/core/cache/wrapped_test.clj new file mode 100644 index 0000000..dea5d6e --- /dev/null +++ b/src/test/clojure/clojure/core/cache/wrapped_test.clj @@ -0,0 +1,27 @@ +; Copyright (c) Rich Hickey. All rights reserved. +; The use and distribution terms for this software are covered by the +; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) +; which can be found in the file epl-v10.html at the root of this distribution. +; By using this software in any fashion, you are agreeing to be bound by +; the terms of this license. +; You must not remove this notice, or any other, from this software. + +(ns clojure.core.cache.wrapped-test + (:require [clojure.core.cache.wrapped :as c] + [clojure.test :refer [deftest is]])) + +(deftest basic-wrapped-test + (let [cache (c/basic-cache-factory {})] + (is (= nil (c/lookup cache :a))) + (is (= ::missing (c/lookup cache :a ::missing))) + ;; mutating operation + (is (= 42 (c/lookup-or-miss cache :a (constantly 42)))) + ;; cache now contains :a + (is (= 42 (c/lookup cache :a))) + ;; :a is present, does not call value-fn + (is (= 42 (c/lookup-or-miss cache :a #(throw (ex-info "bad" {:key %}))))) + ;; cache still contains :a as 42 + (is (= 42 (c/lookup cache :a))) + (c/evict cache :a) + (is (= nil (c/lookup cache :a))) + (is (= ::missing (c/lookup cache :a ::missing))))) From 95266938ed46842fd0487e90d52355561c9023a6 Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Sat, 24 Aug 2019 15:33:06 -0700 Subject: [PATCH 072/145] Update legacy docs to reflect latest status --- docs/Including.md | 6 +++--- docs/Plans.md | 3 ++- docs/Using.md | 6 +++--- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/docs/Including.md b/docs/Including.md index 9718bca..ed859c1 100644 --- a/docs/Including.md +++ b/docs/Including.md @@ -10,7 +10,7 @@ The core.cache releases and snapshots are stored in the following repositories: You can use core.cache in your [Leiningen](https://github.com/technomancy/leiningen) projects with the following `:dependencies` directive in your `project.clj` file: - [org.clojure/core.cache "0.6.3"] + [org.clojure/core.cache "0.8.0"] ## Maven @@ -19,7 +19,7 @@ For Maven-driven projects, use the following slice of XML in your `pom.xml`'s `< org.clojure core.cache - 0.6.3 + 0.8.0 -Enjoy! \ No newline at end of file +Enjoy! diff --git a/docs/Plans.md b/docs/Plans.md index 45fe0b2..17d95e2 100644 --- a/docs/Plans.md +++ b/docs/Plans.md @@ -1,5 +1,7 @@ # Plans for core.cache +These were Fogus's plans for core.cache. See https://clojure.atlassian.net/projects/CCACHE/issues/?filter=allopenissues for what is actually being considered. + * Most Recently Used cache implementation * Function-backed cache implementation * Random eviction cache implementation @@ -10,4 +12,3 @@ * test.generative usage * Explore Arc impl. * More documentation and examples - diff --git a/docs/Using.md b/docs/Using.md index e5a7f66..4fc8371 100644 --- a/docs/Using.md +++ b/docs/Using.md @@ -32,17 +32,17 @@ To ensure the proper cache policies are followed for each specific type, the fol (if (cache/has? C :c) ;; has? checks that the cache contains an item (cache/hit C :c) ;; hit returns a cache with any relevant internal information updated (cache/miss C :c 42)) ;; miss returns a new cache with the new item and without evicted entries - + ;=> {:a 1, :b 2, :c 42} ``` -Using the `has?/hit/miss` pattern ensures that the thresholding and eviction logic for each implementation works properly. **Avoid this pattern at your own risk.** +Using the `has?/hit/miss` pattern ensures that the thresholding and eviction logic for each implementation works properly. It is built into the `through` and `through-cache` functions, as well as `clojure.core.cache.wrapped/lookup-or-miss`. **Avoid this pattern at your own risk.** Finally, to explicitly evict an element in a cache, use the `evict` function: ```clojure (cache/evict C :b) - + ;=> {:a 1} ``` From d4266d4a253cf8746bcfbc415516b2a3b9464378 Mon Sep 17 00:00:00 2001 From: "Hudson @ build.clojure.org" Date: Sat, 24 Aug 2019 17:35:37 -0500 Subject: [PATCH 073/145] [maven-release-plugin] prepare release core.cache-0.8.0 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 248be35..d2b9469 100644 --- a/pom.xml +++ b/pom.xml @@ -2,14 +2,14 @@ 4.0.0 core.cache - 0.7.3-SNAPSHOT + 0.8.0 core.cache Cache library for Clojure. scm:git:git://github.com/clojure/core.cache.git scm:git:ssh://git@github.com/clojure/core.cache.git - HEAD + core.cache-0.8.0 https://github.com/clojure/core.cache From 09630b2c76c82f4d22bdf61b8ecd668d5568e60e Mon Sep 17 00:00:00 2001 From: "Hudson @ build.clojure.org" Date: Sat, 24 Aug 2019 17:35:37 -0500 Subject: [PATCH 074/145] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index d2b9469..9652ec1 100644 --- a/pom.xml +++ b/pom.xml @@ -2,14 +2,14 @@ 4.0.0 core.cache - 0.8.0 + 0.8.1-SNAPSHOT core.cache Cache library for Clojure. scm:git:git://github.com/clojure/core.cache.git scm:git:ssh://git@github.com/clojure/core.cache.git - core.cache-0.8.0 + HEAD https://github.com/clojure/core.cache From 5b1fa3fccbc9671668c095d2d101e5ddc7074e44 Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Sat, 24 Aug 2019 18:24:07 -0700 Subject: [PATCH 075/145] Prep for 0.8.1 release (with fix for wrapped TTL cache) Also `lookup-or-miss` will retry for caches that can invalidate on `lookup` (e.g., TTL). --- README.md | 2 ++ .../clojure/clojure/core/cache/wrapped.clj | 29 +++++++++++++++---- .../clojure/core/cache/wrapped_test.clj | 15 ++++++++++ 3 files changed, 41 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index f20c3f0..3219f41 100644 --- a/README.md +++ b/README.md @@ -143,6 +143,8 @@ Developer Information Change Log ==================== +* Release 0.8.1 on 2019-08-24 + * [CCACHE-56](http://clojure.atlassian.net/browse/CCACHE-56) Fix TTL cache and fix `clojure.core.cache.wrapped/lookup-or-miss` for caches that can invalidate on `lookup` * Release 0.8.0 on 2019-08-24 * [CCACHE-50](http://clojure.atlassian.net/browse/CCACHE-50) Add `clojure.core.cache.wrapped` namespace with atom-wrapped caches for a more convenient API that adds `lookup-or-miss` which avoids the possibility of cache stampede * Release 0.7.2 on 2019-01-06 diff --git a/src/main/clojure/clojure/core/cache/wrapped.clj b/src/main/clojure/clojure/core/cache/wrapped.clj index 02012e3..a05e190 100644 --- a/src/main/clojure/clojure/core/cache/wrapped.clj +++ b/src/main/clojure/clojure/core/cache/wrapped.clj @@ -41,14 +41,33 @@ and then perform the lookup again. value-fn (and wrap-fn) will only be called (at most) once even in the - case of retries, so there is no risk of cache stampede." + case of retries, so there is no risk of cache stampede. + + Since lookup can cause invalidation in some caches (such as TTL), we + trap that case and retry (a maximum of ten times)." ([cache-atom e value-fn] (lookup-or-miss cache-atom e default-wrapper-fn value-fn)) ([cache-atom e wrap-fn value-fn] (let [d-new-value (delay (wrap-fn value-fn e))] - (c/lookup (swap! cache-atom - c/through-cache e default-wrapper-fn (fn [_] @d-new-value)) - e)))) + (loop [n 0 + v (c/lookup (swap! cache-atom + c/through-cache + e + default-wrapper-fn + (fn [_] @d-new-value)) + e + ::expired)] + (when (< n 10) + (if (= ::expired v) + (recur (inc n) + (c/lookup (swap! cache-atom + c/through-cache + e + default-wrapper-fn + (fn [_] @d-new-value)) + e + ::expired)) + v)))))) (defn has? "Checks if the cache contains a value associated with `e`. @@ -147,7 +166,7 @@ This function also allows an optional `:ttl` argument that defines the default time in milliseconds that entries are allowed to reside in the cache." [base & {ttl :ttl :or {ttl 2000}}] - (atom (c/ttl-cache-factory :ttl ttl))) + (atom (c/ttl-cache-factory base :ttl ttl))) (defn lu-cache-factory "Returns an LU cache with the cache and usage-table initialied to `base`. diff --git a/src/test/clojure/clojure/core/cache/wrapped_test.clj b/src/test/clojure/clojure/core/cache/wrapped_test.clj index dea5d6e..49deaa1 100644 --- a/src/test/clojure/clojure/core/cache/wrapped_test.clj +++ b/src/test/clojure/clojure/core/cache/wrapped_test.clj @@ -25,3 +25,18 @@ (c/evict cache :a) (is (= nil (c/lookup cache :a))) (is (= ::missing (c/lookup cache :a ::missing))))) + +(deftest wrapped-ttl-test + ;; TTL lookup-or-miss can expire on the lookup so this test verifies + ;; that bug (in 0.8.0) so I can fix it in 0.8.1! + (let [cache (c/ttl-cache-factory {} :ttl 1) + limit 2000000 + start (System/currentTimeMillis)] + (loop [n 0] + (if-not (c/lookup-or-miss cache :a (constantly 42)) + (do + (is false (str "Failure on call " n))) + (if (< n limit) + (recur (+ 1 n))))) + (println "ttl test completed" limit "calls in" + (- (System/currentTimeMillis) start) "ms"))) From 8b0aae79bb615d8c0924b6cc212f7a162dadd208 Mon Sep 17 00:00:00 2001 From: "Hudson @ build.clojure.org" Date: Sat, 24 Aug 2019 20:25:42 -0500 Subject: [PATCH 076/145] [maven-release-plugin] prepare release core.cache-0.8.1 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 9652ec1..3086868 100644 --- a/pom.xml +++ b/pom.xml @@ -2,14 +2,14 @@ 4.0.0 core.cache - 0.8.1-SNAPSHOT + 0.8.1 core.cache Cache library for Clojure. scm:git:git://github.com/clojure/core.cache.git scm:git:ssh://git@github.com/clojure/core.cache.git - HEAD + core.cache-0.8.1 https://github.com/clojure/core.cache From fc6362a31626008c902aac730a6ef13785654297 Mon Sep 17 00:00:00 2001 From: "Hudson @ build.clojure.org" Date: Sat, 24 Aug 2019 20:25:42 -0500 Subject: [PATCH 077/145] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 3086868..50de6b9 100644 --- a/pom.xml +++ b/pom.xml @@ -2,14 +2,14 @@ 4.0.0 core.cache - 0.8.1 + 0.8.2-SNAPSHOT core.cache Cache library for Clojure. scm:git:git://github.com/clojure/core.cache.git scm:git:ssh://git@github.com/clojure/core.cache.git - core.cache-0.8.1 + HEAD https://github.com/clojure/core.cache From 8c5bdb1ac1c648036c1a0d07ff6bdea8ea2cc4da Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Sat, 24 Aug 2019 18:30:38 -0700 Subject: [PATCH 078/145] Update docs/readme for 0.8.1 --- README.md | 8 ++++---- docs/Including.md | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 3219f41..de26d3c 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ core.cache is based on an old library named Clache that has been thoroughly depr Releases and Dependency Information ======================================== -Latest stable release: 0.8.0 +Latest stable release: 0.8.1 * [All Released Versions](http://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22org.clojure%22%20AND%20a%3A%22core.cache%22) @@ -38,14 +38,14 @@ Latest stable release: 0.8.0 [Leiningen](https://github.com/technomancy/leiningen) dependency information: - [org.clojure/core.cache "0.8.0"] + [org.clojure/core.cache "0.8.1"] [Maven](http://maven.apache.org/) dependency information: org.clojure core.cache - 0.8.0 + 0.8.1 @@ -144,7 +144,7 @@ Change Log ==================== * Release 0.8.1 on 2019-08-24 - * [CCACHE-56](http://clojure.atlassian.net/browse/CCACHE-56) Fix TTL cache and fix `clojure.core.cache.wrapped/lookup-or-miss` for caches that can invalidate on `lookup` + * [CCACHE-56](http://clojure.atlassian.net/browse/CCACHE-56) Fix wrapped TTL cache and fix `clojure.core.cache.wrapped/lookup-or-miss` for caches that can invalidate on `lookup` * Release 0.8.0 on 2019-08-24 * [CCACHE-50](http://clojure.atlassian.net/browse/CCACHE-50) Add `clojure.core.cache.wrapped` namespace with atom-wrapped caches for a more convenient API that adds `lookup-or-miss` which avoids the possibility of cache stampede * Release 0.7.2 on 2019-01-06 diff --git a/docs/Including.md b/docs/Including.md index ed859c1..afc1b71 100644 --- a/docs/Including.md +++ b/docs/Including.md @@ -10,7 +10,7 @@ The core.cache releases and snapshots are stored in the following repositories: You can use core.cache in your [Leiningen](https://github.com/technomancy/leiningen) projects with the following `:dependencies` directive in your `project.clj` file: - [org.clojure/core.cache "0.8.0"] + [org.clojure/core.cache "0.8.1"] ## Maven @@ -19,7 +19,7 @@ For Maven-driven projects, use the following slice of XML in your `pom.xml`'s `< org.clojure core.cache - 0.8.0 + 0.8.1 Enjoy! From f07407272ebe78a461fff790b40ff69af8c115cd Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Mon, 26 Aug 2019 09:49:05 -0700 Subject: [PATCH 079/145] Fix old typo in old docs --- docs/Extending.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/Extending.md b/docs/Extending.md index 5855e26..6a1812a 100644 --- a/docs/Extending.md +++ b/docs/Extending.md @@ -100,7 +100,7 @@ The `hit` method in this case is trivial, it just returns the instance itself. threshold))))) ``` -The `miss` method is where all the action takes place. That is, if the size of the base `cache` is less than the `threshold` then the cached value is staored in the base `cache` and its key in the `ks` set. However, if the threshold was breached then the first key in the `ks` set is removed from the base `cache` and `ks` and a new `LameCache` instance is returned with the new key and value added to `cache` and `ks`. +The `miss` method is where all the action takes place. That is, if the size of the base `cache` is less than the `threshold` then the cached value is stored in the base `cache` and its key in the `ks` set. However, if the threshold was breached then the first key in the `ks` set is removed from the base `cache` and `ks` and a new `LameCache` instance is returned with the new key and value added to `cache` and `ks`. ```clojure (evict [_ key] From 68c317bad2706267a63d024fe3bb5aaf5c1b7b75 Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Mon, 30 Sep 2019 15:56:35 -0700 Subject: [PATCH 080/145] Fixes CCACHE-57; prep for 0.8.2 --- README.md | 8 +++++--- docs/Including.md | 4 ++-- src/main/clojure/clojure/core/cache/wrapped.clj | 2 +- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index de26d3c..2dffcab 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ core.cache is based on an old library named Clache that has been thoroughly depr Releases and Dependency Information ======================================== -Latest stable release: 0.8.1 +Latest stable release: 0.8.2 * [All Released Versions](http://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22org.clojure%22%20AND%20a%3A%22core.cache%22) @@ -38,14 +38,14 @@ Latest stable release: 0.8.1 [Leiningen](https://github.com/technomancy/leiningen) dependency information: - [org.clojure/core.cache "0.8.1"] + [org.clojure/core.cache "0.8.2"] [Maven](http://maven.apache.org/) dependency information: org.clojure core.cache - 0.8.1 + 0.8.2 @@ -143,6 +143,8 @@ Developer Information Change Log ==================== +* Release 0.8.2 on 2019-09-30 + * [CCACHE-57](http://clojure.atlassian.net/browse/CCACHE-57) Fix wrapped cache `miss` function * Release 0.8.1 on 2019-08-24 * [CCACHE-56](http://clojure.atlassian.net/browse/CCACHE-56) Fix wrapped TTL cache and fix `clojure.core.cache.wrapped/lookup-or-miss` for caches that can invalidate on `lookup` * Release 0.8.0 on 2019-08-24 diff --git a/docs/Including.md b/docs/Including.md index afc1b71..0e9d34d 100644 --- a/docs/Including.md +++ b/docs/Including.md @@ -10,7 +10,7 @@ The core.cache releases and snapshots are stored in the following repositories: You can use core.cache in your [Leiningen](https://github.com/technomancy/leiningen) projects with the following `:dependencies` directive in your `project.clj` file: - [org.clojure/core.cache "0.8.1"] + [org.clojure/core.cache "0.8.2"] ## Maven @@ -19,7 +19,7 @@ For Maven-driven projects, use the following slice of XML in your `pom.xml`'s `< org.clojure core.cache - 0.8.1 + 0.8.2 Enjoy! diff --git a/src/main/clojure/clojure/core/cache/wrapped.clj b/src/main/clojure/clojure/core/cache/wrapped.clj index a05e190..cdef30b 100644 --- a/src/main/clojure/clojure/core/cache/wrapped.clj +++ b/src/main/clojure/clojure/core/cache/wrapped.clj @@ -90,7 +90,7 @@ Returns the updated cache from the atom. Provided for completeness." [cache-atom e ret] - (swap! cache-atom c/miss cache-atom e ret)) + (swap! cache-atom c/miss e ret)) (defn evict "Removes an entry from the cache. From 6d978fcafc1d1d8c98c9698bbe54153c8ce45636 Mon Sep 17 00:00:00 2001 From: "Hudson @ build.clojure.org" Date: Mon, 30 Sep 2019 18:00:17 -0500 Subject: [PATCH 081/145] [maven-release-plugin] prepare release core.cache-0.8.2 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 50de6b9..f0d2c57 100644 --- a/pom.xml +++ b/pom.xml @@ -2,14 +2,14 @@ 4.0.0 core.cache - 0.8.2-SNAPSHOT + 0.8.2 core.cache Cache library for Clojure. scm:git:git://github.com/clojure/core.cache.git scm:git:ssh://git@github.com/clojure/core.cache.git - HEAD + core.cache-0.8.2 https://github.com/clojure/core.cache From 5e23c641c06b04b4147c18dcd59f38052021e022 Mon Sep 17 00:00:00 2001 From: "Hudson @ build.clojure.org" Date: Mon, 30 Sep 2019 18:00:17 -0500 Subject: [PATCH 082/145] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index f0d2c57..332d834 100644 --- a/pom.xml +++ b/pom.xml @@ -2,14 +2,14 @@ 4.0.0 core.cache - 0.8.2 + 0.8.3-SNAPSHOT core.cache Cache library for Clojure. scm:git:git://github.com/clojure/core.cache.git scm:git:ssh://git@github.com/clojure/core.cache.git - core.cache-0.8.2 + HEAD https://github.com/clojure/core.cache From e222b2ef1401dcdeb5357398f1c9c0da1b5b939d Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Thu, 6 Feb 2020 08:44:34 -0800 Subject: [PATCH 083/145] Recommend approach for not caching certain results --- docs/Using.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/docs/Using.md b/docs/Using.md index 4fc8371..ceccb4f 100644 --- a/docs/Using.md +++ b/docs/Using.md @@ -48,6 +48,21 @@ Finally, to explicitly evict an element in a cache, use the `evict` function: For specific information about eviction policies and thresholds, view the specific documentation for each cache type listed in the next section. +Sometimes you may wish to cache a function except when it returns certain values, +such as a resource-loading function that may return `nil` if the resource is +(temporarily) unavailable. Because of the edge cases that can arise with doing +multiple lookups on a cache -- protections from which are baked into `through`, +`through-cache`, and `lookup-or-miss` -- it is better to write your code to +simply cache all results and then, post-retrieval, `evict` the key if the +result is something you don't want cached: + +```clojure +(let [result (wrapped/lookup-or-miss C :c load-my-resource)] + (when (nil? result) + (wrapped/evict C :c)) + result) +``` + ## Builtin cache implementations core.cache comes with a number of builtin immutable cache implementations, including (*click through for specific information*): From c04b61060f76a248c65951a8ab968992125346f8 Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Fri, 7 Feb 2020 09:34:50 -0800 Subject: [PATCH 084/145] Clarify cache exclusion example --- docs/Using.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/Using.md b/docs/Using.md index ceccb4f..725960a 100644 --- a/docs/Using.md +++ b/docs/Using.md @@ -58,7 +58,7 @@ result is something you don't want cached: ```clojure (let [result (wrapped/lookup-or-miss C :c load-my-resource)] - (when (nil? result) + (when (nil? result) ; or seq or whatever condition should exclude this result (wrapped/evict C :c)) result) ``` From 9e092f8ffec0fb6a8cbccd7e84e1578e5ed9afd2 Mon Sep 17 00:00:00 2001 From: Fogus Date: Tue, 18 Feb 2020 15:35:54 -0500 Subject: [PATCH 085/145] Removed comment, and bumped version in pom and README. --- README.md | 6 +++--- pom.xml | 2 +- src/main/clojure/clojure/core/cache.clj | 13 ------------- 3 files changed, 4 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index 2dffcab..bba4fa4 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ core.cache is based on an old library named Clache that has been thoroughly depr Releases and Dependency Information ======================================== -Latest stable release: 0.8.2 +Latest stable release: 1.0.0 * [All Released Versions](http://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22org.clojure%22%20AND%20a%3A%22core.cache%22) @@ -38,14 +38,14 @@ Latest stable release: 0.8.2 [Leiningen](https://github.com/technomancy/leiningen) dependency information: - [org.clojure/core.cache "0.8.2"] + [org.clojure/core.cache "1.0.0"] [Maven](http://maven.apache.org/) dependency information: org.clojure core.cache - 0.8.2 + 1.0.0 diff --git a/pom.xml b/pom.xml index 332d834..787b759 100644 --- a/pom.xml +++ b/pom.xml @@ -2,7 +2,7 @@ 4.0.0 core.cache - 0.8.3-SNAPSHOT + 1.0.0-SNAPSHOT core.cache Cache library for Clojure. diff --git a/src/main/clojure/clojure/core/cache.clj b/src/main/clojure/clojure/core/cache.clj index 8337ac0..294bbb9 100644 --- a/src/main/clojure/clojure/core/cache.clj +++ b/src/main/clojure/clojure/core/cache.clj @@ -660,16 +660,3 @@ (clojure.core.cache/seed (SoftCache. (ConcurrentHashMap.) (ConcurrentHashMap.) (ReferenceQueue.)) base)) -(comment - - (def C (-> {:a 1 :b 2} - (fifo-cache-factory :threshold 2) - (ttl-cache-factory :ttl 5000))) - - (assoc C :c 42) - ;;=> {:b 2, :c 42} - - ;; wait 5 seconds - - (assoc C :d 138)) - ;;=> {:d 138} From 4363fa0ffaad8973e844b8ebe3cc73282c984d45 Mon Sep 17 00:00:00 2001 From: Fogus Date: Tue, 18 Feb 2020 15:42:49 -0500 Subject: [PATCH 086/145] Adding 1.0.0 to Including.md --- docs/Including.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/Including.md b/docs/Including.md index 0e9d34d..364c127 100644 --- a/docs/Including.md +++ b/docs/Including.md @@ -10,7 +10,7 @@ The core.cache releases and snapshots are stored in the following repositories: You can use core.cache in your [Leiningen](https://github.com/technomancy/leiningen) projects with the following `:dependencies` directive in your `project.clj` file: - [org.clojure/core.cache "0.8.2"] + [org.clojure/core.cache "1.0.0"] ## Maven @@ -19,7 +19,7 @@ For Maven-driven projects, use the following slice of XML in your `pom.xml`'s `< org.clojure core.cache - 0.8.2 + 1.0.0 Enjoy! From cb8bcad2764db40e0f211a75b287b61b3c5041a8 Mon Sep 17 00:00:00 2001 From: Alex Miller Date: Tue, 18 Feb 2020 14:58:27 -0600 Subject: [PATCH 087/145] bump dep on data.priority-map to 1.0.0 --- README.md | 6 +++++- pom.xml | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 2dffcab..ab2a579 100644 --- a/README.md +++ b/README.md @@ -30,6 +30,8 @@ core.cache is based on an old library named Clache that has been thoroughly depr Releases and Dependency Information ======================================== +This project follows the version scheme MAJOR.MINOR.PATCH where each component provides some relative indication of the size of the change, but does not follow semantic versioning. In general, all changes endeavor to be non-breaking (by moving to new names rather than by breaking existing names). + Latest stable release: 0.8.2 * [All Released Versions](http://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22org.clojure%22%20AND%20a%3A%22core.cache%22) @@ -143,6 +145,8 @@ Developer Information Change Log ==================== +* next + * Update data.priority-map to 1.0.0 * Release 0.8.2 on 2019-09-30 * [CCACHE-57](http://clojure.atlassian.net/browse/CCACHE-57) Fix wrapped cache `miss` function * Release 0.8.1 on 2019-08-24 @@ -193,4 +197,4 @@ Change Log Copyright and License ======================================== -Copyright (c) Rich Hickey, Michael Fogus and contributors, 2012. All rights reserved. The use and distribution terms for this software are covered by the Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) which can be found in the file epl-v10.html at the root of this distribution. By using this software in any fashion, you are agreeing to be bound bythe terms of this license. You must not remove this notice, or any other, from this software. +Copyright (c) Rich Hickey, Michael Fogus and contributors, 2012-2020. All rights reserved. The use and distribution terms for this software are covered by the Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) which can be found in the file epl-v10.html at the root of this distribution. By using this software in any fashion, you are agreeing to be bound bythe terms of this license. You must not remove this notice, or any other, from this software. diff --git a/pom.xml b/pom.xml index 332d834..3ca56ee 100644 --- a/pom.xml +++ b/pom.xml @@ -43,7 +43,7 @@ org.clojure data.priority-map - 0.0.7 + 1.0.0 From 90b8720b529a273d5f317fd9805147f106472d33 Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Tue, 18 Feb 2020 19:49:39 -0800 Subject: [PATCH 088/145] Bump deps.edn version dependencies `data.priority-map` and `test.check` are 1.0.0 now. Corrected 1.10 alias to 1.10.1 version. Updated test-runner to latest SHA. --- deps.edn | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/deps.edn b/deps.edn index 2f1cae0..eeaa9a3 100644 --- a/deps.edn +++ b/deps.edn @@ -3,19 +3,19 @@ ;; against: :1.6 :1.7 :1.8 :1.9 :1.10 :master {:paths ["src/main/clojure"] - :deps {org.clojure/data.priority-map {:mvn/version "0.0.7"}} + :deps {org.clojure/data.priority-map {:mvn/version "1.0.0"}} :aliases {:test {:extra-paths ["src/test/clojure"] - :extra-deps {org.clojure/test.check {:mvn/version "0.9.0"}}} + :extra-deps {org.clojure/test.check {:mvn/version "1.0.0"}}} :1.6 {:override-deps {org.clojure/clojure {:mvn/version "1.6.0"}}} :1.7 {:override-deps {org.clojure/clojure {:mvn/version "1.7.0"}}} :1.8 {:override-deps {org.clojure/clojure {:mvn/version "1.8.0"}}} :1.9 {:override-deps {org.clojure/clojure {:mvn/version "1.9.0"}}} - :1.10 {:override-deps {org.clojure/clojure {:mvn/version "1.10.0"}}} + :1.10 {:override-deps {org.clojure/clojure {:mvn/version "1.10.1"}}} :master {:override-deps {org.clojure/clojure {:mvn/version "1.11.0-master-SNAPSHOT"}}} :runner {:extra-deps {com.cognitect/test-runner {:git/url "https://github.com/cognitect-labs/test-runner" - :sha "76568540e7f40268ad2b646110f237a60295fa3c"}} + :sha "f7ef16dc3b8332b0d77bc0274578ad5270fbfedd"}} :main-opts ["-m" "cognitect.test-runner" "-d" "src/test/clojure"]}}} From dd08b79f15bfe2606ddc3169d8ea3608504d1403 Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Tue, 18 Feb 2020 21:26:22 -0800 Subject: [PATCH 089/145] Update parent pom etc --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 3ca56ee..734367a 100644 --- a/pom.xml +++ b/pom.xml @@ -24,7 +24,7 @@ org.clojure pom.contrib - 0.2.2 + 1.0.0 From b4c7dbefbdcbdd6550fce264d76b7f5e7c56fa32 Mon Sep 17 00:00:00 2001 From: Fogus Date: Wed, 19 Feb 2020 08:44:39 -0500 Subject: [PATCH 090/145] Adding dep for priority-map 1.0.0 --- deps.edn | 2 +- pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/deps.edn b/deps.edn index 2f1cae0..cf22fa6 100644 --- a/deps.edn +++ b/deps.edn @@ -3,7 +3,7 @@ ;; against: :1.6 :1.7 :1.8 :1.9 :1.10 :master {:paths ["src/main/clojure"] - :deps {org.clojure/data.priority-map {:mvn/version "0.0.7"}} + :deps {org.clojure/data.priority-map {:mvn/version "1.0.0"}} :aliases {:test {:extra-paths ["src/test/clojure"] :extra-deps {org.clojure/test.check {:mvn/version "0.9.0"}}} diff --git a/pom.xml b/pom.xml index 787b759..cd21b91 100644 --- a/pom.xml +++ b/pom.xml @@ -43,7 +43,7 @@ org.clojure data.priority-map - 0.0.7 + 1.0.0 From 3d2c7d9303a9c1e4651adb2f2667409d49bcaedd Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Wed, 19 Feb 2020 10:11:06 -0800 Subject: [PATCH 091/145] Back parent pom off to 0.3.0 for now --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 734367a..cd2f159 100644 --- a/pom.xml +++ b/pom.xml @@ -24,7 +24,7 @@ org.clojure pom.contrib - 1.0.0 + 0.3.0 From 8b4bdb57ba3c69f580c9d59112627ed7f85f8a7b Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Thu, 9 Apr 2020 16:31:20 -0700 Subject: [PATCH 092/145] Prep for 1.0.207 release --- README.md | 13 +++++++------ docs/Including.md | 4 ++-- pom.xml | 2 +- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 3aaa0f8..9b7e014 100644 --- a/README.md +++ b/README.md @@ -30,9 +30,9 @@ core.cache is based on an old library named Clache that has been thoroughly depr Releases and Dependency Information ======================================== -This project follows the version scheme MAJOR.MINOR.PATCH where each component provides some relative indication of the size of the change, but does not follow semantic versioning. In general, all changes endeavor to be non-breaking (by moving to new names rather than by breaking existing names). +This project follows the version scheme MAJOR.MINOR.COMMITS where MAJOR and MINOR provide some relative indication of the size of the change, but do not follow semantic versioning. In general, all changes endeavor to be non-breaking (by moving to new names rather than by breaking existing names). COMMITS is an ever-increasing counter of commits since the beginning of this repository. -Latest stable release: 1.0.0 +Latest stable release: 1.0.207 * [All Released Versions](http://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22org.clojure%22%20AND%20a%3A%22core.cache%22) @@ -40,14 +40,14 @@ Latest stable release: 1.0.0 [Leiningen](https://github.com/technomancy/leiningen) dependency information: - [org.clojure/core.cache "1.0.0"] + [org.clojure/core.cache "1.0.207"] [Maven](http://maven.apache.org/) dependency information: org.clojure core.cache - 1.0.0 + 1.0.207 @@ -145,8 +145,9 @@ Developer Information Change Log ==================== -* Release 1.0.0 on 2020-03-11 - * Update data.priority-map to 1.0.0 +* Release 1.0.207 on 2020-04-10 + * Switch to 1.0.x versioning. + * Update `data.priority-map` to 1.0.0 * Release 0.8.2 on 2019-09-30 * [CCACHE-57](http://clojure.atlassian.net/browse/CCACHE-57) Fix wrapped cache `miss` function * Release 0.8.1 on 2019-08-24 diff --git a/docs/Including.md b/docs/Including.md index 364c127..068c6fd 100644 --- a/docs/Including.md +++ b/docs/Including.md @@ -10,7 +10,7 @@ The core.cache releases and snapshots are stored in the following repositories: You can use core.cache in your [Leiningen](https://github.com/technomancy/leiningen) projects with the following `:dependencies` directive in your `project.clj` file: - [org.clojure/core.cache "1.0.0"] + [org.clojure/core.cache "1.0.207"] ## Maven @@ -19,7 +19,7 @@ For Maven-driven projects, use the following slice of XML in your `pom.xml`'s `< org.clojure core.cache - 1.0.0 + 1.0.207 Enjoy! diff --git a/pom.xml b/pom.xml index 0051615..1d4b92f 100644 --- a/pom.xml +++ b/pom.xml @@ -24,7 +24,7 @@ org.clojure pom.contrib - 0.3.0 + 1.0.0 From d674ba6151cef457e793984fb896799c67df808c Mon Sep 17 00:00:00 2001 From: "Hudson @ build.clojure.org" Date: Fri, 10 Apr 2020 15:48:16 -0500 Subject: [PATCH 093/145] [maven-release-plugin] prepare release core.cache-1.0.207 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 1d4b92f..9813787 100644 --- a/pom.xml +++ b/pom.xml @@ -2,14 +2,14 @@ 4.0.0 core.cache - 1.0.0-SNAPSHOT + 1.0.207 core.cache Cache library for Clojure. scm:git:git://github.com/clojure/core.cache.git scm:git:ssh://git@github.com/clojure/core.cache.git - HEAD + core.cache-1.0.207 https://github.com/clojure/core.cache From 5a015d224deda8dd89077f4d62480d1aebbdefa1 Mon Sep 17 00:00:00 2001 From: "Hudson @ build.clojure.org" Date: Fri, 10 Apr 2020 15:48:16 -0500 Subject: [PATCH 094/145] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 9813787..e1267af 100644 --- a/pom.xml +++ b/pom.xml @@ -2,14 +2,14 @@ 4.0.0 core.cache - 1.0.207 + 1.0.208-SNAPSHOT core.cache Cache library for Clojure. scm:git:git://github.com/clojure/core.cache.git scm:git:ssh://git@github.com/clojure/core.cache.git - core.cache-1.0.207 + HEAD https://github.com/clojure/core.cache From abc4953337836b45ed61e321be1c175ee57968f7 Mon Sep 17 00:00:00 2001 From: Alex Miller Date: Thu, 18 Jun 2020 12:57:17 -0500 Subject: [PATCH 095/145] add license file format --- LICENSE | 205 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 205 insertions(+) create mode 100644 LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..e246f6a --- /dev/null +++ b/LICENSE @@ -0,0 +1,205 @@ +Eclipse Public License - v 1.0 + +THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE PUBLIC +LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM +CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. + +1. DEFINITIONS + +"Contribution" means: + +a) in the case of the initial Contributor, the initial code and documentation + distributed under this Agreement, and +b) in the case of each subsequent Contributor: + i) changes to the Program, and + ii) additions to the Program; + + where such changes and/or additions to the Program originate from and are + distributed by that particular Contributor. A Contribution 'originates' + from a Contributor if it was added to the Program by such Contributor + itself or anyone acting on such Contributor's behalf. Contributions do not + include additions to the Program which: (i) are separate modules of + software distributed in conjunction with the Program under their own + license agreement, and (ii) are not derivative works of the Program. + +"Contributor" means any person or entity that distributes the Program. + +"Licensed Patents" mean patent claims licensable by a Contributor which are +necessarily infringed by the use or sale of its Contribution alone or when +combined with the Program. + +"Program" means the Contributions distributed in accordance with this +Agreement. + +"Recipient" means anyone who receives the Program under this Agreement, +including all Contributors. + +2. GRANT OF RIGHTS + a) Subject to the terms of this Agreement, each Contributor hereby grants + Recipient a non-exclusive, worldwide, royalty-free copyright license to + reproduce, prepare derivative works of, publicly display, publicly + perform, distribute and sublicense the Contribution of such Contributor, + if any, and such derivative works, in source code and object code form. + b) Subject to the terms of this Agreement, each Contributor hereby grants + Recipient a non-exclusive, worldwide, royalty-free patent license under + Licensed Patents to make, use, sell, offer to sell, import and otherwise + transfer the Contribution of such Contributor, if any, in source code and + object code form. This patent license shall apply to the combination of + the Contribution and the Program if, at the time the Contribution is + added by the Contributor, such addition of the Contribution causes such + combination to be covered by the Licensed Patents. The patent license + shall not apply to any other combinations which include the Contribution. + No hardware per se is licensed hereunder. + c) Recipient understands that although each Contributor grants the licenses + to its Contributions set forth herein, no assurances are provided by any + Contributor that the Program does not infringe the patent or other + intellectual property rights of any other entity. Each Contributor + disclaims any liability to Recipient for claims brought by any other + entity based on infringement of intellectual property rights or + otherwise. As a condition to exercising the rights and licenses granted + hereunder, each Recipient hereby assumes sole responsibility to secure + any other intellectual property rights needed, if any. For example, if a + third party patent license is required to allow Recipient to distribute + the Program, it is Recipient's responsibility to acquire that license + before distributing the Program. + d) Each Contributor represents that to its knowledge it has sufficient + copyright rights in its Contribution, if any, to grant the copyright + license set forth in this Agreement. + +3. REQUIREMENTS + +A Contributor may choose to distribute the Program in object code form under +its own license agreement, provided that: + + a) it complies with the terms and conditions of this Agreement; and + b) its license agreement: + i) effectively disclaims on behalf of all Contributors all warranties + and conditions, express and implied, including warranties or + conditions of title and non-infringement, and implied warranties or + conditions of merchantability and fitness for a particular purpose; + ii) effectively excludes on behalf of all Contributors all liability for + damages, including direct, indirect, special, incidental and + consequential damages, such as lost profits; + iii) states that any provisions which differ from this Agreement are + offered by that Contributor alone and not by any other party; and + iv) states that source code for the Program is available from such + Contributor, and informs licensees how to obtain it in a reasonable + manner on or through a medium customarily used for software exchange. + +When the Program is made available in source code form: + + a) it must be made available under this Agreement; and + b) a copy of this Agreement must be included with each copy of the Program. + Contributors may not remove or alter any copyright notices contained + within the Program. + +Each Contributor must identify itself as the originator of its Contribution, +if +any, in a manner that reasonably allows subsequent Recipients to identify the +originator of the Contribution. + +4. COMMERCIAL DISTRIBUTION + +Commercial distributors of software may accept certain responsibilities with +respect to end users, business partners and the like. While this license is +intended to facilitate the commercial use of the Program, the Contributor who +includes the Program in a commercial product offering should do so in a manner +which does not create potential liability for other Contributors. Therefore, +if a Contributor includes the Program in a commercial product offering, such +Contributor ("Commercial Contributor") hereby agrees to defend and indemnify +every other Contributor ("Indemnified Contributor") against any losses, +damages and costs (collectively "Losses") arising from claims, lawsuits and +other legal actions brought by a third party against the Indemnified +Contributor to the extent caused by the acts or omissions of such Commercial +Contributor in connection with its distribution of the Program in a commercial +product offering. The obligations in this section do not apply to any claims +or Losses relating to any actual or alleged intellectual property +infringement. In order to qualify, an Indemnified Contributor must: +a) promptly notify the Commercial Contributor in writing of such claim, and +b) allow the Commercial Contributor to control, and cooperate with the +Commercial Contributor in, the defense and any related settlement +negotiations. The Indemnified Contributor may participate in any such claim at +its own expense. + +For example, a Contributor might include the Program in a commercial product +offering, Product X. That Contributor is then a Commercial Contributor. If +that Commercial Contributor then makes performance claims, or offers +warranties related to Product X, those performance claims and warranties are +such Commercial Contributor's responsibility alone. Under this section, the +Commercial Contributor would have to defend claims against the other +Contributors related to those performance claims and warranties, and if a +court requires any other Contributor to pay any damages as a result, the +Commercial Contributor must pay those damages. + +5. NO WARRANTY + +EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN +"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR +IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, +NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each +Recipient is solely responsible for determining the appropriateness of using +and distributing the Program and assumes all risks associated with its +exercise of rights under this Agreement , including but not limited to the +risks and costs of program errors, compliance with applicable laws, damage to +or loss of data, programs or equipment, and unavailability or interruption of +operations. + +6. DISCLAIMER OF LIABILITY + +EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY +CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION +LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE +EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGES. + +7. GENERAL + +If any provision of this Agreement is invalid or unenforceable under +applicable law, it shall not affect the validity or enforceability of the +remainder of the terms of this Agreement, and without further action by the +parties hereto, such provision shall be reformed to the minimum extent +necessary to make such provision valid and enforceable. + +If Recipient institutes patent litigation against any entity (including a +cross-claim or counterclaim in a lawsuit) alleging that the Program itself +(excluding combinations of the Program with other software or hardware) +infringes such Recipient's patent(s), then such Recipient's rights granted +under Section 2(b) shall terminate as of the date such litigation is filed. + +All Recipient's rights under this Agreement shall terminate if it fails to +comply with any of the material terms or conditions of this Agreement and does +not cure such failure in a reasonable period of time after becoming aware of +such noncompliance. If all Recipient's rights under this Agreement terminate, +Recipient agrees to cease use and distribution of the Program as soon as +reasonably practicable. However, Recipient's obligations under this Agreement +and any licenses granted by Recipient relating to the Program shall continue +and survive. + +Everyone is permitted to copy and distribute copies of this Agreement, but in +order to avoid inconsistency the Agreement is copyrighted and may only be +modified in the following manner. The Agreement Steward reserves the right to +publish new versions (including revisions) of this Agreement from time to +time. No one other than the Agreement Steward has the right to modify this +Agreement. The Eclipse Foundation is the initial Agreement Steward. The +Eclipse Foundation may assign the responsibility to serve as the Agreement +Steward to a suitable separate entity. Each new version of the Agreement will +be given a distinguishing version number. The Program (including +Contributions) may always be distributed subject to the version of the +Agreement under which it was received. In addition, after a new version of the +Agreement is published, Contributor may elect to distribute the Program +(including its Contributions) under the new version. Except as expressly +stated in Sections 2(a) and 2(b) above, Recipient receives no rights or +licenses to the intellectual property of any Contributor under this Agreement, +whether expressly, by implication, estoppel or otherwise. All rights in the +Program not expressly granted under this Agreement are reserved. + +This Agreement is governed by the laws of the State of New York and the +intellectual property laws of the United States of America. No party to this +Agreement will bring a legal action under this Agreement more than one year +after the cause of action arose. Each party waives its rights to a jury trial in +any resulting litigation. + + From 847951c8714a0124f53dab4821d89012df428909 Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Sun, 19 Jul 2020 18:54:31 -0700 Subject: [PATCH 096/145] Link to Dan Sutton's article about the pitfalls of the API. --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 9b7e014..e132279 100644 --- a/README.md +++ b/README.md @@ -26,6 +26,7 @@ The `clojure.core.cache.wrapped` namespace contains the same API operating on ca core.cache is based on an old library named Clache that has been thoroughly deprecated. +The `core.cache` API is hard to use correctly. That's why `clojure.core.cache.wrapped/lookup-or-miss` exists: it encapsulates all the best practices around using the API _and_ wraps it in an `atom` from the get-go. Read this article about [the `core.cache` API](https://dev.to/dpsutton/exploring-the-core-cache-api-57al) by Dan Sutton for why it is important to use the API correctly! Releases and Dependency Information ======================================== From 1fef90f5b61ceef07b859a46abd3be77af922282 Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Tue, 1 Sep 2020 13:30:41 -0700 Subject: [PATCH 097/145] Add CLI/deps.edn dependency information --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index e132279..81024ed 100644 --- a/README.md +++ b/README.md @@ -39,6 +39,12 @@ Latest stable release: 1.0.207 * [Development Snapshot Versions](https://oss.sonatype.org/index.html#nexus-search;gav~org.clojure~core.cache~~~) +[CLI/`deps.edn`](https://clojure.org/reference/deps_and_cli) dependency information: + +```clojure +org.clojure/core.cache {:mvn/version "1.0.207"} +``` + [Leiningen](https://github.com/technomancy/leiningen) dependency information: [org.clojure/core.cache "1.0.207"] From ee699021b984df182359648312042b79d05cc506 Mon Sep 17 00:00:00 2001 From: Alex Miller Date: Wed, 24 Feb 2021 14:06:40 -0600 Subject: [PATCH 098/145] update old links --- README.md | 2 +- docs/release-notes/release-0.6.1.markdown | 2 +- docs/release-notes/release-0.6.2.markdown | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 81024ed..668c607 100644 --- a/README.md +++ b/README.md @@ -133,7 +133,7 @@ Example Usage ;=> {:a 1, :d 13, :b 42} ``` -Refer to docstrings in the `clojure.core.cache` or `clojure.core.cache.wrapped` namespaces, or the [autogenerated API documentation](http://clojure.github.com/core.cache/) for additional documentation. +Refer to docstrings in the `clojure.core.cache` or `clojure.core.cache.wrapped` namespaces, or the [autogenerated API documentation](http://clojure.github.io/core.cache/) for additional documentation. Developer Information diff --git a/docs/release-notes/release-0.6.1.markdown b/docs/release-notes/release-0.6.1.markdown index f5fadd5..14cd378 100644 --- a/docs/release-notes/release-0.6.1.markdown +++ b/docs/release-notes/release-0.6.1.markdown @@ -43,7 +43,7 @@ Places * [Source code](https://github.com/clojure/core.cache) * [Ticket system](http://clojure.atlassian.net/browse/CCACHE) * [Announcement](http://groups.google.com/group/clojure/browse_frm/thread/69d08572ab265dc7) -* [API Reference](https://clojure.github.com/core.cache) +* [API Reference](https://clojure.github.io/core.cache) * [Examples and documentation](https://github.com/clojure/core.cache/wiki) (work in progress) Changes from v0.5.0 diff --git a/docs/release-notes/release-0.6.2.markdown b/docs/release-notes/release-0.6.2.markdown index c2729e5..7835912 100644 --- a/docs/release-notes/release-0.6.2.markdown +++ b/docs/release-notes/release-0.6.2.markdown @@ -43,7 +43,7 @@ Places * [Source code](https://github.com/clojure/core.cache) * [Ticket system](http://clojure.atlassian.net/browse/CCACHE) * [Announcement](http://groups.google.com/group/clojure/browse_frm/thread/69d08572ab265dc7) -* [API Reference](https://clojure.github.com/core.cache) +* [API Reference](https://clojure.github.io/core.cache) * [Examples and documentation](https://github.com/clojure/core.cache/wiki) (work in progress) Changes from v0.6.1 @@ -72,4 +72,4 @@ The following capabilities are under design, development, or consideration for f * Deprecation of Clache * More documentation and examples -More planning is needed around capabilities not listed nor thought of. \ No newline at end of file +More planning is needed around capabilities not listed nor thought of. From b89b7545a38710d6ca08179c7d16550b608936c3 Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Thu, 15 Apr 2021 15:37:49 -0700 Subject: [PATCH 099/145] Update parent pom to 1.1.0 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index e1267af..c785643 100644 --- a/pom.xml +++ b/pom.xml @@ -24,7 +24,7 @@ org.clojure pom.contrib - 1.0.0 + 1.1.0 From 9038e65b5d0d2c256c68740007e29ef115ac3ec6 Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Sun, 25 Jul 2021 22:27:51 -0700 Subject: [PATCH 100/145] fix typo in docstring --- .gitignore | 14 +++++++++----- src/main/clojure/clojure/core/cache.clj | 7 +++---- src/main/clojure/clojure/core/cache/wrapped.clj | 6 +++--- 3 files changed, 15 insertions(+), 12 deletions(-) diff --git a/.gitignore b/.gitignore index 4bae240..42793f1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,12 @@ -target +.classpath +.cpcache/ +.idea .lein* -lib -multi-lib +.lsp/sqlite.db .nrepl-port -.idea -.cpcache/ +.project +.settings /build.boot +lib +multi-lib +target diff --git a/src/main/clojure/clojure/core/cache.clj b/src/main/clojure/clojure/core/cache.clj index 294bbb9..287a67d 100644 --- a/src/main/clojure/clojure/core/cache.clj +++ b/src/main/clojure/clojure/core/cache.clj @@ -579,7 +579,7 @@ ;; Factories (defn basic-cache-factory - "Returns a pluggable basic cache initialied to `base`" + "Returns a pluggable basic cache initialized to `base`" [base] {:pre [(map? base)]} (BasicCache. base)) @@ -606,7 +606,7 @@ (clojure.core.cache/seed (FIFOCache. {} clojure.lang.PersistentQueue/EMPTY threshold) base)) (defn lru-cache-factory - "Returns an LRU cache with the cache and usage-table initialied to `base` -- + "Returns an LRU cache with the cache and usage-table initialized to `base` -- each entry is initialized with the same usage value. This function takes an optional `:threshold` argument that defines the maximum number @@ -628,7 +628,7 @@ (clojure.core.cache/seed (TTLCacheQ. {} {} clojure.lang.PersistentQueue/EMPTY 0 ttl) base)) (defn lu-cache-factory - "Returns an LU cache with the cache and usage-table initialied to `base`. + "Returns an LU cache with the cache and usage-table initialized to `base`. This function takes an optional `:threshold` argument that defines the maximum number of elements in the cache before the LU semantics apply (default is 32)." @@ -659,4 +659,3 @@ {:pre [(map? base)]} (clojure.core.cache/seed (SoftCache. (ConcurrentHashMap.) (ConcurrentHashMap.) (ReferenceQueue.)) base)) - diff --git a/src/main/clojure/clojure/core/cache/wrapped.clj b/src/main/clojure/clojure/core/cache/wrapped.clj index cdef30b..6e55b17 100644 --- a/src/main/clojure/clojure/core/cache/wrapped.clj +++ b/src/main/clojure/clojure/core/cache/wrapped.clj @@ -128,7 +128,7 @@ (swap! cache-atom c/through-cache item wrap-fn value-fn))) (defn basic-cache-factory - "Returns a pluggable basic cache initialied to `base`" + "Returns a pluggable basic cache initialized to `base`" [base] (atom (c/basic-cache-factory base))) @@ -151,7 +151,7 @@ (atom (c/fifo-cache-factory base :threshold threshold))) (defn lru-cache-factory - "Returns an LRU cache with the cache and usage-table initialied to `base` -- + "Returns an LRU cache with the cache and usage-table initialized to `base` -- each entry is initialized with the same usage value. This function takes an optional `:threshold` argument that defines the maximum number @@ -169,7 +169,7 @@ (atom (c/ttl-cache-factory base :ttl ttl))) (defn lu-cache-factory - "Returns an LU cache with the cache and usage-table initialied to `base`. + "Returns an LU cache with the cache and usage-table initialized to `base`. This function takes an optional `:threshold` argument that defines the maximum number of elements in the cache before the LU semantics apply (default is 32)." From 430cf69a3e8a5ce00112e3534f0c06c70d5638d8 Mon Sep 17 00:00:00 2001 From: FiV0 Date: Wed, 28 Jul 2021 16:28:58 +0200 Subject: [PATCH 101/145] CCACHE-63 Improve LRU/LU cache initialization when base is small Also fix LU miss logic when the cache is not full. Signed-off-by: Fogus --- src/main/clojure/clojure/core/cache.clj | 13 +++++-------- src/test/clojure/clojure/core/cache_test.clj | 9 ++++++++- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/src/main/clojure/clojure/core/cache.clj b/src/main/clojure/clojure/core/cache.clj index 287a67d..7800345 100644 --- a/src/main/clojure/clojure/core/cache.clj +++ b/src/main/clojure/clojure/core/cache.clj @@ -205,11 +205,8 @@ (str cache \, \space (pr-str q)))) (defn- build-leastness-queue - [base limit start-at] - (into (clojure.data.priority-map/priority-map) - (concat (take (- limit (count base)) (for [k (range (- limit) 0)] [k k])) - (for [[k _] base] [k start-at])))) - + [base start-at] + (into (clojure.data.priority-map/priority-map) (for [[k _] base] [k start-at]))) (defcache LRUCache [cache lru tick limit] CacheProtocol @@ -249,7 +246,7 @@ this)) (seed [_ base] (LRUCache. base - (build-leastness-queue base limit 0) + (build-leastness-queue base 0) 0 limit)) Object @@ -332,7 +329,7 @@ l (-> lu (dissoc min-key) (update-in [item] (fnil inc 0)))] (LUCache. c l limit)) (LUCache. (assoc cache item result) ;; no change case - (assoc lu item 0) + (update-in lu [item] (fnil inc 0)) limit))) (evict [this key] (if (contains? this key) @@ -342,7 +339,7 @@ this)) (seed [_ base] (LUCache. base - (build-leastness-queue base limit 0) + (build-leastness-queue base 0) limit)) Object (toString [_] diff --git a/src/test/clojure/clojure/core/cache_test.clj b/src/test/clojure/clojure/core/cache_test.clj index 39c0ba4..a67f614 100644 --- a/src/test/clojure/clojure/core/cache_test.clj +++ b/src/test/clojure/clojure/core/cache_test.clj @@ -276,7 +276,7 @@ {:a 1, :b 2, :c 3, :d 4} (-> C (assoc :c 3) (assoc :d 4) .cache) {:a 1, :c 3, :d 4, :e 5} (-> C (assoc :c 3) (assoc :d 4) (.hit :a) (assoc :e 5) .cache) {:b 2, :c 3, :d 4, :e 5} (-> C (assoc :c 3) (assoc :d 4) (.hit :b) (.hit :c) (.hit :d) (assoc :e 5) .cache)))) - (testing "regressions against LRU eviction before threshold met" + (testing "regressions against LU eviction before threshold met" (is (= (-> (clojure.core.cache/lu-cache-factory {} :threshold 2) (assoc :a 1) (assoc :b 2) @@ -301,6 +301,13 @@ (assoc :a 1) (assoc :b 2) (assoc :b 3) + .cache))) + + (is (= {:c 3 :d 4} + (-> (clojure.core.cache/lu-cache-factory {:a 1 :b 2} :threshold 2) + (dissoc :a) + (assoc :c 3) + (assoc :d 4) .cache))))) ;; # LIRS From b8356d4672360e8011914ca78e1e520cb0c0b491 Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Mon, 2 Aug 2021 19:31:25 -0700 Subject: [PATCH 102/145] prep for 1.0.217 --- README.md | 10 ++++++---- docs/Including.md | 4 ++-- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 668c607..93fd5cf 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ Releases and Dependency Information This project follows the version scheme MAJOR.MINOR.COMMITS where MAJOR and MINOR provide some relative indication of the size of the change, but do not follow semantic versioning. In general, all changes endeavor to be non-breaking (by moving to new names rather than by breaking existing names). COMMITS is an ever-increasing counter of commits since the beginning of this repository. -Latest stable release: 1.0.207 +Latest stable release: 1.0.217 * [All Released Versions](http://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22org.clojure%22%20AND%20a%3A%22core.cache%22) @@ -42,19 +42,19 @@ Latest stable release: 1.0.207 [CLI/`deps.edn`](https://clojure.org/reference/deps_and_cli) dependency information: ```clojure -org.clojure/core.cache {:mvn/version "1.0.207"} +org.clojure/core.cache {:mvn/version "1.0.217"} ``` [Leiningen](https://github.com/technomancy/leiningen) dependency information: - [org.clojure/core.cache "1.0.207"] + [org.clojure/core.cache "1.0.217"] [Maven](http://maven.apache.org/) dependency information: org.clojure core.cache - 1.0.207 + 1.0.217 @@ -152,6 +152,8 @@ Developer Information Change Log ==================== +* Release 1.0.217 on 2021-08-02 + * [CCACHE-63](http://clojure.atlassian.net/browse/CCACHE-63) Improve cache initialization for LU/LRU; fix LU miss logic when not full. * Release 1.0.207 on 2020-04-10 * Switch to 1.0.x versioning. * Update `data.priority-map` to 1.0.0 diff --git a/docs/Including.md b/docs/Including.md index 068c6fd..e1f1db4 100644 --- a/docs/Including.md +++ b/docs/Including.md @@ -10,7 +10,7 @@ The core.cache releases and snapshots are stored in the following repositories: You can use core.cache in your [Leiningen](https://github.com/technomancy/leiningen) projects with the following `:dependencies` directive in your `project.clj` file: - [org.clojure/core.cache "1.0.207"] + [org.clojure/core.cache "1.0.217"] ## Maven @@ -19,7 +19,7 @@ For Maven-driven projects, use the following slice of XML in your `pom.xml`'s `< org.clojure core.cache - 1.0.207 + 1.0.217 Enjoy! From e8df0ab7e95dd47f66a67975917a6af5cf24767c Mon Sep 17 00:00:00 2001 From: "Hudson @ build.clojure.org" Date: Mon, 2 Aug 2021 21:32:51 -0500 Subject: [PATCH 103/145] [maven-release-plugin] prepare release v1.0.217 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index c785643..636491f 100644 --- a/pom.xml +++ b/pom.xml @@ -2,14 +2,14 @@ 4.0.0 core.cache - 1.0.208-SNAPSHOT + 1.0.217 core.cache Cache library for Clojure. scm:git:git://github.com/clojure/core.cache.git scm:git:ssh://git@github.com/clojure/core.cache.git - HEAD + v1.0.217 https://github.com/clojure/core.cache From ad24d8d0f9463e12f4ac57eb579af6f3e10ceaf6 Mon Sep 17 00:00:00 2001 From: "Hudson @ build.clojure.org" Date: Mon, 2 Aug 2021 21:32:51 -0500 Subject: [PATCH 104/145] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 636491f..1d6f160 100644 --- a/pom.xml +++ b/pom.xml @@ -2,14 +2,14 @@ 4.0.0 core.cache - 1.0.217 + 1.0.218-SNAPSHOT core.cache Cache library for Clojure. scm:git:git://github.com/clojure/core.cache.git scm:git:ssh://git@github.com/clojure/core.cache.git - v1.0.217 + HEAD https://github.com/clojure/core.cache From f2eaf7efa31718763008ff66bfaac55c2d62e90c Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Mon, 2 Aug 2021 19:53:21 -0700 Subject: [PATCH 105/145] clean up deps test setup --- deps.edn | 20 ++++++++------------ run-tests.sh | 5 +++-- 2 files changed, 11 insertions(+), 14 deletions(-) diff --git a/deps.edn b/deps.edn index eeaa9a3..6b8efb6 100644 --- a/deps.edn +++ b/deps.edn @@ -1,21 +1,17 @@ ;; You can run clojure.core.cache tests with: clj -A:test:runner ;; You can also specify an alias to select which version of Clojure to test -;; against: :1.6 :1.7 :1.8 :1.9 :1.10 :master +;; against: :1.8 :1.9 :1.10 :master {:paths ["src/main/clojure"] :deps {org.clojure/data.priority-map {:mvn/version "1.0.0"}} - :aliases {:test - {:extra-paths ["src/test/clojure"] - :extra-deps {org.clojure/test.check {:mvn/version "1.0.0"}}} - :1.6 {:override-deps {org.clojure/clojure {:mvn/version "1.6.0"}}} - :1.7 {:override-deps {org.clojure/clojure {:mvn/version "1.7.0"}}} - :1.8 {:override-deps {org.clojure/clojure {:mvn/version "1.8.0"}}} + :aliases {:1.8 {:override-deps {org.clojure/clojure {:mvn/version "1.8.0"}}} :1.9 {:override-deps {org.clojure/clojure {:mvn/version "1.9.0"}}} - :1.10 {:override-deps {org.clojure/clojure {:mvn/version "1.10.1"}}} + :1.10 {:override-deps {org.clojure/clojure {:mvn/version "1.10.3"}}} :master {:override-deps {org.clojure/clojure {:mvn/version "1.11.0-master-SNAPSHOT"}}} - :runner - {:extra-deps {com.cognitect/test-runner - {:git/url "https://github.com/cognitect-labs/test-runner" - :sha "f7ef16dc3b8332b0d77bc0274578ad5270fbfedd"}} + :test + {:extra-paths ["src/test/clojure"] + :extra-deps {org.clojure/test.check {:mvn/version "1.0.0"} + io.github.cognitect-labs/test-runner + {:git/tag "v0.4.0" :git/sha "334f2e2"}} :main-opts ["-m" "cognitect.test-runner" "-d" "src/test/clojure"]}}} diff --git a/run-tests.sh b/run-tests.sh index d0674d4..b4481c6 100755 --- a/run-tests.sh +++ b/run-tests.sh @@ -1,7 +1,8 @@ #!/bin/sh -versions="1.6 1.7 1.8 1.9 1.10 master" +versions="1.8 1.9 1.10 master" for v in $versions do - time clj -A:test:runner:$v + time clojure -M:test:$v + if test $? != 0; then exit 1; fi done From 63aeed08302e2b2c81faf59adade4ead82c87969 Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Mon, 2 Aug 2021 19:55:48 -0700 Subject: [PATCH 106/145] gitignore tweak --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 42793f1..6985f92 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,7 @@ .nrepl-port .project .settings +.vscode /build.boot lib multi-lib From f8c1fa93d05334e6a622816ce85b30a5190c7cb4 Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Thu, 7 Oct 2021 15:48:02 -0700 Subject: [PATCH 107/145] fix CCACHE-64 --- docs/LRU.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/docs/LRU.md b/docs/LRU.md index 1c60f6f..f301ece 100644 --- a/docs/LRU.md +++ b/docs/LRU.md @@ -1,7 +1,7 @@ LRU cache ========== -The least-recently-used cache is one that evicts items that are accessed least frequently once its threshold has been exceeded. +The least-recently-used cache is one that evicts items that are accessed least recently once its threshold has been exceeded. > In simple terms, the LRU cache will remove the element in the cache that has not been accessed in the longest time. @@ -13,11 +13,11 @@ General usage To create a core.cache `LRUCache` instance you should *always* use its associated constructor function `lru-cache-factory` with an optional `:threshold` parameter: ```clojure - (ns your.lib + (ns your.lib (:require [clojure.core.cache :as cache])) - + (def C (cache/lru-cache-factory {} :threshold 2)) - + (-> C (assoc :a 1) (assoc :b 2)) ;=> {:a 1, :b 2} ``` @@ -34,11 +34,11 @@ At this point the cache has not yet crossed the set threshold of `2`, but if you At this point the operation of the LRU cache looks exactly the same at the FIFO cache. However, the difference becomes apparent when a given cache item is "touched": ```clojure - (-> C (assoc :a 1) - (assoc :b 2) + (-> C (assoc :a 1) + (assoc :b 2) (.hit :a) ;; ensure :a is used most recently (assoc :c 3)) - + ;=> {:a 1, :c 3} ``` @@ -67,5 +67,5 @@ There are a few reasons why you might want to use a LRU cache: * Tends to perform poorly when elements files are accessed occasionally but consistently while other elements are accessed very frequently for a short duration and never accessed again * It requires more historical data to operate * It requires a larger cache to increase efficiency - + As always, you should measure your system's characteristics to determine the best eviction strategy for your purposes. From 2333f68d182d7c407cfd2261543d6c66979b6c36 Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Thu, 7 Oct 2021 15:48:10 -0700 Subject: [PATCH 108/145] ignore kondo/lsp --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 6985f92..3c00365 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,9 @@ .classpath +.clj-kondo/.cache .cpcache/ .idea .lein* -.lsp/sqlite.db +.lsp/.cache .nrepl-port .project .settings From 99bac1992214f71fb8549c4c7d4f720b588a88d1 Mon Sep 17 00:00:00 2001 From: Alex Miller Date: Mon, 6 Dec 2021 13:17:57 -0600 Subject: [PATCH 109/145] update data.priority-map to 1.1.0 --- README.md | 2 ++ deps.edn | 2 +- pom.xml | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 93fd5cf..a78c9b3 100644 --- a/README.md +++ b/README.md @@ -152,6 +152,8 @@ Developer Information Change Log ==================== +* next + * Update `data.priority-map` to 1.1.0 * Release 1.0.217 on 2021-08-02 * [CCACHE-63](http://clojure.atlassian.net/browse/CCACHE-63) Improve cache initialization for LU/LRU; fix LU miss logic when not full. * Release 1.0.207 on 2020-04-10 diff --git a/deps.edn b/deps.edn index 6b8efb6..749b935 100644 --- a/deps.edn +++ b/deps.edn @@ -3,7 +3,7 @@ ;; against: :1.8 :1.9 :1.10 :master {:paths ["src/main/clojure"] - :deps {org.clojure/data.priority-map {:mvn/version "1.0.0"}} + :deps {org.clojure/data.priority-map {:mvn/version "1.1.0"}} :aliases {:1.8 {:override-deps {org.clojure/clojure {:mvn/version "1.8.0"}}} :1.9 {:override-deps {org.clojure/clojure {:mvn/version "1.9.0"}}} :1.10 {:override-deps {org.clojure/clojure {:mvn/version "1.10.3"}}} diff --git a/pom.xml b/pom.xml index 1d6f160..dba70dd 100644 --- a/pom.xml +++ b/pom.xml @@ -43,7 +43,7 @@ org.clojure data.priority-map - 1.0.0 + 1.1.0 From b9b3192fd7beda68a06af7de4b6d4c2a54515094 Mon Sep 17 00:00:00 2001 From: "Hudson @ build.clojure.org" Date: Mon, 6 Dec 2021 13:20:49 -0600 Subject: [PATCH 110/145] [maven-release-plugin] prepare release v1.0.225 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index dba70dd..60bfb06 100644 --- a/pom.xml +++ b/pom.xml @@ -2,14 +2,14 @@ 4.0.0 core.cache - 1.0.218-SNAPSHOT + 1.0.225 core.cache Cache library for Clojure. scm:git:git://github.com/clojure/core.cache.git scm:git:ssh://git@github.com/clojure/core.cache.git - HEAD + v1.0.225 https://github.com/clojure/core.cache From d26970d04fff520d9ca7b0819f479aaf5921fbb9 Mon Sep 17 00:00:00 2001 From: "Hudson @ build.clojure.org" Date: Mon, 6 Dec 2021 13:20:49 -0600 Subject: [PATCH 111/145] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 60bfb06..ee13163 100644 --- a/pom.xml +++ b/pom.xml @@ -2,14 +2,14 @@ 4.0.0 core.cache - 1.0.225 + 1.0.226-SNAPSHOT core.cache Cache library for Clojure. scm:git:git://github.com/clojure/core.cache.git scm:git:ssh://git@github.com/clojure/core.cache.git - v1.0.225 + HEAD https://github.com/clojure/core.cache From baeec4d51439a5430bcaafe0b7ab83848c5844f9 Mon Sep 17 00:00:00 2001 From: Alex Miller Date: Mon, 6 Dec 2021 13:23:55 -0600 Subject: [PATCH 112/145] update for release --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index a78c9b3..964ed16 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ Releases and Dependency Information This project follows the version scheme MAJOR.MINOR.COMMITS where MAJOR and MINOR provide some relative indication of the size of the change, but do not follow semantic versioning. In general, all changes endeavor to be non-breaking (by moving to new names rather than by breaking existing names). COMMITS is an ever-increasing counter of commits since the beginning of this repository. -Latest stable release: 1.0.217 +Latest stable release: 1.0.225 * [All Released Versions](http://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22org.clojure%22%20AND%20a%3A%22core.cache%22) @@ -42,19 +42,19 @@ Latest stable release: 1.0.217 [CLI/`deps.edn`](https://clojure.org/reference/deps_and_cli) dependency information: ```clojure -org.clojure/core.cache {:mvn/version "1.0.217"} +org.clojure/core.cache {:mvn/version "1.0.225"} ``` [Leiningen](https://github.com/technomancy/leiningen) dependency information: - [org.clojure/core.cache "1.0.217"] + [org.clojure/core.cache "1.0.225"] [Maven](http://maven.apache.org/) dependency information: org.clojure core.cache - 1.0.217 + 1.0.225 @@ -152,7 +152,7 @@ Developer Information Change Log ==================== -* next +* Release 1.0.225 on 2021-12-06 * Update `data.priority-map` to 1.1.0 * Release 1.0.217 on 2021-08-02 * [CCACHE-63](http://clojure.atlassian.net/browse/CCACHE-63) Improve cache initialization for LU/LRU; fix LU miss logic when not full. From 442652a562368ae01d490c1d65bd38e80e8cb907 Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Sat, 11 Feb 2023 17:12:11 -0800 Subject: [PATCH 113/145] try to clarify usage of the two namespaces per https://ask.clojure.org/index.php/12517/docs-for-core-cache-documentation-are-ambigous --- .gitignore | 1 + README.md | 33 +++++++++++++++++++++++++++------ docs/Composing.md | 4 ++-- docs/README.md | 2 ++ docs/Using.md | 2 ++ 5 files changed, 34 insertions(+), 8 deletions(-) diff --git a/.gitignore b/.gitignore index 3c00365..640e299 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ .lein* .lsp/.cache .nrepl-port +.portal/vs-code.edn .project .settings .vscode diff --git a/README.md b/README.md index 964ed16..667d009 100644 --- a/README.md +++ b/README.md @@ -62,9 +62,26 @@ org.clojure/core.cache {:mvn/version "1.0.225"} Example Usage ======================================== +The [`clojure.core.cache` namespace](https://cljdoc.org/d/org.clojure/core.cache/CURRENT/api/clojure.core.cache) +provides an API for immutable caches where +it is expected that you would manage storage of these data structures. + +The [`clojure.core.cache.wrapped` namespace](https://cljdoc.org/d/org.clojure/core.cache/CURRENT/api/clojure.core.cache.wrapped) +provides the same API but over +immutable caches already wrapped in an atom, which is generally a more +intuitive API for straightforward use cases. In particular, this namespace +adds a `lookup-or-miss` function which encapsulates the `has?`/`hit`/`miss` +logic for the underlying cache as well as edge cases such as `lookup` +returning `nil` if a cache item expires on fetch (e.g., TTL), and guaranteeing +the value computing function is only called at most once. + +The expectation is that you use _either_ `clojure.core.cache` _or_ +`clojure.core.cache.wrapped` and you do not try to mix them. + ```clojure (require '[clojure.core.cache :as cache]) + ;; C1 is an immutable cache: (def C1 (cache/fifo-cache-factory {:a 1, :b 2})) (def C1' (if (cache/has? C1 :c) @@ -107,24 +124,28 @@ Example Usage ;=> 1 ;; or use the wrapped API instead: - (require '[clojure.core.cache.wrapped :as c]) + (require '[clojure.core.cache.wrapped :as w]) - (def C3 (c/fifo-cache-factory {:a 1, :b 2})) + ;; in this case C3 is an atom containing a cache: + (def C3 (w/fifo-cache-factory {:a 1, :b 2})) - (c/through-cache C3 :d (constantly 13)) ; returns updated cache + ;; operations modify the atom and return the updated cache: + (w/through-cache C3 :d (constantly 13)) ;=> {:a 1, :b 3, :d 13} - (c/evict C3 :b) + ;; modifies the atom and returns the updated cache: + (w/evict C3 :b) ;=> {:a 1, :d 13} - (c/lookup C3 :a) ; or (get @C3 :a) + ;; for some caches this is a mutating operation (e.g., TTL): + (w/lookup C3 :a) ; or (get @C3 :a) ;=> 1 ;; unique to the wrapped API: - (c/lookup-or-miss C3 :b (constantly 42)) + (w/lookup-or-miss C3 :b (constantly 42)) ;=> 42 diff --git a/docs/Composing.md b/docs/Composing.md index ac6cd3c..98bbe65 100644 --- a/docs/Composing.md +++ b/docs/Composing.md @@ -10,9 +10,9 @@ Put in simpler terms, to create a cache instance composed of the seed data `{:a ;; used right away (assoc C :c 42) -;;=> {:b 2, :c 42} +;;=> {:b 2, :c 42} -;; used after 5 seconds +;; used after 5 seconds (assoc C :d 138) ;;=> {:d 138} diff --git a/docs/README.md b/docs/README.md index 31b80c3..1f81d19 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,6 +1,8 @@ core.cache ========== +> Note: the documentation here is for the `clojure.core.cache` namespace. See also the documentation for the [`clojure.core.cache.wrapped` namespace](https://cljdoc.org/d/org.clojure/core.cache/CURRENT/api/clojure.core.cache.wrapped) on cljdoc.org. + ## Table of Topics * Overview (this page) diff --git a/docs/Using.md b/docs/Using.md index 725960a..2c56f10 100644 --- a/docs/Using.md +++ b/docs/Using.md @@ -1,3 +1,5 @@ +> Note: the documentation here is for the `clojure.core.cache` namespace. See also the documentation for the [`clojure.core.cache.wrapped` namespace](https://cljdoc.org/d/org.clojure/core.cache/CURRENT/api/clojure.core.cache.wrapped) on cljdoc.org. + # Using core.cache *note: see the page on [including core.cache](./Including.md) before you begin this section* From 38476660d77861f0867c3b1d3543346832fad2e7 Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Fri, 17 Mar 2023 21:25:33 -0700 Subject: [PATCH 114/145] clarify lookup-or-miss usage --- README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 667d009..149d1fb 100644 --- a/README.md +++ b/README.md @@ -144,8 +144,12 @@ The expectation is that you use _either_ `clojure.core.cache` _or_ ;=> 1 - ;; unique to the wrapped API: + ;; unique to the wrapped API, this combines through-cache and lookup + ;; to return the looked up value, possibly after calling the passed in + ;; function with the key to populate the cache if the key wasn't present: (w/lookup-or-miss C3 :b (constantly 42)) + ;; calls (jdbc/get-by-id :storage my-key) in the event of a cache miss: + (w/lookup-or-miss C3 my-key (partial jdbc/get-by-id db-spec :storage)) ;=> 42 From 803d1c0b060ac0ad14c0cae6e6bcefa8c907199b Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Fri, 17 Mar 2023 21:27:37 -0700 Subject: [PATCH 115/145] move JDBC example after showing C3 contents --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 149d1fb..15fc7c7 100644 --- a/README.md +++ b/README.md @@ -148,14 +148,15 @@ The expectation is that you use _either_ `clojure.core.cache` _or_ ;; to return the looked up value, possibly after calling the passed in ;; function with the key to populate the cache if the key wasn't present: (w/lookup-or-miss C3 :b (constantly 42)) - ;; calls (jdbc/get-by-id :storage my-key) in the event of a cache miss: - (w/lookup-or-miss C3 my-key (partial jdbc/get-by-id db-spec :storage)) ;=> 42 @C3 ;=> {:a 1, :d 13, :b 42} + + ;; calls (jdbc/get-by-id :storage my-key) in the event of a cache miss: + (w/lookup-or-miss C3 my-key (partial jdbc/get-by-id db-spec :storage)) ``` Refer to docstrings in the `clojure.core.cache` or `clojure.core.cache.wrapped` namespaces, or the [autogenerated API documentation](http://clojure.github.io/core.cache/) for additional documentation. From 55ce9869f6cee00d2b277d728640630e0c54050f Mon Sep 17 00:00:00 2001 From: Alex Miller Date: Fri, 26 May 2023 14:57:50 -0500 Subject: [PATCH 116/145] add actions --- .github/workflows/release.yml | 19 +++++++++++++++++++ .github/workflows/snapshot.yml | 8 ++++++++ .github/workflows/test.yml | 7 +++++++ README.md | 10 +++------- 4 files changed, 37 insertions(+), 7 deletions(-) create mode 100644 .github/workflows/release.yml create mode 100644 .github/workflows/snapshot.yml create mode 100644 .github/workflows/test.yml diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..e2718bd --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,19 @@ +name: Release on demand + +on: + workflow_dispatch: + inputs: + releaseVersion: + description: "Version to release" + required: true + snapshotVersion: + description: "Snapshot version after release" + required: true + +jobs: + call-release: + uses: clojure/build.ci/.github/workflows/release.yml@master + with: + releaseVersion: ${{ github.event.inputs.releaseVersion }} + snapshotVersion: ${{ github.event.inputs.snapshotVersion }} + secrets: inherit \ No newline at end of file diff --git a/.github/workflows/snapshot.yml b/.github/workflows/snapshot.yml new file mode 100644 index 0000000..2472957 --- /dev/null +++ b/.github/workflows/snapshot.yml @@ -0,0 +1,8 @@ +name: Snapshot on demand + +on: [workflow_dispatch] + +jobs: + call-snapshot: + uses: clojure/build.ci/.github/workflows/snapshot.yml@master + secrets: inherit diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..1fa127c --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,7 @@ +name: Test + +on: [push] + +jobs: + call-test: + uses: clojure/build.ci/.github/workflows/test.yml@master diff --git a/README.md b/README.md index 15fc7c7..d7e7944 100644 --- a/README.md +++ b/README.md @@ -166,12 +166,8 @@ Developer Information ======================================== * [GitHub project](https://github.com/clojure/core.cache) - -* [Bug Tracker](http://clojure.atlassian.net/browse/CCACHE) - -* [Continuous Integration](http://build.clojure.org/job/core.cache/) - -* [Compatibility Test Matrix](http://build.clojure.org/job/core.cache-test-matrix/) +* [Bug Tracker](https://clojure.atlassian.net/browse/CCACHE) +* [Continuous Integration](https://github.com/clojure/core.cache/actions/workflows/test.yml) @@ -235,4 +231,4 @@ Change Log Copyright and License ======================================== -Copyright (c) Rich Hickey, Michael Fogus and contributors, 2012-2020. All rights reserved. The use and distribution terms for this software are covered by the Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) which can be found in the file epl-v10.html at the root of this distribution. By using this software in any fashion, you are agreeing to be bound bythe terms of this license. You must not remove this notice, or any other, from this software. +Copyright (c) Rich Hickey, Michael Fogus and contributors, 2012-2023. All rights reserved. The use and distribution terms for this software are covered by the Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) which can be found in the file epl-v10.html at the root of this distribution. By using this software in any fashion, you are agreeing to be bound bythe terms of this license. You must not remove this notice, or any other, from this software. From 070c893b12622b9f7ace487468873a508a39254b Mon Sep 17 00:00:00 2001 From: JarrodCTaylor Date: Wed, 16 Aug 2023 09:24:00 -0500 Subject: [PATCH 117/145] Added github action to build api docs --- .github/workflows/doc-build.yml | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 .github/workflows/doc-build.yml diff --git a/.github/workflows/doc-build.yml b/.github/workflows/doc-build.yml new file mode 100644 index 0000000..2f2995a --- /dev/null +++ b/.github/workflows/doc-build.yml @@ -0,0 +1,10 @@ +name: Build API Docs + +on: + workflow_dispatch: + +jobs: + call-doc-build-workflow: + uses: clojure/build.ci/.github/workflows/doc-build.yml@master + with: + project: clojure/core.cache From 632b65a95c92d1091c4d6999dd75de520c09e662 Mon Sep 17 00:00:00 2001 From: Alex Miller Date: Mon, 19 Feb 2024 13:42:51 -0600 Subject: [PATCH 118/145] update parent pom and dep versions --- deps.edn | 4 ++-- pom.xml | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/deps.edn b/deps.edn index 749b935..f6d0676 100644 --- a/deps.edn +++ b/deps.edn @@ -3,14 +3,14 @@ ;; against: :1.8 :1.9 :1.10 :master {:paths ["src/main/clojure"] - :deps {org.clojure/data.priority-map {:mvn/version "1.1.0"}} + :deps {org.clojure/data.priority-map {:mvn/version "1.2.0"}} :aliases {:1.8 {:override-deps {org.clojure/clojure {:mvn/version "1.8.0"}}} :1.9 {:override-deps {org.clojure/clojure {:mvn/version "1.9.0"}}} :1.10 {:override-deps {org.clojure/clojure {:mvn/version "1.10.3"}}} :master {:override-deps {org.clojure/clojure {:mvn/version "1.11.0-master-SNAPSHOT"}}} :test {:extra-paths ["src/test/clojure"] - :extra-deps {org.clojure/test.check {:mvn/version "1.0.0"} + :extra-deps {org.clojure/test.check {:mvn/version "1.1.1"} io.github.cognitect-labs/test-runner {:git/tag "v0.4.0" :git/sha "334f2e2"}} :main-opts ["-m" "cognitect.test-runner" diff --git a/pom.xml b/pom.xml index ee13163..86c8276 100644 --- a/pom.xml +++ b/pom.xml @@ -16,7 +16,7 @@ Eclipse Public License 1.0 - http://opensource.org/licenses/eclipse-1.0.php + https://opensource.org/license/epl-1-0/ repo @@ -24,26 +24,26 @@ org.clojure pom.contrib - 1.1.0 + 1.2.0 fogus Michael Fogus - http://www.fogus.me + https://www.fogus.me - 1.6.0 + 1.9.0 org.clojure data.priority-map - 1.1.0 + 1.2.0 From dab8bc6f9ef7e5e67947ace0e68238fc2e1dba01 Mon Sep 17 00:00:00 2001 From: clojure-build Date: Mon, 19 Feb 2024 19:47:26 +0000 Subject: [PATCH 119/145] [maven-release-plugin] prepare release v1.1.234 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 86c8276..7e8a5e4 100644 --- a/pom.xml +++ b/pom.xml @@ -2,14 +2,14 @@ 4.0.0 core.cache - 1.0.226-SNAPSHOT + 1.1.234 core.cache Cache library for Clojure. scm:git:git://github.com/clojure/core.cache.git scm:git:ssh://git@github.com/clojure/core.cache.git - HEAD + v1.1.234 https://github.com/clojure/core.cache From b142cf2ecd10f46f9dd85ace7b3506f6542003a4 Mon Sep 17 00:00:00 2001 From: clojure-build Date: Mon, 19 Feb 2024 19:47:26 +0000 Subject: [PATCH 120/145] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 7e8a5e4..3b4f2a7 100644 --- a/pom.xml +++ b/pom.xml @@ -2,14 +2,14 @@ 4.0.0 core.cache - 1.1.234 + 1.2.0-SNAPSHOT core.cache Cache library for Clojure. scm:git:git://github.com/clojure/core.cache.git scm:git:ssh://git@github.com/clojure/core.cache.git - v1.1.234 + HEAD https://github.com/clojure/core.cache From 99fbd669a429bc800ff32b64b21cf82b6b486f06 Mon Sep 17 00:00:00 2001 From: Alex Miller Date: Mon, 10 Jun 2024 08:38:30 -0500 Subject: [PATCH 121/145] update for release --- README.md | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index d7e7944..228dc8b 100644 --- a/README.md +++ b/README.md @@ -33,28 +33,27 @@ Releases and Dependency Information This project follows the version scheme MAJOR.MINOR.COMMITS where MAJOR and MINOR provide some relative indication of the size of the change, but do not follow semantic versioning. In general, all changes endeavor to be non-breaking (by moving to new names rather than by breaking existing names). COMMITS is an ever-increasing counter of commits since the beginning of this repository. -Latest stable release: 1.0.225 - -* [All Released Versions](http://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22org.clojure%22%20AND%20a%3A%22core.cache%22) +Latest stable release: 1.1.234 +* [All Released Versions](https://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22org.clojure%22%20AND%20a%3A%22core.cache%22) * [Development Snapshot Versions](https://oss.sonatype.org/index.html#nexus-search;gav~org.clojure~core.cache~~~) -[CLI/`deps.edn`](https://clojure.org/reference/deps_and_cli) dependency information: +[CLI/`deps.edn`](https://clojure.org/reference/deps_edn) dependency information: ```clojure -org.clojure/core.cache {:mvn/version "1.0.225"} +org.clojure/core.cache {:mvn/version "1.1.234"} ``` [Leiningen](https://github.com/technomancy/leiningen) dependency information: - [org.clojure/core.cache "1.0.225"] + [org.clojure/core.cache "1.1.234"] [Maven](http://maven.apache.org/) dependency information: org.clojure core.cache - 1.0.225 + 1.1.234 @@ -174,6 +173,8 @@ Developer Information Change Log ==================== +* Release 1.1.234 on 2024-02-19 + * Update parent pom and `data.priority-map` versions * Release 1.0.225 on 2021-12-06 * Update `data.priority-map` to 1.1.0 * Release 1.0.217 on 2021-08-02 From fb4ef581f1aa4eb287dd432dafada46553ffadaf Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Mon, 5 Aug 2024 12:20:44 -0700 Subject: [PATCH 122/145] Clarify "at most once" guarantee is per-invocation of lookup-or-miss --- src/main/clojure/clojure/core/cache/wrapped.clj | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/clojure/clojure/core/cache/wrapped.clj b/src/main/clojure/clojure/core/cache/wrapped.clj index 6e55b17..3b825aa 100644 --- a/src/main/clojure/clojure/core/cache/wrapped.clj +++ b/src/main/clojure/clojure/core/cache/wrapped.clj @@ -40,6 +40,7 @@ value (using value-fn, and optionally wrap-fn), update the cache for `e` and then perform the lookup again. + For any given invocation of lookup-or-miss, it is guaranteed that value-fn (and wrap-fn) will only be called (at most) once even in the case of retries, so there is no risk of cache stampede. From afe95655321722fe7898dc8615926e922da0b610 Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Fri, 4 Oct 2024 15:42:56 -0700 Subject: [PATCH 123/145] update run-tess.sh/deps.edn to match ci multi-version tests Signed-off-by: Sean Corfield --- .calva/repl.calva-repl | 16 ++++++++++++++++ deps.edn | 10 +++++----- run-tests.sh | 2 +- 3 files changed, 22 insertions(+), 6 deletions(-) create mode 100644 .calva/repl.calva-repl diff --git a/.calva/repl.calva-repl b/.calva/repl.calva-repl new file mode 100644 index 0000000..65a3689 --- /dev/null +++ b/.calva/repl.calva-repl @@ -0,0 +1,16 @@ +; This is the Calva REPL Window. +; It's just a file, really, with some special treatment from Calva. +; Use it as a REPL input prompt if you like. (When the REPL is connected.) +; TIPS: The keyboard shortcut `ctrl+alt+o r` shows and focuses this window +; Please see https://calva.io/repl-window/ for more info. +; Happy coding! ♥️ + +; TIPS: As with any Clojure file when the REPL is connected: +; - `alt+enter` evaluates the current top level form. +; - `ctrl+enter` evaluates the current form. +; Special for this file: +; - `alt+up` and `alt+down` traverse up and down the REPL command history +; when the cursor is after the last contents at the prompt +; +; See also the Calva Inspector: https://calva.io/inspector/ +clj꞉user꞉>  diff --git a/deps.edn b/deps.edn index f6d0676..55ceeff 100644 --- a/deps.edn +++ b/deps.edn @@ -1,17 +1,17 @@ ;; You can run clojure.core.cache tests with: clj -A:test:runner ;; You can also specify an alias to select which version of Clojure to test -;; against: :1.8 :1.9 :1.10 :master +;; against: :1.9 :1.10 :1.11 :1.12 {:paths ["src/main/clojure"] :deps {org.clojure/data.priority-map {:mvn/version "1.2.0"}} - :aliases {:1.8 {:override-deps {org.clojure/clojure {:mvn/version "1.8.0"}}} - :1.9 {:override-deps {org.clojure/clojure {:mvn/version "1.9.0"}}} + :aliases {:1.9 {:override-deps {org.clojure/clojure {:mvn/version "1.9.0"}}} :1.10 {:override-deps {org.clojure/clojure {:mvn/version "1.10.3"}}} - :master {:override-deps {org.clojure/clojure {:mvn/version "1.11.0-master-SNAPSHOT"}}} + :1.11 {:override-deps {org.clojure/clojure {:mvn/version "1.11.4"}}} + :1.12 {:override-deps {org.clojure/clojure {:mvn/version "1.12.0"}}} :test {:extra-paths ["src/test/clojure"] :extra-deps {org.clojure/test.check {:mvn/version "1.1.1"} io.github.cognitect-labs/test-runner - {:git/tag "v0.4.0" :git/sha "334f2e2"}} + {:git/tag "v0.5.1" :git/sha "dfb30dd"}} :main-opts ["-m" "cognitect.test-runner" "-d" "src/test/clojure"]}}} diff --git a/run-tests.sh b/run-tests.sh index b4481c6..8d255fb 100755 --- a/run-tests.sh +++ b/run-tests.sh @@ -1,6 +1,6 @@ #!/bin/sh -versions="1.8 1.9 1.10 master" +versions="1.9 1.10 1.11 1.12" for v in $versions do time clojure -M:test:$v From e0e958c5ea734fe38fbb66fb42306452270e4ad8 Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Fri, 4 Oct 2024 15:50:18 -0700 Subject: [PATCH 124/145] remove calva repl file (oops) Signed-off-by: Sean Corfield --- .calva/repl.calva-repl | 16 ---------------- 1 file changed, 16 deletions(-) delete mode 100644 .calva/repl.calva-repl diff --git a/.calva/repl.calva-repl b/.calva/repl.calva-repl deleted file mode 100644 index 65a3689..0000000 --- a/.calva/repl.calva-repl +++ /dev/null @@ -1,16 +0,0 @@ -; This is the Calva REPL Window. -; It's just a file, really, with some special treatment from Calva. -; Use it as a REPL input prompt if you like. (When the REPL is connected.) -; TIPS: The keyboard shortcut `ctrl+alt+o r` shows and focuses this window -; Please see https://calva.io/repl-window/ for more info. -; Happy coding! ♥️ - -; TIPS: As with any Clojure file when the REPL is connected: -; - `alt+enter` evaluates the current top level form. -; - `ctrl+enter` evaluates the current form. -; Special for this file: -; - `alt+up` and `alt+down` traverse up and down the REPL command history -; when the cursor is after the last contents at the prompt -; -; See also the Calva Inspector: https://calva.io/inspector/ -clj꞉user꞉>  From a587ba0165924c22ffb3e1014110f79c7d5f3e37 Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Fri, 4 Oct 2024 15:51:04 -0700 Subject: [PATCH 125/145] ignore calva repl file Signed-off-by: Sean Corfield --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 640e299..831a568 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,4 @@ lib multi-lib target +.calva/repl.calva-repl From c15b60d09f417636b4e9239fbb421ef8ba4feb6f Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Fri, 8 Nov 2024 22:58:28 -0800 Subject: [PATCH 126/145] CCACHE-65 potential fix for cache stampede Signed-off-by: Sean Corfield --- .clj-kondo/config.edn | 1 + README.md | 2 ++ .../clojure/clojure/core/cache/wrapped.clj | 28 +++++++++---------- .../clojure/core/cache/wrapped_test.clj | 25 +++++++++++++++++ 4 files changed, 42 insertions(+), 14 deletions(-) create mode 100644 .clj-kondo/config.edn diff --git a/.clj-kondo/config.edn b/.clj-kondo/config.edn new file mode 100644 index 0000000..f40cd26 --- /dev/null +++ b/.clj-kondo/config.edn @@ -0,0 +1 @@ +{:lint-as {clojure.core.cache/defcache clojure.core/defrecord}} diff --git a/README.md b/README.md index 228dc8b..bf79cc7 100644 --- a/README.md +++ b/README.md @@ -173,6 +173,8 @@ Developer Information Change Log ==================== +* Release 1.2.next in progress + * [CCACHE-65](http://clojure.atlassian.net/browse/CCACHE-65) Use `delay` in `lookup-or-miss` to avoid cache-stampede. * Release 1.1.234 on 2024-02-19 * Update parent pom and `data.priority-map` versions * Release 1.0.225 on 2021-12-06 diff --git a/src/main/clojure/clojure/core/cache/wrapped.clj b/src/main/clojure/clojure/core/cache/wrapped.clj index 3b825aa..1aba3f9 100644 --- a/src/main/clojure/clojure/core/cache/wrapped.clj +++ b/src/main/clojure/clojure/core/cache/wrapped.clj @@ -29,9 +29,9 @@ Reads from the current version of the atom." ([cache-atom e] - (c/lookup @cache-atom e)) + (force (c/lookup @cache-atom e))) ([cache-atom e not-found] - (c/lookup @cache-atom e not-found))) + (force (c/lookup @cache-atom e not-found)))) (def ^{:private true} default-wrapper-fn #(%1 %2)) @@ -51,23 +51,23 @@ ([cache-atom e wrap-fn value-fn] (let [d-new-value (delay (wrap-fn value-fn e))] (loop [n 0 - v (c/lookup (swap! cache-atom - c/through-cache + v (force (c/lookup (swap! cache-atom + c/through-cache + e + default-wrapper-fn + (fn [_] d-new-value)) e - default-wrapper-fn - (fn [_] @d-new-value)) - e - ::expired)] + ::expired))] (when (< n 10) (if (= ::expired v) (recur (inc n) - (c/lookup (swap! cache-atom - c/through-cache + (force (c/lookup (swap! cache-atom + c/through-cache + e + default-wrapper-fn + (fn [_] d-new-value)) e - default-wrapper-fn - (fn [_] @d-new-value)) - e - ::expired)) + ::expired))) v)))))) (defn has? diff --git a/src/test/clojure/clojure/core/cache/wrapped_test.clj b/src/test/clojure/clojure/core/cache/wrapped_test.clj index 49deaa1..c9ca4e1 100644 --- a/src/test/clojure/clojure/core/cache/wrapped_test.clj +++ b/src/test/clojure/clojure/core/cache/wrapped_test.clj @@ -8,6 +8,7 @@ (ns clojure.core.cache.wrapped-test (:require [clojure.core.cache.wrapped :as c] + [clojure.core.cache :as cache] [clojure.test :refer [deftest is]])) (deftest basic-wrapped-test @@ -40,3 +41,27 @@ (recur (+ 1 n))))) (println "ttl test completed" limit "calls in" (- (System/currentTimeMillis) start) "ms"))) + +(deftest cache-stampede + (let [thread-count 100 + cache-atom (-> {} + (cache/ttl-cache-factory :ttl 120000) + (cache/lu-cache-factory :threshold 100) + (atom)) + latch (java.util.concurrent.CountDownLatch. thread-count) + invocations-counter (atom 0) + values (atom [])] + (dotimes [_ thread-count] + (.start (Thread. (fn [] + (swap! values conj + (c/lookup-or-miss cache-atom "my-key" + (fn [_] + (swap! invocations-counter inc) + (Thread/sleep 3000) + "some value"))) + (.countDown latch))))) + + (.await latch) + (is (= 1 (deref invocations-counter))) + (doseq [v @values] + (is (= "some value" v))))) From c7cd3e8e09bdf3b223b8fdb49c0db9339af8dee6 Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Fri, 8 Nov 2024 23:17:14 -0800 Subject: [PATCH 127/145] remove caveat about for any given invocation Signed-off-by: Sean Corfield --- src/main/clojure/clojure/core/cache/wrapped.clj | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/clojure/clojure/core/cache/wrapped.clj b/src/main/clojure/clojure/core/cache/wrapped.clj index 1aba3f9..5878224 100644 --- a/src/main/clojure/clojure/core/cache/wrapped.clj +++ b/src/main/clojure/clojure/core/cache/wrapped.clj @@ -40,7 +40,6 @@ value (using value-fn, and optionally wrap-fn), update the cache for `e` and then perform the lookup again. - For any given invocation of lookup-or-miss, it is guaranteed that value-fn (and wrap-fn) will only be called (at most) once even in the case of retries, so there is no risk of cache stampede. From a76f95314e406b01818972b26bf3aeab52f8caea Mon Sep 17 00:00:00 2001 From: Alex Miller Date: Fri, 30 May 2025 14:22:54 -0500 Subject: [PATCH 128/145] update to new parent pom --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 3b4f2a7..3fdb30c 100644 --- a/pom.xml +++ b/pom.xml @@ -24,7 +24,7 @@ org.clojure pom.contrib - 1.2.0 + 1.3.0 From 4a043644a0706b6d834ebf890a64d2fdcc9c388b Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Sun, 8 Jun 2025 21:34:43 -0400 Subject: [PATCH 129/145] note that supplied caches are in-memory Signed-off-by: Sean Corfield --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index bf79cc7..0dc8daf 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ core.cache is a Clojure contrib library providing the following features: * A `defcache` macro for hooking your `CacheProtocol` implementations into the Clojure associative data capabilities. -* Implementations of some basic caching strategies +* Implementations of some basic in-memory caching strategies - First-in-first-out (FIFOCache) - Least-recently-used (LRUCache) - Least-used (LUCache -- sometimes called Least Frequently Used) @@ -19,9 +19,9 @@ core.cache is a Clojure contrib library providing the following features: * Factory functions for each existing cache type -* Caches are generally immutable and should be used in conjunction with Clojure's state management, such as `atom`. SoftCache is the exception here, built on top of mutable Java collections, but it can be treated as an immutable cache as well. +* Caches are generally in-memory and immutable and should be used in conjunction with Clojure's state management, such as `atom`. SoftCache is the exception here, an in-memory cache built on top of mutable Java collections, but it can be treated as an immutable cache as well. -The `clojure.core.cache` namespace contains the immutable caches themselves. +The `clojure.core.cache` namespace contains the immutable in-memory caches themselves. The `clojure.core.cache.wrapped` namespace contains the same API operating on caches wrapped in atoms, which is the "normal" use in the wild (introduced in 0.8.0). core.cache is based on an old library named Clache that has been thoroughly deprecated. From 4805288a1f02c83fc6d88e7812f6046cb8215087 Mon Sep 17 00:00:00 2001 From: Alex Miller Date: Mon, 5 Jan 2026 14:23:43 -0600 Subject: [PATCH 130/145] update permissions in workflows --- .github/workflows/doc-build.yml | 3 +++ .github/workflows/release.yml | 3 +++ .github/workflows/snapshot.yml | 3 +++ .github/workflows/test.yml | 3 +++ 4 files changed, 12 insertions(+) diff --git a/.github/workflows/doc-build.yml b/.github/workflows/doc-build.yml index 2f2995a..65beb66 100644 --- a/.github/workflows/doc-build.yml +++ b/.github/workflows/doc-build.yml @@ -1,5 +1,8 @@ name: Build API Docs +permissions: + contents: write + on: workflow_dispatch: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index e2718bd..286cf95 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,5 +1,8 @@ name: Release on demand +permissions: + contents: write + on: workflow_dispatch: inputs: diff --git a/.github/workflows/snapshot.yml b/.github/workflows/snapshot.yml index 2472957..9fdad8c 100644 --- a/.github/workflows/snapshot.yml +++ b/.github/workflows/snapshot.yml @@ -1,5 +1,8 @@ name: Snapshot on demand +permissions: + contents: read + on: [workflow_dispatch] jobs: diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 1fa127c..2cc441a 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -1,5 +1,8 @@ name: Test +permissions: + contents: read + on: [push] jobs: From 7c42c977cbad00195789d429f930d47448e08b60 Mon Sep 17 00:00:00 2001 From: Alex Miller Date: Mon, 5 Jan 2026 14:25:29 -0600 Subject: [PATCH 131/145] update parent pom and contrib dep versions --- deps.edn | 6 +++--- pom.xml | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/deps.edn b/deps.edn index 55ceeff..5eb3590 100644 --- a/deps.edn +++ b/deps.edn @@ -3,14 +3,14 @@ ;; against: :1.9 :1.10 :1.11 :1.12 {:paths ["src/main/clojure"] - :deps {org.clojure/data.priority-map {:mvn/version "1.2.0"}} + :deps {org.clojure/data.priority-map {:mvn/version "1.2.1"}} :aliases {:1.9 {:override-deps {org.clojure/clojure {:mvn/version "1.9.0"}}} :1.10 {:override-deps {org.clojure/clojure {:mvn/version "1.10.3"}}} :1.11 {:override-deps {org.clojure/clojure {:mvn/version "1.11.4"}}} - :1.12 {:override-deps {org.clojure/clojure {:mvn/version "1.12.0"}}} + :1.12 {:override-deps {org.clojure/clojure {:mvn/version "1.12.4"}}} :test {:extra-paths ["src/test/clojure"] - :extra-deps {org.clojure/test.check {:mvn/version "1.1.1"} + :extra-deps {org.clojure/test.check {:mvn/version "1.1.3"} io.github.cognitect-labs/test-runner {:git/tag "v0.5.1" :git/sha "dfb30dd"}} :main-opts ["-m" "cognitect.test-runner" diff --git a/pom.xml b/pom.xml index 3fdb30c..a8821d3 100644 --- a/pom.xml +++ b/pom.xml @@ -24,7 +24,7 @@ org.clojure pom.contrib - 1.3.0 + 1.4.0 @@ -36,14 +36,14 @@ - 1.9.0 + 1.11.4 org.clojure data.priority-map - 1.2.0 + 1.2.1 From e57f6634ca92a65bb95fc39206634ddc0ee5ae42 Mon Sep 17 00:00:00 2001 From: clojure-build Date: Mon, 5 Jan 2026 20:58:52 +0000 Subject: [PATCH 132/145] [maven-release-plugin] prepare release v1.2.0 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index a8821d3..d1af342 100644 --- a/pom.xml +++ b/pom.xml @@ -2,14 +2,14 @@ 4.0.0 core.cache - 1.2.0-SNAPSHOT + 1.2.0 core.cache Cache library for Clojure. scm:git:git://github.com/clojure/core.cache.git scm:git:ssh://git@github.com/clojure/core.cache.git - HEAD + v1.2.0 https://github.com/clojure/core.cache From b5e1889236d57e450d32b95454e7984ea0664c91 Mon Sep 17 00:00:00 2001 From: clojure-build Date: Mon, 5 Jan 2026 20:58:52 +0000 Subject: [PATCH 133/145] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index d1af342..7a61820 100644 --- a/pom.xml +++ b/pom.xml @@ -2,14 +2,14 @@ 4.0.0 core.cache - 1.2.0 + 1.2.1-SNAPSHOT core.cache Cache library for Clojure. scm:git:git://github.com/clojure/core.cache.git scm:git:ssh://git@github.com/clojure/core.cache.git - v1.2.0 + HEAD https://github.com/clojure/core.cache From 7f1a9cf9d622f6317b92a76976fc53e1fb8aae36 Mon Sep 17 00:00:00 2001 From: clojure-build Date: Mon, 5 Jan 2026 22:46:41 +0000 Subject: [PATCH 134/145] [maven-release-plugin] prepare release v1.2.249 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 7a61820..6a51003 100644 --- a/pom.xml +++ b/pom.xml @@ -2,14 +2,14 @@ 4.0.0 core.cache - 1.2.1-SNAPSHOT + 1.2.249 core.cache Cache library for Clojure. scm:git:git://github.com/clojure/core.cache.git scm:git:ssh://git@github.com/clojure/core.cache.git - HEAD + v1.2.249 https://github.com/clojure/core.cache From 53a4701e905343f2a1119b3ae5c028919bf80b86 Mon Sep 17 00:00:00 2001 From: clojure-build Date: Mon, 5 Jan 2026 22:46:41 +0000 Subject: [PATCH 135/145] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 6a51003..e780eca 100644 --- a/pom.xml +++ b/pom.xml @@ -2,14 +2,14 @@ 4.0.0 core.cache - 1.2.249 + 1.2.250-SNAPSHOT core.cache Cache library for Clojure. scm:git:git://github.com/clojure/core.cache.git scm:git:ssh://git@github.com/clojure/core.cache.git - v1.2.249 + HEAD https://github.com/clojure/core.cache From f47487c6b72a01c34485e4df1549df761af6183f Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Thu, 12 Feb 2026 21:07:42 -0500 Subject: [PATCH 136/145] ignore calva mcp port Signed-off-by: Sean Corfield --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 831a568..fa951c1 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,4 @@ lib multi-lib target .calva/repl.calva-repl +.calva/mcp-server/port From 31592ef0794d00f725a6e47417c8397d8bebe9ac Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Sat, 21 Feb 2026 21:54:12 -0500 Subject: [PATCH 137/145] address CCACHE-67 by applying patch from dharrigan Signed-off-by: Sean Corfield --- README.md | 1 + src/main/clojure/clojure/core/cache/wrapped.clj | 15 +++++++++++++++ .../clojure/clojure/core/cache/wrapped_test.clj | 8 ++++++++ 3 files changed, 24 insertions(+) diff --git a/README.md b/README.md index 0dc8daf..2c6d517 100644 --- a/README.md +++ b/README.md @@ -174,6 +174,7 @@ Change Log ==================== * Release 1.2.next in progress + * [CCACHE-67](http://clojure.atlassian.net/browse/CCACHE-67) Add `clojure.core.cache.wrapped/size` function to get the size of the cache without dereferencing the atom. (via [@dharrigan](https://github.com/dharrigan)). * [CCACHE-65](http://clojure.atlassian.net/browse/CCACHE-65) Use `delay` in `lookup-or-miss` to avoid cache-stampede. * Release 1.1.234 on 2024-02-19 * Update parent pom and `data.priority-map` versions diff --git a/src/main/clojure/clojure/core/cache/wrapped.clj b/src/main/clojure/clojure/core/cache/wrapped.clj index 5878224..473d434 100644 --- a/src/main/clojure/clojure/core/cache/wrapped.clj +++ b/src/main/clojure/clojure/core/cache/wrapped.clj @@ -76,6 +76,21 @@ [cache-atom e] (c/has? @cache-atom e)) +(defn size + "Obtain the approximate size/count of the wrapped cache. + + The value returned is a point-in-time approximate count/size as the nature + of certain caches don't reflect their true size until a 'lookup-or-miss' + operation is invoked - such as the TTL cache. + + Whilst it is an approximate value, the returned result can be useful for + metric tracking or decision making. + + Returns an approximate count/size of the wrapped cache. + " + [cache-atom] + (count @cache-atom)) + (defn hit "Is meant to be called if the cache is determined to contain a value associated with `e`. diff --git a/src/test/clojure/clojure/core/cache/wrapped_test.clj b/src/test/clojure/clojure/core/cache/wrapped_test.clj index c9ca4e1..4c7e755 100644 --- a/src/test/clojure/clojure/core/cache/wrapped_test.clj +++ b/src/test/clojure/clojure/core/cache/wrapped_test.clj @@ -14,17 +14,25 @@ (deftest basic-wrapped-test (let [cache (c/basic-cache-factory {})] (is (= nil (c/lookup cache :a))) + ;; the size of the cache is zero + (is (= 0 (c/size cache))) (is (= ::missing (c/lookup cache :a ::missing))) ;; mutating operation (is (= 42 (c/lookup-or-miss cache :a (constantly 42)))) ;; cache now contains :a (is (= 42 (c/lookup cache :a))) + ;; and it now has a size of one + (is (= 1 (c/size cache))) ;; :a is present, does not call value-fn (is (= 42 (c/lookup-or-miss cache :a #(throw (ex-info "bad" {:key %}))))) ;; cache still contains :a as 42 (is (= 42 (c/lookup cache :a))) + ;; and it still has a size of one + (is (= 1 (c/size cache))) (c/evict cache :a) (is (= nil (c/lookup cache :a))) + ;; and the cache now has a size of zero + (is (= 0 (c/size cache))) (is (= ::missing (c/lookup cache :a ::missing))))) (deftest wrapped-ttl-test From 9310b18ca3dc73f1e5afbb26085cff77a959e741 Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Sat, 21 Feb 2026 21:59:41 -0500 Subject: [PATCH 138/145] prep for 1.2.254 Signed-off-by: Sean Corfield --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 2c6d517..d182c88 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ Releases and Dependency Information This project follows the version scheme MAJOR.MINOR.COMMITS where MAJOR and MINOR provide some relative indication of the size of the change, but do not follow semantic versioning. In general, all changes endeavor to be non-breaking (by moving to new names rather than by breaking existing names). COMMITS is an ever-increasing counter of commits since the beginning of this repository. -Latest stable release: 1.1.234 +Latest stable release: 1.2.254 * [All Released Versions](https://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22org.clojure%22%20AND%20a%3A%22core.cache%22) * [Development Snapshot Versions](https://oss.sonatype.org/index.html#nexus-search;gav~org.clojure~core.cache~~~) @@ -41,19 +41,19 @@ Latest stable release: 1.1.234 [CLI/`deps.edn`](https://clojure.org/reference/deps_edn) dependency information: ```clojure -org.clojure/core.cache {:mvn/version "1.1.234"} +org.clojure/core.cache {:mvn/version "1.2.254"} ``` [Leiningen](https://github.com/technomancy/leiningen) dependency information: - [org.clojure/core.cache "1.1.234"] + [org.clojure/core.cache "1.2.254"] [Maven](http://maven.apache.org/) dependency information: org.clojure core.cache - 1.1.234 + 1.2.254 @@ -173,7 +173,7 @@ Developer Information Change Log ==================== -* Release 1.2.next in progress +* Release 1.2.254 on 2026-02-21 * [CCACHE-67](http://clojure.atlassian.net/browse/CCACHE-67) Add `clojure.core.cache.wrapped/size` function to get the size of the cache without dereferencing the atom. (via [@dharrigan](https://github.com/dharrigan)). * [CCACHE-65](http://clojure.atlassian.net/browse/CCACHE-65) Use `delay` in `lookup-or-miss` to avoid cache-stampede. * Release 1.1.234 on 2024-02-19 From 82b792a9116cc5f5eef67b8f03ba83e2bbed2897 Mon Sep 17 00:00:00 2001 From: clojure-build Date: Sun, 22 Feb 2026 03:01:17 +0000 Subject: [PATCH 139/145] [maven-release-plugin] prepare release v1.2.254 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index e780eca..fde5595 100644 --- a/pom.xml +++ b/pom.xml @@ -2,14 +2,14 @@ 4.0.0 core.cache - 1.2.250-SNAPSHOT + 1.2.254 core.cache Cache library for Clojure. scm:git:git://github.com/clojure/core.cache.git scm:git:ssh://git@github.com/clojure/core.cache.git - HEAD + v1.2.254 https://github.com/clojure/core.cache From fd7fc11935b046b77d6164842afa1717de3fd38a Mon Sep 17 00:00:00 2001 From: clojure-build Date: Sun, 22 Feb 2026 03:01:17 +0000 Subject: [PATCH 140/145] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index fde5595..97042e4 100644 --- a/pom.xml +++ b/pom.xml @@ -2,14 +2,14 @@ 4.0.0 core.cache - 1.2.254 + 1.2.999-SNAPSHOT core.cache Cache library for Clojure. scm:git:git://github.com/clojure/core.cache.git scm:git:ssh://git@github.com/clojure/core.cache.git - v1.2.254 + HEAD https://github.com/clojure/core.cache From e14f4acd6db726c031af60c6d4d719452f9fc77e Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Mon, 23 Feb 2026 19:27:04 -0500 Subject: [PATCH 141/145] Another run at CCACHE-65 Signed-off-by: Sean Corfield --- .rebel_readline_history | 18 +++++ .../clojure/clojure/core/cache/wrapped.clj | 75 +++++++++++++------ .../clojure/core/cache/wrapped_test.clj | 67 +++++++++++++---- 3 files changed, 124 insertions(+), 36 deletions(-) create mode 100644 .rebel_readline_history diff --git a/.rebel_readline_history b/.rebel_readline_history new file mode 100644 index 0000000..a619ae0 --- /dev/null +++ b/.rebel_readline_history @@ -0,0 +1,18 @@ +1771730881107:(require '[clojure.core.cache :as cache] '[clojure.core.cache.wrapped :as cache-wrapped]) +1771730883786:(let [thread-count 20\n cache-atom (-> {}\n (cache/ttl-cache-factory :ttl 120000)\n (cache/lu-cache-factory :threshold 100)\n (atom))\n latch (java.util.concurrent.CountDownLatch. thread-count)\n invocations-counter (atom 0)]\n (doseq [i (range thread-count)]\n (println "starting thread" i)\n (.start (Thread. (fn []\n (cache-wrapped/lookup-or-miss cache-atom "my-key"\n (fn [k]\n (swap! invocations-counter inc)\n (Thread/sleep 3000)\n "some value"))\n (.countDown latch)))))\n (.await latch)\n (deref invocations-counter)) +1771874817202:(force (delay ((fn [] (throw (Exception. "bad")))))) +1771874830891:(def x (force (delay ((fn [] (throw (Exception. "bad"))))))) +1771874832688:x +1771875362757:(def p (promise)) +1771875366556:(realized? p) +1771875376098:(deliver p 42) +1771875377638:(realized? p) +1771875417454:(force p) +1771875420076:p +1771875423512:@p +1771879609917:(def x (delay (throw (Exception. "bad")))) +1771879610748:x +1771879620704:(force x) +1771879622323:x +1771879802447:(def x (with-meta (delay (throw (Exception. "bad"))) {::core.cache.added true})) +1771885580329:(source force) diff --git a/src/main/clojure/clojure/core/cache/wrapped.clj b/src/main/clojure/clojure/core/cache/wrapped.clj index 473d434..a3936fd 100644 --- a/src/main/clojure/clojure/core/cache/wrapped.clj +++ b/src/main/clojure/clojure/core/cache/wrapped.clj @@ -22,6 +22,42 @@ (set! *warn-on-reflection* true) +(def ^{:private true} default-wrapper-fn #(%1 %2)) + +;; Similar to clojure.lang.Delay, but will not memoize an exception and will +;; instead retry. +;; fun - the function, never nil +;; available? - indicates a memoized value is available, volatile for visibility +;; value - the value (if available) - volatile for visibility +(deftype RetryingDelay [fun ^:volatile-mutable available? ^:volatile-mutable value] + clojure.lang.IDeref + (deref [this] + ;; first check (safe with volatile flag) + (if available? + value + (locking fun + ;; second check (race condition with locking) + (if available? + value + ;; fun may throw - will retry on next deref + (let [v (fun)] + ;; this ordering is important - MUST set value before setting available? + ;; or you have a race with the first check above + (set! value v) + (set! available? true) + v))))) + clojure.lang.IPending + (isRealized [this] + available?)) + +(defn- d-lay [fun] + (->RetryingDelay fun false nil)) + +(defn- r-force [maybe-d-lay] + (if (instance? RetryingDelay maybe-d-lay) + (deref maybe-d-lay) + maybe-d-lay)) + (defn lookup "Retrieve the value associated with `e` if it exists, else `nil` in the 2-arg case. Retrieve the value associated with `e` if it exists, @@ -29,11 +65,9 @@ Reads from the current version of the atom." ([cache-atom e] - (force (c/lookup @cache-atom e))) + (r-force (c/lookup @cache-atom e))) ([cache-atom e not-found] - (force (c/lookup @cache-atom e not-found)))) - -(def ^{:private true} default-wrapper-fn #(%1 %2)) + (r-force (c/lookup @cache-atom e not-found)))) (defn lookup-or-miss "Retrieve the value associated with `e` if it exists, else compute the @@ -48,25 +82,24 @@ ([cache-atom e value-fn] (lookup-or-miss cache-atom e default-wrapper-fn value-fn)) ([cache-atom e wrap-fn value-fn] - (let [d-new-value (delay (wrap-fn value-fn e))] - (loop [n 0 - v (force (c/lookup (swap! cache-atom - c/through-cache - e - default-wrapper-fn - (fn [_] d-new-value)) - e - ::expired))] + (let [d-new-value (d-lay #(wrap-fn value-fn e)) + hit-or-miss + (fn [] + (try + (r-force (c/lookup (swap! cache-atom + c/through-cache + e + default-wrapper-fn + (fn [_] d-new-value)) + e + ::expired)) + (catch Throwable t + (swap! cache-atom c/evict e) + (throw t))))] + (loop [n 0 v (hit-or-miss)] (when (< n 10) (if (= ::expired v) - (recur (inc n) - (force (c/lookup (swap! cache-atom - c/through-cache - e - default-wrapper-fn - (fn [_] d-new-value)) - e - ::expired))) + (recur (inc n) (hit-or-miss)) v)))))) (defn has? diff --git a/src/test/clojure/clojure/core/cache/wrapped_test.clj b/src/test/clojure/clojure/core/cache/wrapped_test.clj index 4c7e755..b66677c 100644 --- a/src/test/clojure/clojure/core/cache/wrapped_test.clj +++ b/src/test/clojure/clojure/core/cache/wrapped_test.clj @@ -43,33 +43,70 @@ start (System/currentTimeMillis)] (loop [n 0] (if-not (c/lookup-or-miss cache :a (constantly 42)) - (do - (is false (str "Failure on call " n))) - (if (< n limit) - (recur (+ 1 n))))) + (is false (str "Failure on call " n)) + (when (< n limit) + (recur (inc n))))) (println "ttl test completed" limit "calls in" (- (System/currentTimeMillis) start) "ms"))) (deftest cache-stampede - (let [thread-count 100 + (let [thread-count 1000 cache-atom (-> {} (cache/ttl-cache-factory :ttl 120000) (cache/lu-cache-factory :threshold 100) (atom)) latch (java.util.concurrent.CountDownLatch. thread-count) invocations-counter (atom 0) - values (atom [])] - (dotimes [_ thread-count] - (.start (Thread. (fn [] - (swap! values conj - (c/lookup-or-miss cache-atom "my-key" - (fn [_] - (swap! invocations-counter inc) - (Thread/sleep 3000) - "some value"))) - (.countDown latch))))) + freds (atom []) + values (atom []) + exes (atom 0)] + (dotimes [n thread-count] + (if (<= n (rand-int thread-count)) + (swap! freds conj + (Thread. + (fn [] + (try + (swap! values conj + (c/lookup-or-miss cache-atom "my-key" + (fn [_] + (throw (Exception. "Bad"))))) + (catch Exception e + (swap! exes inc) + (is (= "Bad" (.getMessage e))))) + (.countDown latch)))) + (swap! freds conj + (Thread. + (fn [] + (try + (swap! values conj + (c/lookup-or-miss cache-atom "my-key" + (fn [_] + (swap! invocations-counter inc) + (Thread/sleep 3000) + "some value"))) + (catch Exception _ + (is false "Unexpected cached exception"))) + (.countDown latch)))))) + + (run! #(.start ^Thread %) @freds) (.await latch) + (println "cache-stampede test completed with" @invocations-counter + "successful invocation(s)\n\tand" (count @values) + "successful lookups in" thread-count + "threads with" @exes "exceptions") (is (= 1 (deref invocations-counter))) + (is (= (- thread-count @exes) (count @values))) (doseq [v @values] (is (= "some value" v))))) + +(deftest cache-thrown + (let [c (c/basic-cache-factory {})] + (is (thrown? Exception + (c/lookup-or-miss c :a + (fn [_] + (throw (Exception. "bad")))))) + ;; cache should not have :a in it + (is (= nil (c/lookup c :a))) + ;; and the cache should still be empty + (is (= 0 (c/size c))))) From a17987c3b46b5a9335421c0334251a5e24cd5842 Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Mon, 23 Feb 2026 19:32:01 -0500 Subject: [PATCH 142/145] CCACHE-65 use locking for the time being (bad) Signed-off-by: Sean Corfield --- .../clojure/clojure/core/cache/wrapped.clj | 23 ++++++++++--------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/src/main/clojure/clojure/core/cache/wrapped.clj b/src/main/clojure/clojure/core/cache/wrapped.clj index a3936fd..95e3a3f 100644 --- a/src/main/clojure/clojure/core/cache/wrapped.clj +++ b/src/main/clojure/clojure/core/cache/wrapped.clj @@ -85,17 +85,18 @@ (let [d-new-value (d-lay #(wrap-fn value-fn e)) hit-or-miss (fn [] - (try - (r-force (c/lookup (swap! cache-atom - c/through-cache - e - default-wrapper-fn - (fn [_] d-new-value)) - e - ::expired)) - (catch Throwable t - (swap! cache-atom c/evict e) - (throw t))))] + (locking cache-atom ; I really do not like this... :( + (try + (r-force (c/lookup (swap! cache-atom + c/through-cache + e + default-wrapper-fn + (fn [_] d-new-value)) + e + ::expired)) + (catch Throwable t + (swap! cache-atom c/evict e) + (throw t)))))] (loop [n 0 v (hit-or-miss)] (when (< n 10) (if (= ::expired v) From 72cc71d846f55619cdcf5e9fdc2a511f72eb5ed3 Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Mon, 23 Feb 2026 19:38:44 -0500 Subject: [PATCH 143/145] prep for 1.2.259 Signed-off-by: Sean Corfield --- README.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index d182c88..dcc2dc2 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ Releases and Dependency Information This project follows the version scheme MAJOR.MINOR.COMMITS where MAJOR and MINOR provide some relative indication of the size of the change, but do not follow semantic versioning. In general, all changes endeavor to be non-breaking (by moving to new names rather than by breaking existing names). COMMITS is an ever-increasing counter of commits since the beginning of this repository. -Latest stable release: 1.2.254 +Latest stable release: 1.2.259 * [All Released Versions](https://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22org.clojure%22%20AND%20a%3A%22core.cache%22) * [Development Snapshot Versions](https://oss.sonatype.org/index.html#nexus-search;gav~org.clojure~core.cache~~~) @@ -41,19 +41,19 @@ Latest stable release: 1.2.254 [CLI/`deps.edn`](https://clojure.org/reference/deps_edn) dependency information: ```clojure -org.clojure/core.cache {:mvn/version "1.2.254"} +org.clojure/core.cache {:mvn/version "1.2.259"} ``` [Leiningen](https://github.com/technomancy/leiningen) dependency information: - [org.clojure/core.cache "1.2.254"] + [org.clojure/core.cache "1.2.259"] [Maven](http://maven.apache.org/) dependency information: org.clojure core.cache - 1.2.254 + 1.2.259 @@ -173,6 +173,8 @@ Developer Information Change Log ==================== +* Release 1.2.259 on 2026-02-23 + * [CCACHE-65](http://clojure.atlassian.net/browse/CCACHE-65) again! Avoids caching exceptions but currently relies on `locking` to avoid an edge case race condition if the `value-fn` throws an exception under heavy load on `lookup-or-miss`. This is a temporary solution until we can implement a more robust solution that doesn't rely on `locking`. * Release 1.2.254 on 2026-02-21 * [CCACHE-67](http://clojure.atlassian.net/browse/CCACHE-67) Add `clojure.core.cache.wrapped/size` function to get the size of the cache without dereferencing the atom. (via [@dharrigan](https://github.com/dharrigan)). * [CCACHE-65](http://clojure.atlassian.net/browse/CCACHE-65) Use `delay` in `lookup-or-miss` to avoid cache-stampede. From a18d283c33968c8a8a81c84b818a81a3d0ee3f35 Mon Sep 17 00:00:00 2001 From: clojure-build Date: Tue, 24 Feb 2026 00:40:15 +0000 Subject: [PATCH 144/145] [maven-release-plugin] prepare release v1.2.259 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 97042e4..ff77cf0 100644 --- a/pom.xml +++ b/pom.xml @@ -2,14 +2,14 @@ 4.0.0 core.cache - 1.2.999-SNAPSHOT + 1.2.259 core.cache Cache library for Clojure. scm:git:git://github.com/clojure/core.cache.git scm:git:ssh://git@github.com/clojure/core.cache.git - HEAD + v1.2.259 https://github.com/clojure/core.cache From ec4632c236f274abdacb76ac2010745f73506985 Mon Sep 17 00:00:00 2001 From: clojure-build Date: Tue, 24 Feb 2026 00:40:15 +0000 Subject: [PATCH 145/145] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index ff77cf0..97042e4 100644 --- a/pom.xml +++ b/pom.xml @@ -2,14 +2,14 @@ 4.0.0 core.cache - 1.2.259 + 1.2.999-SNAPSHOT core.cache Cache library for Clojure. scm:git:git://github.com/clojure/core.cache.git scm:git:ssh://git@github.com/clojure/core.cache.git - v1.2.259 + HEAD https://github.com/clojure/core.cache