Last active
January 15, 2016 19:30
-
-
Save joshrotenberg/4a8b699c42419b78659a to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(ns stuff.file-cache | |
(:require [clj-time.core :as t]) | |
(:require [clojure.java.io :as io]) | |
(:require [taoensso.nippy :as nippy]) | |
(:import [java.io DataInputStream DataOutputStream])) | |
;; This was just a quick experiment. I wanted to cache some lookup tables from a database. Rather than memoize each one individually, | |
;; though, I just wanted the whole chunk at once, the use case being a big table in Oracle that only changed periodically. I would use this | |
;; to cache on disk, and then also cache each one in memory, so even if the app restarted it wouldn't have to hit the database more than | |
;; once per 24 hour period. Worked ok in development, never quite made it to production. | |
(defn freeze | |
"Freeze data to a file at path and tag it good until expires. Returns the data stored." | |
[path data expires] | |
(locking data | |
(with-open [w (io/output-stream path)] | |
(nippy/freeze-to-out! (DataOutputStream. w) {:stored-at (t/now) :expires-at expires :data data}) | |
data))) | |
(defn thaw | |
"Returns the data in path, or nil if expired. Throws an exception if the file doesn't exist." | |
[path] | |
(locking path | |
(if-not (.exists (io/as-file path)) | |
nil | |
(with-open [r (io/input-stream path)] | |
(let [t (nippy/thaw-from-in! (DataInputStream. r)) | |
n (t/now)] | |
(when (t/before? n (:expires-at t)) | |
(:data t))))))) | |
(defn cached | |
"Takes a path, an expiration time (Joda), and a function that returns the data to store. Returns a function | |
that returns the data from the right source." | |
[f path expires-at] | |
(fn [] | |
(if-let [d (thaw path)] | |
d | |
(freeze path (f) expires-at)))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment