From 0042a56d02912813cf267e5b3bc7d11e22b4e3b3 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Sat, 6 Jan 2018 17:00:14 -0500 Subject: [PATCH] Add new cache library (persistent-soft wrapper) --- core/autoload/cache.el | 97 ++++++++++++++++++++++++++++++ core/autoload/packages.el | 10 +-- core/core-lib.el | 1 - modules/feature/services/config.el | 12 +--- 4 files changed, 104 insertions(+), 16 deletions(-) create mode 100644 core/autoload/cache.el diff --git a/core/autoload/cache.el b/core/autoload/cache.el new file mode 100644 index 000000000..c4392be0a --- /dev/null +++ b/core/autoload/cache.el @@ -0,0 +1,97 @@ +;;; ../core/autoload/cache.el -*- lexical-binding: t; -*- + +;; This little library thinly wraps around persistent-soft (which is a pcache +;; wrapper, how about that). It has three purposes: +;; +;; + To encapsulate the cache backend (persistent-soft/pcache in this case), in +;; case it needs to change. +;; + To provide `doom-cache-persist': a mechanism for easily persisting +;; variables across Emacs sessions. +;; + To lazy-load persistent-soft until it is really needed. +;; +;; Like persistent-soft, caches assume a 2-tier structure, where all caches are +;; namespaced by location. + +(require 'persistent-soft) + +(defvar doom-cache-alists () + "An alist of alists, containing lists of variables for the doom cache library +to persist across Emacs sessions.") + +(defvar doom-cache-location 'doom + "The default location for cache files. This symbol is translated into a file +name under `pcache-directory' (by default a subdirectory under +`doom-cache-dir'). One file may contain multiple cache entries.") + +(defun doom|save-persistent-cache () + "Hook to run when an Emacs session is killed. Saves all persisted variables +listed in `doom-cache-alists' to files." + (dolist (alist doom-cache-alists) + (cl-loop with key = (car alist) + for var in (cdr alist) + if (symbol-value var) + do (doom-cache-set var it nil key)))) +(add-hook 'kill-emacs-hook #'doom|save-persistent-cache) + + +;; +;; Library +;; + +;;;###autoload +(defmacro with-cache! (location &rest body) + "Runs BODY with a different default `doom-cache-location'." + (declare (indent defun)) + `(let ((doom-cache-location ',location)) + ,@body)) + +;;;###autoload +(defun doom-cache-persist (location variables) + "Persist VARIABLES (list of symbols) in LOCATION (symbol). + +This populates these variables with cached values, if one exists, and saves them +to file when Emacs quits. + +Warning: this is incompatible with buffer-local variables." + (dolist (var variables) + (when (doom-cache-exists var location) + (set var (doom-cache-get var location)))) + (map-put doom-cache-alists location + (append variables (cdr (assq location doom-cache-alists))))) + +;;;###autoload +(defun doom-cache-desist (location &optional variables) + "Unregisters VARIABLES (list of symbols) in LOCATION (symbol) from +`doom-cache-alists', thus preventing them from being saved between sessions. +Does not affect the actual variables themselves or their values." + (if variables + (map-put doom-cache-alists location + (cl-set-difference (cdr (assq location doom-cache-alists)) + variables)) + (map-delete doom-cache-alists location))) + +;;;###autoload +(defun doom-cache-get (key &optional location) + "Retrieve KEY from LOCATION (defaults to `doom-cache-location'), if it exists +and hasn't expired." + (persistent-soft-fetch + key (symbol-name (or location doom-cache-location)))) + +;;;###autoload +(defun doom-cache-set (key value &optional ttl location) + "Set KEY to VALUE in the cache. TTL is the time (in seconds) until this cache +entry expires. LOCATION is the super-key to store this cache item under; the +default is `doom-cache-location'. " + (persistent-soft-store + key value + (symbol-name (or location doom-cache-location)) ttl)) + +;;;###autoload +(defun doom-cache-exists (key &optional location) + "Returns t if KEY exists at LOCATION (defaults to `doom-cache-location')." + (persistent-soft-exists-p key (or location doom-cache-location))) + +;;;###autoload +(defun doom-cache-clear (&optional location) + "Clear a cache LOCATION (defaults to `doom-cache-location')." + (persistent-soft-flush (or location doom-cache-location))) diff --git a/core/autoload/packages.el b/core/autoload/packages.el index 1e59fb4dd..1eb4ec417 100644 --- a/core/autoload/packages.el +++ b/core/autoload/packages.el @@ -1,22 +1,22 @@ ;;; core/autoload/packages.el -*- lexical-binding: t; -*- +(load! cache) (require 'use-package) (require 'quelpa) - -(defvar doom--last-refresh nil) +(require 'async) ;;;###autoload (defun doom-refresh-packages (&optional force-p) "Refresh ELPA packages." (when force-p (doom-refresh-clear-cache)) - (unless (or (persistent-soft-fetch 'last-pkg-refresh "emacs") + (unless (or (doom-cache-get 'last-pkg-refresh) doom--refreshed-p) (condition-case-unless-debug ex (progn (message "Refreshing package archives") (package-refresh-contents) - (persistent-soft-store 'last-pkg-refresh t "emacs" 900)) + (doom-cache-set 'last-pkg-refresh t 900)) ('error (doom-refresh-clear-cache) (message "Failed to refresh packages: (%s) %s" @@ -26,7 +26,7 @@ (defun doom-refresh-clear-cache () "Clear the cache for `doom-refresh-packages'." (setq doom--refreshed-p nil) - (persistent-soft-store 'last-pkg-refresh nil "emacs")) + (doom-cache-set 'last-pkg-refresh nil)) ;;;###autoload (defun doom-package-backend (name &optional noerror) diff --git a/core/core-lib.el b/core/core-lib.el index 5fbe58daf..61f1ea589 100644 --- a/core/core-lib.el +++ b/core/core-lib.el @@ -2,7 +2,6 @@ (require 'subr-x) (load "async-autoloads" nil t) -(load "persistent-soft-autoloads" nil t) (dolist (sym '(json-read json-read-file json-read-from-string json-encode)) (autoload sym "json")) (eval-and-compile diff --git a/modules/feature/services/config.el b/modules/feature/services/config.el index 6430a8864..8d8dcacfd 100644 --- a/modules/feature/services/config.el +++ b/modules/feature/services/config.el @@ -16,16 +16,8 @@ (set! :evil-state 'prodigy-mode 'emacs) ;; Make services, etc persistent between Emacs sessions - (setq prodigy-services (persistent-soft-fetch 'prodigy-services "prodigy") - prodigy-tags (persistent-soft-fetch 'prodigy-tags "prodigy") - prodigy-filters (persistent-soft-fetch 'prodigy-filters "prodigy")) - - (defun +services|save () - "Save all services, tags and filters to files." - (+services/cleanup) - (cl-loop for sym in '(prodigy-services prodigy-tags prodigy-filters) - do (persistent-soft-store sym (symbol-value sym) "prodigy"))) - (add-hook 'kill-emacs-hook #'+services|save) + (doom-cache-persist + :prodigy '(prodigy-services prodigy-tags prodigy-filters)) (defun +services*prodigy-services (orig-fn &rest args) "Adds a new :project property to prodigy services, which hides the service