diff options
| author | Lars Ingebrigtsen | 2020-08-18 16:45:29 +0200 |
|---|---|---|
| committer | Lars Ingebrigtsen | 2020-08-18 16:45:29 +0200 |
| commit | 23e6c36645bb8f07f55ba94af21cebaaab2c91d3 (patch) | |
| tree | 37e8284749a3603fc76fa0d768002c910676c33e /lisp/image | |
| parent | 82893e9e8e0dae5cbd3ae26a7ee92896fcadfdae (diff) | |
| download | emacs-23e6c36645bb8f07f55ba94af21cebaaab2c91d3.tar.gz emacs-23e6c36645bb8f07f55ba94af21cebaaab2c91d3.zip | |
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).
Diffstat (limited to 'lisp/image')
| -rw-r--r-- | lisp/image/gravatar.el | 57 |
1 files changed, 42 insertions, 15 deletions
diff --git a/lisp/image/gravatar.el b/lisp/image/gravatar.el index d1091e57cb5..e917033562e 100644 --- a/lisp/image/gravatar.el +++ b/lisp/image/gravatar.el | |||
| @@ -39,6 +39,7 @@ | |||
| 39 | "Whether to cache retrieved gravatars." | 39 | "Whether to cache retrieved gravatars." |
| 40 | :type 'boolean | 40 | :type 'boolean |
| 41 | :group 'gravatar) | 41 | :group 'gravatar) |
| 42 | (make-obsolete-variable 'gravatar-automatic-caching nil "28.1") | ||
| 42 | 43 | ||
| 43 | (defcustom gravatar-cache-ttl 2592000 | 44 | (defcustom gravatar-cache-ttl 2592000 |
| 44 | "Time to live in seconds for gravatar cache entries. | 45 | "Time to live in seconds for gravatar cache entries. |
| @@ -48,6 +49,7 @@ is retrieved anew. The default value is 30 days." | |||
| 48 | ;; Restricted :type to number of seconds. | 49 | ;; Restricted :type to number of seconds. |
| 49 | :version "27.1" | 50 | :version "27.1" |
| 50 | :group 'gravatar) | 51 | :group 'gravatar) |
| 52 | (make-obsolete-variable 'gravatar-cache-ttl nil "28.1") | ||
| 51 | 53 | ||
| 52 | (defcustom gravatar-rating "g" | 54 | (defcustom gravatar-rating "g" |
| 53 | "Most explicit Gravatar rating level to allow. | 55 | "Most explicit Gravatar rating level to allow. |
| @@ -206,19 +208,50 @@ to track whether you're reading a specific mail." | |||
| 206 | (search-forward "\n\n" nil t) | 208 | (search-forward "\n\n" nil t) |
| 207 | (buffer-substring (point) (point-max))))) | 209 | (buffer-substring (point) (point-max))))) |
| 208 | 210 | ||
| 211 | (defvar gravatar--cache (make-hash-table :test 'equal) | ||
| 212 | "Cache for gravatars.") | ||
| 213 | |||
| 209 | ;;;###autoload | 214 | ;;;###autoload |
| 210 | (defun gravatar-retrieve (mail-address callback &optional cbargs) | 215 | (defun gravatar-retrieve (mail-address callback &optional cbargs) |
| 211 | "Asynchronously retrieve a gravatar for MAIL-ADDRESS. | 216 | "Asynchronously retrieve a gravatar for MAIL-ADDRESS. |
| 212 | When finished, call CALLBACK as (apply CALLBACK GRAVATAR CBARGS), | 217 | When finished, call CALLBACK as (apply CALLBACK GRAVATAR CBARGS), |
| 213 | where GRAVATAR is either an image descriptor, or the symbol | 218 | where GRAVATAR is either an image descriptor, or the symbol |
| 214 | `error' if the retrieval failed." | 219 | `error' if the retrieval failed." |
| 215 | (gravatar-build-url | 220 | (let ((cached (gethash mail-address gravatar--cache))) |
| 216 | mail-address | 221 | (gravatar--prune-cache) |
| 217 | (lambda (url) | 222 | (if cached |
| 218 | (if (url-cache-expired url gravatar-cache-ttl) | 223 | (apply callback (cdr cached) cbargs) |
| 219 | (url-retrieve url #'gravatar-retrieved (list callback cbargs) t) | 224 | ;; Nothing in the cache, fetch it. |
| 220 | (with-current-buffer (url-fetch-from-cache url) | 225 | (gravatar-build-url |
| 221 | (gravatar-retrieved () callback cbargs)))))) | 226 | mail-address |
| 227 | (lambda (url) | ||
| 228 | (url-retrieve | ||
| 229 | url | ||
| 230 | (lambda (status) | ||
| 231 | (let* ((data (and (not (plist-get status :error)) | ||
| 232 | (gravatar-get-data))) | ||
| 233 | (image (and data (create-image data nil t)))) | ||
| 234 | ;; Store the image in the cache. | ||
| 235 | (when image | ||
| 236 | (setf (gethash mail-address gravatar--cache) | ||
| 237 | (cons (time-convert (current-time) 'integer) | ||
| 238 | image))) | ||
| 239 | (prog1 | ||
| 240 | (apply callback (if data image 'error) cbargs) | ||
| 241 | (kill-buffer)))) | ||
| 242 | nil t)))))) | ||
| 243 | |||
| 244 | (defun gravatar--prune-cache () | ||
| 245 | (let ((expired nil) | ||
| 246 | (time (- (time-convert (current-time) 'integer) | ||
| 247 | ;; Twelve hours. | ||
| 248 | (* 12 60 60)))) | ||
| 249 | (maphash (lambda (key val) | ||
| 250 | (when (< (car val) time) | ||
| 251 | (push key expired))) | ||
| 252 | gravatar--cache) | ||
| 253 | (dolist (key expired) | ||
| 254 | (remhash key gravatar--cache)))) | ||
| 222 | 255 | ||
| 223 | ;;;###autoload | 256 | ;;;###autoload |
| 224 | (defun gravatar-retrieve-synchronously (mail-address) | 257 | (defun gravatar-retrieve-synchronously (mail-address) |
| @@ -229,10 +262,8 @@ retrieval failed." | |||
| 229 | (gravatar-build-url mail-address (lambda (u) (setq url u))) | 262 | (gravatar-build-url mail-address (lambda (u) (setq url u))) |
| 230 | (while (not url) | 263 | (while (not url) |
| 231 | (sleep-for 0.01)) | 264 | (sleep-for 0.01)) |
| 232 | (with-current-buffer (if (url-cache-expired url gravatar-cache-ttl) | 265 | (with-current-buffer (url-retrieve-synchronously url t) |
| 233 | (url-retrieve-synchronously url t) | 266 | (gravatar-retrieved nil #'identity)))) |
| 234 | (url-fetch-from-cache url)) | ||
| 235 | (gravatar-retrieved () #'identity)))) | ||
| 236 | 267 | ||
| 237 | (defun gravatar-retrieved (status cb &optional cbargs) | 268 | (defun gravatar-retrieved (status cb &optional cbargs) |
| 238 | "Handle Gravatar response data in current buffer. | 269 | "Handle Gravatar response data in current buffer. |
| @@ -241,10 +272,6 @@ an image descriptor, or the symbol `error' on failure. | |||
| 241 | This function is intended as a callback for `url-retrieve'." | 272 | This function is intended as a callback for `url-retrieve'." |
| 242 | (let ((data (unless (plist-get status :error) | 273 | (let ((data (unless (plist-get status :error) |
| 243 | (gravatar-get-data)))) | 274 | (gravatar-get-data)))) |
| 244 | (and data ; Only cache on success. | ||
| 245 | url-current-object ; Only cache if not already cached. | ||
| 246 | gravatar-automatic-caching | ||
| 247 | (url-store-in-cache)) | ||
| 248 | (prog1 (apply cb (if data (create-image data nil t) 'error) cbargs) | 275 | (prog1 (apply cb (if data (create-image data nil t) 'error) cbargs) |
| 249 | (kill-buffer)))) | 276 | (kill-buffer)))) |
| 250 | 277 | ||