(in-package #:cl-user) (defpackage #:snapshot (:use #:cl #:utils #:storage #:nera) (:export #:take-snapshot #:restore-from-snapshot #:delete-snapshot #:store-snapshot)) (in-package #:snapshot) (defun take-snapshot () "Takes a Snapshot of the website's data and stores it in /snapshots. I've not included make a SQL dump of the Meilisearch database here because the user can repopulate that database after they have restored this website. The 'repopulate' feature is built into the website already." (let ((snapshot-directory (format nil "~a_~a/" (utils:slugify (site-settings::site-name-of (nera:get-site-settings))) (utils:create-timestamp-text)))) (storage:ensure-raw-directory-exists (format nil "snapshots/~a" snapshot-directory)) (storage:copy-storage-directory (format nil "snapshots/~a/storage/" snapshot-directory)) (storage:copy-raw-directory "db/" (format nil "snapshots/~a/db/" snapshot-directory)))) (defun restore-from-snapshot (snapshot-name) "Deletes the data in /storage and the DB and replaces it with `SNAPSHOT-NAME'." (storage:remove-raw-directory "storage/") (storage:remove-raw-directory "db/") (storage:copy-raw-directory (format nil "snapshots/~a/storage/" snapshot-name) "storage/") (storage:copy-raw-directory (format nil "snapshots/~a/db/" snapshot-name) "db/")) (defun delete-snapshot (snapshot-name) "Deletes the snapshot in the /snapshots directory with `SNAPSHOT-NAME'." (storage:remove-raw-directory (format nil "snapshots/~a/" snapshot-name))) (defun store-snapshot (filename data) "Unzips `SNAPSHOT-FILE' and stores it in /snapshots directory. The .zip file is deleted after it has been un-zipped. I did think about moving the zipped version of the file into the /storage/media directory but there is too much second guessing going on. I found I was uploading .zip files from the /storage/media directory and I don't know if users will be uploading .zip files they had just downloaded from /storage/media. If that is the case, then there is: a.) No need to move it to /storage/madia; b.) Extra work regarding checks for duplicate entries; and, c.) I don't know if that is too much 'magic' for users and cause confusion. If the user is in a paniced state -- trying to restore their website, confusion is the thing I want to keep to a minimum for them." (storage:store-with-raw-path (format nil "snapshots/~a" filename) data) (zip:unzip (storage:make-raw-path (format nil"snapshots/~a" filename)) (storage:make-raw-path (format nil "snapshots/~a/" (pathname-name filename)))) (storage:remove-file-with-raw-path (format nil "snapshots/~a" filename)))