Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
File backed atom.
(ns afile.core
(:require
[clojure.edn :as edn]
[clojure.pprint :refer [pprint]]
[clojure.test :refer [deftest is run-tests]]))
(defn- load-file!
[fname init-value]
(let [f (java.io.File. fname)]
(if (.exists f)
(-> (slurp f) edn/read-string)
init-value)))
(defn- write-change!
[fname ref old new]
(spit fname (with-out-str (pprint new))))
(defn afile
"A file-backed atom: takes a file and an initial value (if the file
is empty) and returns an atom such that all updates are saved to the
file. Supports [swap! reset! compare-and-set!]."
([fname]
(afile fname nil))
([fname init-value]
(let [value (load-file! fname init-value)
cache (atom value)]
(add-watch cache fname write-change!)
cache)))
;;;
(deftest file-backed-atom
[]
(.delete (java.io.File. "test.edn"))
(let [pfile (afile "test.edn" {:x 0})
runs (for [x (range 100)]
(future (swap! pfile #(assoc % :x (inc (:x %))))))]
(loop [runs runs]
(when-let [run (first runs)]
(deref run)
(recur (rest runs))))
(let [v (edn/read-string (slurp "test.edn"))]
(is (= {:x 100} v)))))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.