perf(moderation): O(1) hidden count, index hidden folder prefixes (P2)
ober
adf7e709dec967169ffb5faa719b4e832ceee862
--- a/src/imagesite/moderation.ss +++ b/src/imagesite/moderation.ss @@ -57,19 +57,37 @@ (sort (map car (hash->list hidden)) string<?)) (def (hidden-media-count hidden) - (length (hidden-media-paths hidden))) + (hash-length hidden)) + +;; Cache of (hidden-table . folder-entry-list) keyed by table identity, so +;; hidden-path? scans only the folder entries (not every hidden media path) and +;; rebuilds that short list once per hidden table rather than once per media +;; checked. The cached table is read in one snapshot to stay consistent under +;; concurrent requests; a miss simply recomputes. +(def *hidden-folder-cache* (cons #f '())) + +(def (hidden-folder-prefixes hidden) + (let ((cached *hidden-folder-cache*)) + (if (eq? (car cached) hidden) + (cdr cached) + (let ((folders (let loop ((entries (hash->list hidden)) (out '())) + (cond + ((null? entries) (reverse out)) + ((hidden-folder-entry? (car (car entries))) + (loop (cdr entries) (cons (car (car entries)) out))) + (else (loop (cdr entries) out)))))) + (set! *hidden-folder-cache* (cons hidden folders)) + folders)))) (def (hidden-path? hidden rel) (and hidden (safe-relative-path? rel) (or (hash-key? hidden rel) - (let loop ((entries (hash->list hidden))) + (let loop ((folders (hidden-folder-prefixes hidden))) (cond - ((null? entries) #f) - ((let ((entry (car (car entries)))) - (and (hidden-folder-entry? entry) - (string-prefix? entry rel))) #t) - (else (loop (cdr entries)))))))) + ((null? folders) #f) + ((string-prefix? (car folders) rel) #t) + (else (loop (cdr folders)))))))) (def (hidden-media? hidden rel) (hidden-path? hidden rel))