Journal, the Kitchen Sink
Tags: lisp
, Date: 2020-09-04
Ever wished for machine-readable logs and TRACE
s, maybe
for writing tests or something more fancy? The
Journal library takes a simple idea:
user-defined execution traces and implements
logging, tracing, a
testing "framework" with mock
support, and an Event Sourcing style
database on top.
Perhaps the highlight from the linked tutorials is how easy persistence is. Let's write a simple game:
(defun play-guess-my-number ()
(let ((my-number (random 10)))
(format t "~%I thought of a number.~%")
(loop for i upfrom 0 do
(write-line "Guess my number:")
(let ((guess (values (parse-integer (read-line)))))
(format t "You guessed ~D.~%" guess)
(when (= guess my-number)
(format t "You guessed it in ~D tries!" (1+ i))
(return))))))
That came out pretty ugly, didn't it? Now, suppose we want to turn this into a browser game so:
the state of the game must be saved,
and the game shall be resumed from the last saved state,
even if the web server's worker thread times out, or there is a power failure.
So, these are the requirements apart from adding the webby stuff,
which I'm not going to bore you with. To implement them, we wrap
REPLAYED
around external interactions, RANDOM
and READ-LINE
:
(defun play-guess-my-number ()
(let ((my-number (replayed (think-of-a-number) ; <- HERE
(random 10))))
(format t "~%I thought of a number.~%")
(loop for i upfrom 0 do
(write-line "Guess my number:")
(let ((guess (replayed (read-guess) ; <- HERE
(values (parse-integer (read-line))))))
(format t "You guessed ~D.~%" guess)
(when (= guess my-number)
(format t "You guessed it in ~D tries!" (1+ i))
(return))))))
Now, we need to say where to store the event journal:
(with-bundle ((make-file-bundle "/tmp/guess-my-number/" :sync t))
(play-guess-my-number))
This is invoked from a web server worker thread, and it replays the
game until the point where it was interrupted last time around.
Then, it will block waiting for user input in READ-LINE
or, if the
game is finished, return. Note the :SYNC T
, which tells Journal to
take durability seriously.