diff options
| author | Craig Jennings <c@cjennings.net> | 2026-06-28 03:53:24 -0400 |
|---|---|---|
| committer | Craig Jennings <c@cjennings.net> | 2026-06-28 03:53:24 -0400 |
| commit | ec38418d6d3eb4342363af1714f0073a74d52fbc (patch) | |
| tree | 1327072f95de36f0577e114fd259c8d064426619 | |
| parent | 944a52f0e33087dafba383edb3d97ec19a06d361 (diff) | |
| download | emacs-wttrin-ec38418d6d3eb4342363af1714f0073a74d52fbc.tar.gz emacs-wttrin-ec38418d6d3eb4342363af1714f0073a74d52fbc.zip | |
fix: always evict at least one cache entry when over max
wttrin--cleanup-cache-if-needed removed floor(count * 0.20) entries, which is 0
for a small cache (e.g. two entries at max one), so the cache could sit over its
advertised maximum indefinitely. It now removes at least one whenever it is over.
| -rw-r--r-- | tests/test-wttrin--cleanup-cache-if-needed.el | 9 | ||||
| -rw-r--r-- | wttrin.el | 7 |
2 files changed, 9 insertions, 7 deletions
diff --git a/tests/test-wttrin--cleanup-cache-if-needed.el b/tests/test-wttrin--cleanup-cache-if-needed.el index 1850d17..7533bfa 100644 --- a/tests/test-wttrin--cleanup-cache-if-needed.el +++ b/tests/test-wttrin--cleanup-cache-if-needed.el @@ -108,16 +108,17 @@ (should (= 1 (testutil-wttrin-cache-size)))) (test-wttrin--cleanup-cache-if-needed-teardown))) -(ert-deftest test-wttrin--cleanup-cache-if-needed-boundary-two-entries-at-max-one-removes-none () - "Test that two entries at max=1 removes no entries due to integer division." +(ert-deftest test-wttrin--cleanup-cache-if-needed-boundary-two-entries-at-max-one-reduces-to-max () + "Boundary: two entries at max=1 reduces to the max. +floor(2 * 0.20) is 0, but cleanup must still remove at least one entry when the +cache is over max, or it would exceed its advertised maximum indefinitely." (test-wttrin--cleanup-cache-if-needed-setup) (unwind-protect (testutil-wttrin-with-cache-max 1 (testutil-wttrin-add-to-cache "old" "data1" 100) (testutil-wttrin-add-to-cache "new" "data2" 50) (wttrin--cleanup-cache-if-needed) - ;; 2 entries / 5 = 0 in integer division, so no entries removed - (should (= 2 (testutil-wttrin-cache-size)))) + (should (= 1 (testutil-wttrin-cache-size)))) (test-wttrin--cleanup-cache-if-needed-teardown))) (ert-deftest test-wttrin--cleanup-cache-if-needed-boundary-one-over-max-removes-oldest () @@ -1283,12 +1283,13 @@ Returns a list where each element is a cons cell (key . timestamp)." (defun wttrin--cleanup-cache-if-needed () "Remove oldest entries if cache exceeds max size. Removes oldest entries based on `wttrin--cache-cleanup-percentage' -when cache count exceeds `wttrin-cache-max-entries'. +when cache count exceeds `wttrin-cache-max-entries', and always at least one +so the cache can't sit over its maximum when the percentage floors to zero. This creates headroom to avoid frequent cleanups." (when (> (hash-table-count wttrin--cache) wttrin-cache-max-entries) (let* ((entries-by-age (wttrin--get-cache-entries-by-age)) - (num-to-remove (floor (* (length entries-by-age) - wttrin--cache-cleanup-percentage)))) + (num-to-remove (max 1 (floor (* (length entries-by-age) + wttrin--cache-cleanup-percentage))))) (dotimes (i num-to-remove) (remhash (car (nth i entries-by-age)) wttrin--cache))))) |
