iens

Manager of links to read
git clone https://git.instinctive.eu/iens.git
Log | Files | Refs | README | LICENSE

commit fbdafcf4dc0f8074c3f87e2ff52eb95afc03110c
parent 39ce128a3b6821447c5e9464554382d7a76dc0df
Author: Natasha Kerensikova <natgh@instinctive.eu>
Date:   Sat,  9 Mar 2024 13:22:43 +0000

Feed signatures and basic caching
Diffstat:
Msrc/iens.scm | 86+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 86 insertions(+), 0 deletions(-)

diff --git a/src/iens.scm b/src/iens.scm @@ -331,6 +331,92 @@ (trace `(touch-feed ,mtime ,feed-id)) (exec (sql db "UPDATE feed SET mtime=? WHERE id=?;") mtime feed-id)) +;; Feed Caching + +(define (build-signature selector) + (query fetch-rows + (sql db (string-append "SELECT id,mtime FROM entry " selector ";")))) + +(define (car< a b) (< (car a) (car b))) + +(define (diff-signature old-sig new-sig) + (let loop ((old (sort old-sig car<)) + (new (sort new-sig car<)) + (result '())) + (cond ((and (null? old) (null? new)) + result) + ((null? old) + (loop old + (cdr new) + (cons `(add ,@(car new)) result))) + ((null? new) + (loop (cdr old) + new + (cons `(del ,@(car old)) result))) + ((equal? (car new) (car old)) + (loop (cdr old) + (cdr new) + result)) + ((= (caar new) (caar old)) + (loop (cdr old) + (cdr new) + (cons `(chg ,@(car old) ,(cadar new)) result))) + ((< (caar new) (caar old)) + (loop old + (cdr new) + (cons `(add ,@(car new)) result))) + ((> (caar new) (caar old)) + (loop (cdr old) + new + (cons `(del ,@(car old)) result))) + (else (assert #f "Should be unreachable"))))) + +(define (write-diff sig-diff) + (for-each + (lambda (hunk) + (cond ((eqv? (car hunk) 'add) + (write-line (conc " added item #" (cadr hunk) + " at " (rfc-3339 (caddr hunk))))) + ((eqv? (car hunk) 'del) + (write-line (conc " removed item #" (cadr hunk) + " at " (rfc-3339 (caddr hunk))))) + ((eqv? (car hunk) 'chg) + (write-line (conc " updated item #" (cadr hunk) + ": " (rfc-3339 (caddr hunk)) + " → " (rfc-3339 (cadddr hunk))))) + (else (assert #f "Should be unreachable")))) + sig-diff)) + +(define feed-cache + (query (map-rows* (lambda (id selector) + (cons id (build-signature selector)))) + (sql db "SELECT id,selector FROM feed WHERE active=1;"))) + +(define (check-feed* id) + (let ((new (query fetch-value + (sql db "SELECT selector FROM feed WHERE id=?;") + id)) + (old (alist-ref id feed-cache = '()))) + (cond ((and (not new) (null? old)) + (write-line (conc "Feed #" id " does not exist"))) + ((not new) + (write-line (conc "Feed #" id " does not exist anymore"))) + ((null? old) + (write-line (conc "Feed #" id " is not cached"))) + (else + (let ((sig-diff (diff-signature old (build-signature new)))) + (if (null? sig-diff) + (write-line (conc "Feed #" id " has not changed")) + (write-line (conc "Feed #" id " was modified:"))) + (write-diff sig-diff)))))) + +(defcmd (check-feed . args) + "[feed-id ...]" "Check the cache for the given feeds, or all active feeds" + (for-each check-feed* + (if (null? args) + (query fetch-column (sql db "SELECT id FROM feed WHERE active=1;")) + args))) + ;; Tag Management (define (set-tag-auto name auto)