If your data fits in RAM, you can write your system as a pure Clojure function, without any database complexity. It will be much simpler, cleaner and orders of magnitude faster.
Prevayler takes care of persistence.
(defn my-business [state event timestamp]
...) ; Your business logic as a pure function. Returns the new state with event applied.
(with-open [p1 (prevayler! {:business-fn my-business})]
(assert (= @p1 {})) ; The default initial state is an empty map.
(handle! p1 event1) ; Your events can be any Clojure value or Serializable object.
(handle! p1 event2)
(assert (= @p1 new-state))) ; Your system state with the events applied.
(with-open [p2 (prevayler! my-business)] ; Next time you run,
(assert (= @p2 new-state))) ; the state is recovered, even if there was a system crash.
Prevayler-clj implements the system prevalence pattern: it keeps a snapshot of your business state followed by a journal of events. On startup or crash recovery it reads the last state and reapplies all events since: your business state is restored to where it was.
Prevayler's default file name is journal4
but you can pass in your own file (see tests). Prevayler-clj will create and write to it like this:
Contains the state at the moment your system was last started, followed by all events since. Serialization is done using Nippy.
On startup, the journal is renamed to journal4.backup
and a new journal4
file is created.
This new journal will only be consistent after the business state has been written to it so when journal.backup
exists, it takes precedence over journal4
.
After a new consistent journal is written, journal.backup
is renamed with a timestamp appendix. You can keep these old versions elsewhere if you like. Prevayler-clj no longer uses them.
"Simplicity is prerequisite for reliability." Dijkstra (1970)
Can you improve this documentation? These fine people already did:
Klaus Wuestefeld & Rodrigo B. de OliveiraEdit on GitHub
cljdoc is a website building & hosting documentation for Clojure/Script libraries
× close