Skip to content

Commit

Permalink
Merge pull request #14 from asafch/docstrings
Browse files Browse the repository at this point in the history
Clarify docstrings; differentiate sync vs. async loader in async cache
  • Loading branch information
barkanido authored Jan 11, 2021
2 parents 59999f0 + 5e4ea39 commit dc72310
Show file tree
Hide file tree
Showing 9 changed files with 225 additions and 157 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
#### VERSION 0.1.9
* Clarify docstrings
* Differentiate the construction of an AsyncLoadingCache that uses a CacheLoader
vs. an AsyncCacheLoader

#### VERSION 0.1.8
* Bump caffeine to 2.8.8

Expand Down
22 changes: 11 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,21 +1,23 @@
# Cloffeine

Simple clojure wrapper around https://github.com/ben-manes/caffeine cache.
Simple clojure wrapper over [`Caffeine`](https://github.com/ben-manes/caffeine).

[![Clojars Project](https://img.shields.io/clojars/v/com.appsflyer/cloffeine.svg)](https://clojars.org/com.appsflyer/cloffeine)

[![Coverage Status](https://coveralls.io/repos/github/AppsFlyer/cloffeine/badge.svg?branch=master)](https://coveralls.io/github/AppsFlyer/cloffeine?branch=master)

[![cljdoc badge](https://cljdoc.org/badge/com.appsflyer/cloffeine)](https://cljdoc.org/d/com.appsflyer/cloffeine/CURRENT)


add `[com.appsflyer/cloffeine "0.1.8"]` under `:dependencies`
## Installing
Add `[com.appsflyer/cloffeine "0.1.9"]` to your `project.clj` under `:dependencies`.

## [Checkout the docs](https://appsflyer.github.io/cloffeine/index.html)

Usage:
------
Manual loading:


## Usage

### Manual loading

```clojure
(require '[cloffeine.cache :as cache])
Expand All @@ -28,7 +30,7 @@ Manual loading:
(is (= "key" (cache/get cache :key name)))
```

Automatic loading
### Automatic loading

```clojure
(require '[cloffeine.loading-cache :as loading-cache])
Expand All @@ -52,10 +54,9 @@ Automatic loading
(cache/invalidate! lcache :key)
(is (= "key" (cache/get lcache :key name)))
(is (= 1 @loads))

```

Async:
### Async cache

```clojure
(require '[cloffeine.async-cache :as async-cache])
Expand All @@ -66,10 +67,9 @@ Async:
(is (= :v @(async-cache/get acache :key name)))
(async-cache/invalidate! acache :key)
(is (= "key" @(async-cache/get acache :key name)))

```

Async with automatic loading:
### Async with automatic loading:

```clojure
(require '[cloffeine.async-loading-cache :as async-loading-cache])
Expand Down
48 changes: 24 additions & 24 deletions project.clj
Original file line number Diff line number Diff line change
@@ -1,31 +1,31 @@
(defproject com.appsflyer/cloffeine "0.1.8"
(defproject com.appsflyer/cloffeine "0.1.9"
:description "A warpper over https://github.com/ben-manes/caffeine"
:url "https://github.com/AppsFlyer/cloffeine"
:license {:name "Eclipse Public License"
:url "http://www.eclipse.org/legal/epl-v10.html"}
:url "http://www.eclipse.org/legal/epl-v10.html"}
:dependencies [[com.github.ben-manes.caffeine/caffeine "2.8.8"]]
:plugins [[lein-codox "0.10.7"]]
:codox {:output-path "codox"
:source-uri "http://github.com/AppsFlyer/cloffeine/blob/{version}/{filepath}#L{line}"
:metadata {:doc/format :markdown}}
:source-uri "http://github.com/AppsFlyer/cloffeine/blob/{version}/{filepath}#L{line}"
:metadata {:doc/format :markdown}}
:profiles {:uberjar {:aot :all}
:dev {:plugins [[jonase/eastwood "0.3.5"]
[lein-cloverage "1.1.1"]
[lein-eftest "0.5.9"]
[lein-kibit "0.1.7"]
[com.jakemccrary/lein-test-refresh "0.24.1"]
[lein-cloverage "1.1.2"]
[lein-ancient "0.6.15"]]
:eftest {:multithread? false
:report eftest.report.junit/report
:report-to-file "target/junit.xml"}
:dependencies [[org.clojure/clojure "1.10.1"]
[criterium "0.4.6"]
[cheshire "5.10.0"]
[com.taoensso/timbre "5.1.0"]
[clj-kondo "RELEASE"]
[funcool/promesa "6.0.0"]
[com.google.guava/guava-testlib "28.1-jre"]]
:aliases {"clj-kondo" ["run" "-m" "clj-kondo.main"]
"lint" ["run" "-m" "clj-kondo.main" "--lint" "src" "test"]}
:global-vars {*warn-on-reflection* true}}})
:dev {:plugins [[jonase/eastwood "0.3.5"]
[lein-cloverage "1.1.1"]
[lein-eftest "0.5.9"]
[lein-kibit "0.1.7"]
[com.jakemccrary/lein-test-refresh "0.24.1"]
[lein-cloverage "1.1.2"]
[lein-ancient "0.6.15"]]
:eftest {:multithread? false
:report eftest.report.junit/report
:report-to-file "target/junit.xml"}
:dependencies [[org.clojure/clojure "1.10.1"]
[criterium "0.4.6"]
[cheshire "5.10.0"]
[com.taoensso/timbre "5.1.0"]
[clj-kondo "RELEASE"]
[funcool/promesa "6.0.0"]
[com.google.guava/guava-testlib "28.1-jre"]]
:aliases {"clj-kondo" ["run" "-m" "clj-kondo.main"]
"lint" ["run" "-m" "clj-kondo.main" "--lint" "src" "test"]}
:global-vars {*warn-on-reflection* true}}})
23 changes: 13 additions & 10 deletions src/cloffeine/async_cache.clj
Original file line number Diff line number Diff line change
@@ -1,41 +1,44 @@
(ns cloffeine.async-cache
(:refer-clojure :exclude [get])
(:require [cloffeine.common :as common]
[cloffeine.cache :as cache])
(:require [cloffeine.cache :as cache]
[cloffeine.common :as common])
(:import [com.github.benmanes.caffeine.cache AsyncCache]))

(defn make-cache
"Create an AsyncCache. See `cloffeine.common/builder` for settings.
A semi-persistent mapping from keys to values. Values are automatically loaded by the cache asynchronously, and are stored in the cache until either evicted or manually invalidated.
Implementations of this interface are expected to be thread-safe, and can be safely accessed by multiple concurrent threads."
A semi-persistent mapping from keys to values. Values should be manually set in
the cache using cloffeine.async-cache/put!."
(^AsyncCache []
(make-cache {}))
(^AsyncCache [settings]
(let [bldr (common/make-builder settings)]
(.buildAsync bldr))))

(defn get
"Returns the future associated with key in this cache, obtaining that value from mappingFunction if necessary."
"Returns the future associated with the key in this cache, obtaining that value
from mappingFunction if necessary."
[^AsyncCache acache k f]
(.get acache k (common/ifn->function f)))

(defn get-if-present "Returns the future associated with key in this cache, or null if there is no cached future for key."
(defn get-if-present
"Returns the future associated with key in this cache, or nil if there is no
cached future for key."
[^AsyncCache acache k]
;; TODO: acache can return nil. always wrap in future?
;; TODO: acache can return nil. always wrap in future?
(.getIfPresent acache k))

(defn put!
(defn put!
"Associates value with key in this cache."
[^AsyncCache acache k future-v]
(.put acache k future-v))

(defn ->Cache
"Returns a view of the entries stored in this cache as a synchronous Cache."
"Returns a view of the entries stored in this cache as a synchronous cache."
[^AsyncCache acache]
(.synchronous acache))

(defn invalidate!
"Discards any cached value for the key."
"Disassociates the value cached for the key."
[^AsyncCache acache k]
(-> acache
->Cache
Expand Down
44 changes: 26 additions & 18 deletions src/cloffeine/async_loading_cache.clj
Original file line number Diff line number Diff line change
@@ -1,48 +1,56 @@
(ns cloffeine.async-loading-cache
(:refer-clojure :exclude [get])
(:require [cloffeine.common :as common]
[cloffeine.async-cache :as acache]
(:require [cloffeine.async-cache :as acache]
[cloffeine.common :as common]
[cloffeine.loading-cache :as loading-cache])
(:import [com.github.benmanes.caffeine.cache
AsyncCache
AsyncLoadingCache
AsyncCacheLoader]))
(:import [com.github.benmanes.caffeine.cache
AsyncCache
AsyncLoadingCache
AsyncCacheLoader
CacheLoader]))

(defn make-cache
"Create an AsyncLoadingCache. See `cloffeine.common/builder` for settings.
A semi-persistent mapping from keys to values. Values are automatically loaded by the cache asynchronously, and are stored in the cache until either evicted or manually invalidated.)
Implementations of this interface are expected to be thread-safe, and can be safely accessed by multiple concurrent threads."
(^AsyncLoadingCache [cache-loader]
A semi-persistent mapping from keys to values. Values are automatically loaded
by the cache synchronously, and are stored in the cache until either evicted
or manually invalidated."
(^AsyncLoadingCache [^CacheLoader cache-loader]
(make-cache cache-loader {}))
(^AsyncLoadingCache [cache-loader settings]
(^AsyncLoadingCache [^CacheLoader cache-loader settings]
(let [bldr (common/make-builder settings)]
(.buildAsync bldr cache-loader))))

(defn make-cache-async-loader
"Create a CacheLoader"
"Create an AsyncLoadingCache that uses an AsyncCacheLoader to asynchronously
load missing entries."
(^AsyncLoadingCache [^AsyncCacheLoader cl]
(make-cache cl {}))
(make-cache-async-loader cl {}))
(^AsyncLoadingCache [^AsyncCacheLoader cl settings]
(let [bldr (common/make-builder settings)]
(.buildAsync bldr cl))))

(defn get
"Returns the future associated with key in this cache, obtaining that value from AsyncCacheLoader.asyncLoad(K, java.util.concurrent.Executor) if necessary."
"Returns the future associated with the key in this cache, obtaining that
value from AsyncCacheLoader.asyncLoad(K, java.util.concurrent.Executor) if necessary."
([^AsyncLoadingCache alcache k]
(.get alcache k))
([^AsyncCache alcache k f]
(acache/get alcache k f)))

(def get-if-present acache/get-if-present)
(def put! acache/put!)
(def ^{:doc "Returns the future associated with key in this cache, or nil if
there is no cached future for key."}
get-if-present acache/get-if-present)

(defn ->LoadingCache
"Returns a view of the entries stored in this cache as a synchronous LoadingCache."
(def ^{:doc "Associates value with key in this cache."}
put! acache/put!)

(defn ->LoadingCache
"Returns a view of the entries stored in this cache as a synchronous cache."
[^AsyncLoadingCache alcache]
(.synchronous alcache))

(defn invalidate!
"Discards any cached value for the key."
"Disassociates the value cached for the key."
[^AsyncLoadingCache alcache k]
(-> alcache
->LoadingCache
Expand Down
39 changes: 23 additions & 16 deletions src/cloffeine/cache.clj
Original file line number Diff line number Diff line change
@@ -1,46 +1,50 @@
(ns cloffeine.cache
(:refer-clojure :exclude [get])
(:require [cloffeine.common :as common])
(:import [com.github.benmanes.caffeine.cache Cache]
[java.util.concurrent ConcurrentMap]))
(:import [java.util.concurrent ConcurrentMap]
[com.github.benmanes.caffeine.cache Cache]))

(defn make-cache
"Create an AsyncLoadingCache. See `cloffeine.common/builder` for settings.
A semi-persistent mapping from keys to values. Cache entries are manually added using get(Object, Function) or put(Object, Object), and are stored in the cache until either evicted or manually invalidated.
Implementations of this interface are expected to be thread-safe, and can be safely accessed by multiple concurrent threads."
"Create a LoadingCache. See `cloffeine.common/builder` for settings.
A semi-persistent mapping from keys to values. Cache entries are manually added
using get(Object, Function) or put(Object, Object), and are stored in the cache
until either evicted or manually invalidated."
(^Cache []
(make-cache {}))
(^Cache [settings]
(let [bldr (common/make-builder settings)]
(.build bldr))))

(defn get
"Returns the value associated with the key in this cache, obtaining that value from the mappingFunction if necessary."
"Returns the value associated with the key in this cache, obtaining that value
from the mappingFunction if necessary."
[^Cache cache k loading-fn]
(.get cache k (common/ifn->function loading-fn)))

(defn get-all
"Returns a map of the values associated with the keys, creating or retrieving those values if necessary."
"Returns a map of the values associated with the keys, creating or retrieving
those values if necessary using 'mapping-fn'."
[^Cache cache ks mapping-fn]
(into {} (.getAll cache ks (common/ifn->function mapping-fn))))

(defn get-all-present
"Returns a map of the values associated with the keys in this cache."
"Returns a map of all the values associated with the keys in this cache."
[^Cache cache ks]
(into {} (.getAllPresent cache ks)))

(defn get-if-present
"Returns the value associated with the key in this cache, or null if there is no cached value for the key."
"Returns the value associated with the key in this cache, or nil if there is
no cached value for the key."
[^Cache cache k]
(.getIfPresent cache k))

(defn invalidate!
"Discards any cached value for the key."
"Disassociates the value cached for the key."
[^Cache cache k]
(.invalidate cache k))

(defn invalidate-all!
"Discards all entries in the cache."
(defn invalidate-all!
"Disassociates all the values in the cache."
([^Cache cache]
(.invalidateAll cache))
([^Cache cache ks]
Expand All @@ -62,7 +66,8 @@ Implementations of this interface are expected to be thread-safe, and can be saf
(.estimatedSize cache))

(defn policy
"Returns access to inspect and perform low-level operations on this cache based on its runtime characteristics."
"Returns access to inspect and perform low-level operations on this cache based
on its runtime characteristics."
[^Cache cache]
(.policy cache))

Expand All @@ -75,10 +80,12 @@ Implementations of this interface are expected to be thread-safe, and can be saf
(.compute m k bi-fn))

(defn compute
"see: https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ConcurrentMap.html#compute-K-java.util.function.BiFunction-
Attempts to compute a mapping for the specified key and its current mapped value (or null if there is no current mapping). For example, to either create or append a String msg to a value mapping:
"Attempts to compute a mapping for the specified key and its current mapped
value (or nil if there is no current mapping).
For example, to either create or append a String msg to a value mapping:
`(compute cache \"k\" (fn [k, v] (if (nil? v) msg (str v msg)))`
"
See: https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ConcurrentMap.html#compute-K-java.util.function.BiFunction-"
[^Cache cache k remapper-fn]
(let [bi-fn (common/ifn->bifunction remapper-fn)]
(-> cache
Expand Down
Loading

0 comments on commit dc72310

Please sign in to comment.