aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCraig Jennings <c@cjennings.net>2026-04-04 13:24:01 -0500
committerCraig Jennings <c@cjennings.net>2026-04-04 13:24:01 -0500
commit752e2f825b1ee3eb513e27f2c03bcaef30eec767 (patch)
treeebcc6628d778489b2c6c45e80d429499fcfaebf1
parent821c7c1ded6bef400dcfda9aec27832f116ce369 (diff)
downloademacs-wttrin-752e2f825b1ee3eb513e27f2c03bcaef30eec767.tar.gz
emacs-wttrin-752e2f825b1ee3eb513e27f2c03bcaef30eec767.zip
fix: cache timestamp reflects request time, not response time
float-time was captured in the outer let* before the async fetch. The callback used this stale value, making cache entries appear slightly older than they are. Move the float-time call into the callback so the timestamp reflects when the data actually arrived.
-rw-r--r--tests/test-wttrin--get-cached-or-fetch.el28
-rw-r--r--wttrin.el5
2 files changed, 30 insertions, 3 deletions
diff --git a/tests/test-wttrin--get-cached-or-fetch.el b/tests/test-wttrin--get-cached-or-fetch.el
index fa6b9d0..75b4e8b 100644
--- a/tests/test-wttrin--get-cached-or-fetch.el
+++ b/tests/test-wttrin--get-cached-or-fetch.el
@@ -328,5 +328,33 @@ Proactive refresh keeps data fresh; on-demand reads always use cache."
(should (equal callback-result test-wttrin--get-cached-or-fetch-new-weather))))
(test-wttrin--get-cached-or-fetch-teardown)))
+(ert-deftest test-wttrin--get-cached-or-fetch-normal-timestamp-reflects-response-time ()
+ "Cache timestamp should reflect when the response arrived, not when
+the request was initiated. A stale request-time timestamp would make
+the cached data appear older than it actually is."
+ (test-wttrin--get-cached-or-fetch-setup)
+ (unwind-protect
+ (let* ((location "Paris")
+ (cache-key (wttrin--make-cache-key location))
+ (response-time 5000.0))
+ (cl-letf (((symbol-function 'float-time)
+ (lambda () response-time))
+ ((symbol-function 'wttrin-fetch-raw-string)
+ (lambda (_query callback)
+ ;; Simulate time passing: response arrives later
+ (setq response-time 5005.0)
+ (funcall callback "fresh data")))
+ ((symbol-function 'wttrin--cleanup-cache-if-needed)
+ (lambda () nil)))
+ (let ((wttrin--force-refresh t))
+ (wttrin--get-cached-or-fetch
+ location
+ (lambda (_data) nil)))
+ ;; Timestamp should be 5005 (when callback ran), not 5000 (when request started)
+ (let ((cached (gethash cache-key wttrin--cache)))
+ (should cached)
+ (should (= (car cached) 5005.0)))))
+ (test-wttrin--get-cached-or-fetch-teardown)))
+
(provide 'test-wttrin--get-cached-or-fetch)
;;; test-wttrin--get-cached-or-fetch.el ends here
diff --git a/wttrin.el b/wttrin.el
index d95f0c2..c2cb74d 100644
--- a/wttrin.el
+++ b/wttrin.el
@@ -444,8 +444,7 @@ regardless of age. The background refresh timer keeps data fresh.
CALLBACK is called with the weather data string when ready, or nil on error."
(let* ((cache-key (wttrin--make-cache-key location))
(cached (gethash cache-key wttrin--cache))
- (data (cdr cached))
- (now (float-time)))
+ (data (cdr cached)))
(if (and cached (not wttrin--force-refresh))
;; Return cached data immediately regardless of age
(funcall callback data)
@@ -456,7 +455,7 @@ CALLBACK is called with the weather data string when ready, or nil on error."
(if fresh-data
(progn
(wttrin--cleanup-cache-if-needed)
- (puthash cache-key (cons now fresh-data) wttrin--cache)
+ (puthash cache-key (cons (float-time) fresh-data) wttrin--cache)
(funcall callback fresh-data))
;; On error, return stale cache if available
(if cached