1
0
mirror of https://git.savannah.gnu.org/git/emacs.git synced 2024-12-11 09:20:51 +00:00

Implement a cache for all types of gravatars

* lisp/image/gravatar.el (gravatar-automatic-caching): Made obsolete.
(gravatar-cache-ttl): Ditto.
(gravatar--cache): New variable to cache gravatars in-memory.
(gravatar-retrieve): Maintain the cache.
(gravatar--prune-cache): Remove old entries.
(gravatar-retrieved): Remove use of the old-style cache (bug#40355).
This commit is contained in:
Lars Ingebrigtsen 2020-08-18 16:45:29 +02:00
parent 82893e9e8e
commit 23e6c36645

View File

@ -39,6 +39,7 @@
"Whether to cache retrieved gravatars." "Whether to cache retrieved gravatars."
:type 'boolean :type 'boolean
:group 'gravatar) :group 'gravatar)
(make-obsolete-variable 'gravatar-automatic-caching nil "28.1")
(defcustom gravatar-cache-ttl 2592000 (defcustom gravatar-cache-ttl 2592000
"Time to live in seconds for gravatar cache entries. "Time to live in seconds for gravatar cache entries.
@ -48,6 +49,7 @@ is retrieved anew. The default value is 30 days."
;; Restricted :type to number of seconds. ;; Restricted :type to number of seconds.
:version "27.1" :version "27.1"
:group 'gravatar) :group 'gravatar)
(make-obsolete-variable 'gravatar-cache-ttl nil "28.1")
(defcustom gravatar-rating "g" (defcustom gravatar-rating "g"
"Most explicit Gravatar rating level to allow. "Most explicit Gravatar rating level to allow.
@ -206,19 +208,50 @@ to track whether you're reading a specific mail."
(search-forward "\n\n" nil t) (search-forward "\n\n" nil t)
(buffer-substring (point) (point-max))))) (buffer-substring (point) (point-max)))))
(defvar gravatar--cache (make-hash-table :test 'equal)
"Cache for gravatars.")
;;;###autoload ;;;###autoload
(defun gravatar-retrieve (mail-address callback &optional cbargs) (defun gravatar-retrieve (mail-address callback &optional cbargs)
"Asynchronously retrieve a gravatar for MAIL-ADDRESS. "Asynchronously retrieve a gravatar for MAIL-ADDRESS.
When finished, call CALLBACK as (apply CALLBACK GRAVATAR CBARGS), When finished, call CALLBACK as (apply CALLBACK GRAVATAR CBARGS),
where GRAVATAR is either an image descriptor, or the symbol where GRAVATAR is either an image descriptor, or the symbol
`error' if the retrieval failed." `error' if the retrieval failed."
(gravatar-build-url (let ((cached (gethash mail-address gravatar--cache)))
mail-address (gravatar--prune-cache)
(lambda (url) (if cached
(if (url-cache-expired url gravatar-cache-ttl) (apply callback (cdr cached) cbargs)
(url-retrieve url #'gravatar-retrieved (list callback cbargs) t) ;; Nothing in the cache, fetch it.
(with-current-buffer (url-fetch-from-cache url) (gravatar-build-url
(gravatar-retrieved () callback cbargs)))))) mail-address
(lambda (url)
(url-retrieve
url
(lambda (status)
(let* ((data (and (not (plist-get status :error))
(gravatar-get-data)))
(image (and data (create-image data nil t))))
;; Store the image in the cache.
(when image
(setf (gethash mail-address gravatar--cache)
(cons (time-convert (current-time) 'integer)
image)))
(prog1
(apply callback (if data image 'error) cbargs)
(kill-buffer))))
nil t))))))
(defun gravatar--prune-cache ()
(let ((expired nil)
(time (- (time-convert (current-time) 'integer)
;; Twelve hours.
(* 12 60 60))))
(maphash (lambda (key val)
(when (< (car val) time)
(push key expired)))
gravatar--cache)
(dolist (key expired)
(remhash key gravatar--cache))))
;;;###autoload ;;;###autoload
(defun gravatar-retrieve-synchronously (mail-address) (defun gravatar-retrieve-synchronously (mail-address)
@ -229,10 +262,8 @@ retrieval failed."
(gravatar-build-url mail-address (lambda (u) (setq url u))) (gravatar-build-url mail-address (lambda (u) (setq url u)))
(while (not url) (while (not url)
(sleep-for 0.01)) (sleep-for 0.01))
(with-current-buffer (if (url-cache-expired url gravatar-cache-ttl) (with-current-buffer (url-retrieve-synchronously url t)
(url-retrieve-synchronously url t) (gravatar-retrieved nil #'identity))))
(url-fetch-from-cache url))
(gravatar-retrieved () #'identity))))
(defun gravatar-retrieved (status cb &optional cbargs) (defun gravatar-retrieved (status cb &optional cbargs)
"Handle Gravatar response data in current buffer. "Handle Gravatar response data in current buffer.
@ -241,10 +272,6 @@ an image descriptor, or the symbol `error' on failure.
This function is intended as a callback for `url-retrieve'." This function is intended as a callback for `url-retrieve'."
(let ((data (unless (plist-get status :error) (let ((data (unless (plist-get status :error)
(gravatar-get-data)))) (gravatar-get-data))))
(and data ; Only cache on success.
url-current-object ; Only cache if not already cached.
gravatar-automatic-caching
(url-store-in-cache))
(prog1 (apply cb (if data (create-image data nil t) 'error) cbargs) (prog1 (apply cb (if data (create-image data nil t) 'error) cbargs)
(kill-buffer)))) (kill-buffer))))