Last active
May 21, 2024 12:32
-
-
Save akashpal-21/5991e99949af5feb0f75729374ce3d66 to your computer and use it in GitHub Desktop.
org-roam-node-cache.el
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
;; org-roam-node-cache.el | |
;; When `org-roam-node-read' is called -- | |
;; `org-roam-node-read--completions' is initiated which fetches the list of struct nodes, applies FILTER-FN if any, | |
;; then formats them as specified by `org-roam-node-display-template' and finally | |
;; after sorting according to `org-roam-node-default-sort' or user SORT-FN | |
;; passes this final list further down. | |
;; `org-roam-node-read--completions' makes two subcalls - | |
;; A. To `org-roam-node-list' which queries the db and generates a nodes struct for each node. | |
;; B. To `org-roam-node-read--to-candidate' which formats the struct nodes according to the display template | |
;; Processes ranked most expensive to least expensive | |
;; 1. `org-roam-node-read--to-candidate' -- final formatting | |
;; 2. `org-roam-node-list' -- initial formatting & db query | |
;; 3. rest of `org-roam-node-read--completions' (filtering and sorting) | |
;; By default Basic cache is enabled. | |
(defcustom org-roam-node-cache-level 1 | |
"Level of caching for Org-roam nodes. | |
1: Basic cache (cache candidate formatting only). | |
2: Partial cache (cache candidate formatting & node list). | |
3: Full cache (cache candidate formatting, node list, filter-function & sort-function). | |
If changed when `org-roam-node-cache-mode' is active - restart mode." | |
:group 'org-roam | |
:type '(choice (const :tag "Basic cache" 1) | |
(const :tag "Partial cache" 2) | |
(const :tag "Full cache" 3))) | |
; Definitions | |
(defvar org-roam-node-cache-candidate-format (make-hash-table :test 'equal) | |
"The Cache of candidate formatting") | |
(defvar org-roam-node-cache-time nil | |
"Time when the node-cache was taken") | |
(defvar org-roam-node-cache-list nil | |
"The Cache of Org-roam nodes") | |
(defvar org-roam-node-cache-candidate-list nil | |
"The Cache of final candidate list") | |
(defvar org-roam-node-cache-prev-filter-fn nil | |
"Store the last FILTER-FN if any") | |
(defvar org-roam-node-cache-prev-sort-fn nil | |
"Store the last SORT-FN if any") | |
(defun cached/org-roam-node-read--to-candidate (fn &rest args) | |
(or (gethash args org-roam-node-cache-candidate-format) | |
(let ((result (apply fn args))) | |
(puthash args result org-roam-node-cache-candidate-format) | |
result))) | |
(defun cached/org-roam-node-list (fn &optional force-refresh &rest args) | |
;; Node list Cache nullification logic | |
(unless (and (not force-refresh) | |
org-roam-node-cache-time | |
org-roam-node-cache-list | |
(time-less-p | |
(file-attribute-modification-time (file-attributes org-roam-db-location)) | |
org-roam-node-cache-time)) | |
(setq org-roam-node-cache-list (apply fn args)) | |
(setq org-roam-node-cache-time (current-time))) | |
org-roam-node-cache-list) | |
(defun cached/org-roam-node-read--completions (fn &optional filter-fn sort-fn &rest args) | |
(let ((sort-fn (or sort-fn | |
(when org-roam-node-default-sort | |
(intern (concat "org-roam-node-read-sort-by-" | |
(symbol-name org-roam-node-default-sort))))))) | |
;; Final Candidate cache nullification or changed FILTER-FN processing logic | |
(unless (and (eq filter-fn org-roam-node-cache-prev-filter-fn) | |
org-roam-node-cache-time | |
org-roam-node-cache-candidate-list | |
(time-less-p | |
(file-attribute-modification-time (file-attributes org-roam-db-location)) | |
org-roam-node-cache-time)) | |
(setq org-roam-node-cache-candidate-list (apply fn filter-fn sort-fn args)) | |
(setq org-roam-node-cache-time (current-time)) | |
(setq org-roam-node-cache-prev-filter-fn filter-fn) | |
(setq org-roam-node-cache-prev-sort-fn sort-fn)) | |
;; Changed SORT-FN processing logic | |
(unless (eq sort-fn org-roam-node-cache-prev-sort-fn) | |
(when sort-fn | |
(setq org-roam-node-cache-candidate-list (funcall #'seq-sort sort-fn org-roam-node-cache-candidate-list)) | |
(setq org-roam-node-cache-prev-sort-fn sort-fn))) | |
org-roam-node-cache-candidate-list)) | |
(defun org-roam-node-cache-initialize (&optional level) | |
"Initialize Org-roam node caching based on `org-roam-node-cache-level'." | |
(org-roam-node-cache-deactivate) ; start at clean slate | |
(let ((cache-level (or level org-roam-node-cache-level))) | |
(when (>= cache-level 1) | |
;; Basic Cache | |
(advice-add 'org-roam-node-read--to-candidate :around #'cached/org-roam-node-read--to-candidate)) | |
(when (>= cache-level 2) | |
;; Partial Cache | |
(advice-add 'org-roam-node-list :around #'cached/org-roam-node-list)) | |
(when (>= cache-level 3) | |
;; Full Cache | |
(advice-add 'org-roam-node-read--completions :around #'cached/org-roam-node-read--completions)))) | |
(defun org-roam-node-cache-deactivate () | |
"Disable any node cache if active" | |
(advice-remove 'org-roam-node-read--to-candidate #'cached/org-roam-node-read--to-candidate) | |
(advice-remove 'org-roam-node-list #'cached/org-roam-node-list) | |
(advice-remove 'org-roam-node-read--completions #'cached/org-roam-node-read--completions)) | |
;;;### autoload | |
(define-minor-mode org-roam-node-cache-mode | |
"Global minor mode to Cache org-roam nodes | |
Define cache level in `org-roam-node-cache-level'." | |
:init-value nil | |
:global t | |
(cond | |
(org-roam-node-cache-mode | |
(org-roam-node-cache-initialize)) | |
(t | |
(org-roam-node-cache-deactivate)))) | |
(provide 'org-roam-node-cache) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment