Skip to content

Instantly share code, notes, and snippets.

@ivarref
Last active July 28, 2020 14:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ivarref/a9592d3ef4b3fb6c03c6ca8cd2c3c210 to your computer and use it in GitHub Desktop.
Save ivarref/a9592d3ef4b3fb6c03c6ca8cd2c3c210 to your computer and use it in GitHub Desktop.
(defn ttl-fn
"Returns a function that will cache the `f` function.
The f function must return a map with two keys:
- :ttl number of seconds for the return value to live.
- :val the value that this function will return and cache."
[f]
(let [cache (atom nil)]
(fn [& args]
(locking cache
(let [now-seconds (int (/ (System/currentTimeMillis) 1000))]
(:val (swap! cache (fn [{:keys [expires] :as cached-val
:or {expires 0}}]
(if (>= now-seconds expires)
(do
(log/info "pulling value...")
(let [{:keys [ttl val]} (apply f args)]
(assert (int? ttl))
{:expires (+ now-seconds ttl)
:val val}))
(do
(log/info "time until expiry:" (- expires now-seconds))
cached-val))))))))))
;; example usage:
(defn get-client-credentials
[{:env/keys [SSO_TOKEN_URL
SSO_ID
SSO_SECRET]}]
(try
(let [resp (client/post SSO_TOKEN_URL
{:accept :json
:basic-auth [SSO_ID SSO_SECRET]
:as :json
:content-type :application/x-www-form-urlencoded
:form-params {:grant_type "client_credentials"
:scope "users:read"}})]
{:ttl (- (-> resp :body :expires_in) 60) ;; <-- must return :ttl
:val (-> resp :body :access_token)}) ;; <-- and :val
(catch Throwable t
(log/error t "error while getting client credentials!")
(when-let [status (some-> t (ex-data) :status)]
(log/error "http response code was" status))
(throw t))))
(def get-client-credentials-cached (ttl-fn get-client-credentials)) ;; <-- use this!
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment