diff options
| author | Craig Jennings <c@cjennings.net> | 2026-05-10 14:48:25 -0500 |
|---|---|---|
| committer | Craig Jennings <c@cjennings.net> | 2026-05-10 14:48:25 -0500 |
| commit | a7071b13d5a3309e28ee03e33acc526d7eaed810 (patch) | |
| tree | b79b547a581646ab04eb784f16bec840b1e3c51a /modules/org-agenda-config.el | |
| parent | eb512124d9d587f9f26a17e9031f30a2cfff9476 (diff) | |
| download | dotemacs-a7071b13d5a3309e28ee03e33acc526d7eaed810.tar.gz dotemacs-a7071b13d5a3309e28ee03e33acc526d7eaed810.zip | |
refactor(org-agenda): migrate to cj-cache helper
Phase 5 step 2 of utility-consolidation. The agenda-files cache (four module-level vars + 35-line build-with-cache function) now delegates to `cj-cache.el'. Behavior preserved: cache-hit logging, "Building..." background message, building-flag cleanup on error.
Add `cj/--org-agenda-scan-files' as a pure-ish helper that returns the file list (the slow filesystem walk). `cj/build-org-agenda-list' becomes a thin wrapper that calls `cj/cache-value-or-rebuild' with the scan helper as BUILD-FN and routes the original log lines through :on-hit / :on-build-success.
Drop four module-level state vars:
- `cj/org-agenda-files-cache'
- `cj/org-agenda-files-cache-time'
- `cj/org-agenda-files-cache-ttl'
- `cj/org-agenda-files-building'
Replace with a single `cj/--org-agenda-files-cache' plist held by the helper.
Rewrite the existing test file to test wrapper behavior at the contract level (stub the scan helper, verify wrapper outcomes) instead of poking at internal state vars. 8 tests cover first-call builds, second-call uses cache, force-rebuild bypass, TTL expiration, empty scan, building-flag cleanup on success and error, and error propagation.
Diffstat (limited to 'modules/org-agenda-config.el')
| -rw-r--r-- | modules/org-agenda-config.el | 84 |
1 files changed, 33 insertions, 51 deletions
diff --git a/modules/org-agenda-config.el b/modules/org-agenda-config.el index 9205cf1c..049ece7b 100644 --- a/modules/org-agenda-config.el +++ b/modules/org-agenda-config.el @@ -44,6 +44,7 @@ ;;; Code: (require 'user-constants) (require 'system-lib) +(require 'cj-cache) ;; Load debug functions if enabled (when (or (eq cj/debug-modules t) @@ -82,21 +83,11 @@ #'org-agenda-todo-previousset)))) ;; ------------------------ Org Agenda File List Cache ------------------------- -;; Cache agenda file list to avoid expensive directory scanning on every view +;; Cache agenda file list to avoid expensive directory scanning on every view. +;; The TTL+building cache lifecycle is provided by `cj-cache.el'. -(defvar cj/org-agenda-files-cache nil - "Cached agenda files list to avoid expensive directory scanning. -Set to nil to invalidate cache.") - -(defvar cj/org-agenda-files-cache-time nil - "Time when agenda files cache was last built.") - -(defvar cj/org-agenda-files-cache-ttl 3600 - "Time-to-live for agenda files cache in seconds (default: 1 hour).") - -(defvar cj/org-agenda-files-building nil - "Non-nil when agenda files are being built asynchronously. -Prevents duplicate builds if user opens agenda before async build completes.") +(defvar cj/--org-agenda-files-cache (cj/cache-make :ttl 3600) + "Cache state for the agenda files list. See `cj-cache.el'.") ;; ------------------------ Add Files To Org Agenda List ----------------------- ;; Checks immediate subdirectories of DIRECTORY for todo.org files and adds @@ -118,6 +109,17 @@ Only checks DIRECTORY/*/todo.org — does not recurse deeper." ;; builds the org agenda list from all agenda targets with caching. ;; agenda targets is the schedule, contacts, project todos, ;; inbox, and org roam projects. +(defun cj/--org-agenda-scan-files () + "Scan disk for the agenda files list. Pure-ish: no caching, no logging. +Returns the list to assign to `org-agenda-files'. Slow -- walks +`projects-dir' for per-project todo.org files." + (let ((files (list inbox-file schedule-file gcal-file pcal-file dcal-file))) + ;; cj/add-files-to-org-agenda-files-list mutates org-agenda-files; let-bind + ;; it for the duration of the helper, then return whatever it produced. + (let ((org-agenda-files files)) + (cj/add-files-to-org-agenda-files-list projects-dir) + org-agenda-files))) + (defun cj/build-org-agenda-list (&optional force-rebuild) "Build org-agenda-files list with caching. @@ -127,43 +129,23 @@ Otherwise, returns cached list if available and not expired. This function scans projects-dir for todo.org files, so caching improves performance from several seconds to instant." (interactive "P") - ;; Check if we can use cache - (let ((cache-valid (and cj/org-agenda-files-cache - cj/org-agenda-files-cache-time - (not force-rebuild) - (< (- (float-time) cj/org-agenda-files-cache-time) - cj/org-agenda-files-cache-ttl)))) - (if cache-valid - ;; Use cached file list (instant) - (progn - (setq org-agenda-files cj/org-agenda-files-cache) - ;; Always show cache-hit message (interactive or background) - (cj/log-silently "Using cached agenda files (%d files)" - (length org-agenda-files))) - ;; Check if async build is in progress - (when cj/org-agenda-files-building - (cj/log-silently "Waiting for background agenda build to complete...")) - ;; Rebuild from scratch (slow - scans projects directory) - (unwind-protect - (progn - (setq cj/org-agenda-files-building t) - (let ((start-time (current-time))) - ;; Reset org-agenda-files to base files - (setq org-agenda-files (list inbox-file schedule-file gcal-file pcal-file dcal-file)) - - ;; Check all projects for scheduled tasks - (cj/add-files-to-org-agenda-files-list projects-dir) - - ;; Update cache - (setq cj/org-agenda-files-cache org-agenda-files) - (setq cj/org-agenda-files-cache-time (float-time)) - - ;; Always show completion message (interactive or background) - (cj/log-silently "Built agenda files: %d files in %.3f sec" - (length org-agenda-files) - (- (float-time) (float-time start-time))))) - ;; Always clear the building flag, even if build fails - (setq cj/org-agenda-files-building nil))))) + (when (cj/cache-building-p cj/--org-agenda-files-cache) + (cj/log-silently "Waiting for background agenda build to complete...")) + (let* ((start-time (current-time)) + (files + (cj/cache-value-or-rebuild + cj/--org-agenda-files-cache + #'cj/--org-agenda-scan-files + :force-rebuild force-rebuild + :on-hit (lambda (v) + (cj/log-silently "Using cached agenda files (%d files)" + (length v))) + :on-build-success + (lambda (v) + (cj/log-silently "Built agenda files: %d files in %.3f sec" + (length v) + (- (float-time) (float-time start-time))))))) + (setq org-agenda-files files))) ;; Build cache asynchronously after startup to avoid blocking Emacs (run-with-idle-timer |
