Overview
Comment: | Make cache db connection thread-safe |
---|---|
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA3-256: |
37240160dc8996b6a458287746c3f82b |
User & Date: | joel on 2020-02-20 03:16:19 |
Other Links: | manifest | tags |
References
2020-02-20
| ||
04:41 | Update code docs for cache to reflect [37240160] check-in: c18bd9b3 user: joel tags: trunk | |
Context
2020-02-20
| ||
04:29 | Refactor listing functions (see [8ad560204]) check-in: 3be7a3ab user: joel tags: trunk | |
03:16 | Make cache db connection thread-safe check-in: 37240160 user: joel tags: trunk | |
03:00 | Use new init script & revise makefile to ensure series info is accurate after a clean rebuild check-in: c8598882 user: joel tags: trunk | |
Changes
Modified cache.rkt from [3c46d95b] to [8c1589ae].
︙ | ︙ | |||
32 33 34 35 36 37 38 | unfence preheat-series! series-grouped-list) ;; Cache DB and Schemas (define DBFILE (build-path (current-project-root) "vitreous.sqlite")) | | | 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | unfence preheat-series! series-grouped-list) ;; Cache DB and Schemas (define DBFILE (build-path (current-project-root) "vitreous.sqlite")) (define cache-conn (make-parameter (sqlite3-connect #:database DBFILE #:mode 'create))) (define current-plain-title (make-parameter "void")) (define-schema cache:article #:table "articles" ([id id/f #:primary-key #:auto-increment] [page symbol/f] [title-plain string/f] |
︙ | ︙ | |||
95 96 97 98 99 100 101 | (define-schema listing #:virtual ([html string/f] [published date/f] [series-page symbol/f])) (define (init-cache-db!) | | | | | | | | 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 | (define-schema listing #:virtual ([html string/f] [published date/f] [series-page symbol/f])) (define (init-cache-db!) (create-table! (cache-conn) 'cache:article) (create-table! (cache-conn) 'cache:note) (create-table! (cache-conn) 'cache:series) (create-table! (cache-conn) 'cache:index-entry)) (define (delete-article! page) (query-exec (cache-conn) (~> (from cache:article #:as a) (where (= a.page ,(format "~a" page))) delete))) (define (delete-notes! page) (query-exec (cache-conn) (~> (from cache:note #:as n) (where (= n.page ,(format "~a" page))) delete))) ;; ;; ~~~ Fetching articles and notes ~~~ ;; |
︙ | ︙ | |||
177 178 179 180 181 182 183 | (where-not-concealed) (limit ,lim) (order-by ([a.published ,ord])) (project-onto listing-schema))) ;; Get all the a list of the HTML all the results in a query (define (listing-htmls list-query) | | | 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 | (where-not-concealed) (limit ,lim) (order-by ([a.published ,ord])) (project-onto listing-schema))) ;; Get all the a list of the HTML all the results in a query (define (listing-htmls list-query) (for/list ([l (in-entities (cache-conn) list-query)]) (listing-html l))) ;; Return cached HTML of articles and/or notes, fenced within a style txexpr to prevent it being ;; escaped by ->html. See also: definition of `unfence` ;; E.g.: (<listing-full> articles+notes) (define (<listing-full> query-func #:series [s #t] #:limit [lim -1] #:order [ord 'desc]) |
︙ | ︙ | |||
205 206 207 208 209 210 211 | (define (unfence html-str) (regexp-replace* #px"<[\\/]{0,1}style>" html-str "")) ;; ;; ~~~ Fetching series ~~~ ;; (define (series-grouped-list) | | | | | 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 | (define (unfence html-str) (regexp-replace* #px"<[\\/]{0,1}style>" html-str "")) ;; ;; ~~~ Fetching series ~~~ ;; (define (series-grouped-list) (~> (for/list ([row (in-entities (cache-conn) (from cache:series #:as s))]) row) (group-list-by cache:series-noun-plural _ string-ci=?))) ;; Preloads the SQLite cache with info about each series. ;; I may not actually need this but I’m leaving it for now. (define (preheat-series!) (query-exec (cache-conn) (~> (from cache:series #:as s) (where 1) delete)) (define series-rows (for/list ([series-pagenode (in-list (cdr (series-pagetree)))]) (define series-metas (get-metas series-pagenode)) (make-cache:series #:page series-pagenode #:title (hash-ref series-metas 'title) #:published (hash-ref series-metas 'published "") #:noun-plural (hash-ref series-metas 'noun-plural "") #:noun-singular (hash-ref series-metas 'noun-singular "")))) (void (apply insert! (cache-conn) series-rows))) |
Modified crystalize.rkt from [c41782ea] to [271e4525].
︙ | ︙ | |||
8 9 10 11 12 13 14 | db/sqlite3 threading racket/match racket/string txexpr pollen/template (except-in pollen/core select) ; avoid conflict with deta | | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | db/sqlite3 threading racket/match racket/string txexpr pollen/template (except-in pollen/core select) ; avoid conflict with deta ) (require "dust.rkt" "cache.rkt" "snippets-html.rkt") (provide parse-and-cache-article! cache-series!) ;; Save an article and its notes (if any) to the database, and return the |
︙ | ︙ | |||
45 46 47 48 49 50 51 | (length note-txprs))] [footer (html$-article-close footertext)] [listing-short (html$-article-listing-short pagenode pubdate title-html)] [notes-section-html (cache-notes! pagenode title-plain note-txprs)]) (cache-index-entries! pagenode doc) ; note original doc is used here (current-plain-title title-plain) (delete-article! pagenode) | | | 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | (length note-txprs))] [footer (html$-article-close footertext)] [listing-short (html$-article-listing-short pagenode pubdate title-html)] [notes-section-html (cache-notes! pagenode title-plain note-txprs)]) (cache-index-entries! pagenode doc) ; note original doc is used here (current-plain-title title-plain) (delete-article! pagenode) (insert-one! (cache-conn) (make-cache:article #:page pagenode #:title-plain title-plain #:title-html-flow title-html #:title-specified? title-specified? #:published pubdate #:updated (maybe-meta 'updated) |
︙ | ︙ | |||
128 129 130 131 132 133 134 | (cond [(ormap non-empty-string? (list series-part disp-part notes-part)) (string-join (list series-part disp-part notes-part))] [else ""])) ;; ~~~ Notes ~~~ (define (cache-notes! pagenode parent-title note-txprs) | | | | 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 | (cond [(ormap non-empty-string? (list series-part disp-part notes-part)) (string-join (list series-part disp-part notes-part))] [else ""])) ;; ~~~ Notes ~~~ (define (cache-notes! pagenode parent-title note-txprs) (query-exec (cache-conn) (delete (~> (from cache:note #:as n) (where (= n.page ,(symbol->string pagenode)))))) (cond [(not (null? note-txprs)) (define note-htmls (for/list ([n (in-list note-txprs)]) (cache-note! n pagenode parent-title))) (html$-notes-section note-htmls)] [else ""])) |
︙ | ︙ | |||
160 161 162 163 164 165 166 | (define-values (disp-mark disp-verb) (disposition-values disposition-attr)) (let* ([note-id (build-note-id note-tx)] [title-tx (make-note-title pagenode parent-title-plain)] [title-html (->html title-tx #:splice? #t)] [author (maybe-attr 'author attrs default-authorname)] [author-url (maybe-attr 'author-url attrs)] [content-html (html$-note-contents disp-mark disp-verb elems)]) | | | 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 | (define-values (disp-mark disp-verb) (disposition-values disposition-attr)) (let* ([note-id (build-note-id note-tx)] [title-tx (make-note-title pagenode parent-title-plain)] [title-html (->html title-tx #:splice? #t)] [author (maybe-attr 'author attrs default-authorname)] [author-url (maybe-attr 'author-url attrs)] [content-html (html$-note-contents disp-mark disp-verb elems)]) (insert-one! (cache-conn) (make-cache:note #:page pagenode #:html-anchor note-id #:title-html-flow title-html #:title-plain (tx-strs title-tx) #:published note-date #:author author |
︙ | ︙ | |||
220 221 222 223 224 225 226 | #:html-anchor (attr-ref tx 'id))])) ;; Save any index entries in doc to the SQLite cache. ;; Sub-entries are specified by "!" in the index key (define (cache-index-entries! pagenode doc) (define-values (_ entry-txs) (splitf-txexpr doc index-entry-txpr?)) ; Naive idempotence: delete and re-insert all index entries every time doc is rendered. | | | | | | | 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 | #:html-anchor (attr-ref tx 'id))])) ;; Save any index entries in doc to the SQLite cache. ;; Sub-entries are specified by "!" in the index key (define (cache-index-entries! pagenode doc) (define-values (_ entry-txs) (splitf-txexpr doc index-entry-txpr?)) ; Naive idempotence: delete and re-insert all index entries every time doc is rendered. (query-exec (cache-conn) (delete (~> (from cache:index-entry #:as entry) (where (= entry.page ,(symbol->string pagenode)))))) (unless (null? entry-txs) (void (apply insert! (cache-conn) (for/list ([etx (in-list entry-txs)]) (txexpr->index-entry etx pagenode)))))) ;; Save the current article to the `series` table of the SQLite cache ;; Should be called from a template for series pages (define (cache-series!) (define here-page (path->string (here-output-path))) (query-exec (cache-conn) (delete (~> (from cache:series #:as s) (where (= s.page ,here-page))))) (void (insert-one! (cache-conn) (make-cache:series #:page (string->symbol here-page) #:title (hash-ref (current-metas) 'title) #:published (hash-ref (current-metas) 'published "") #:noun-plural (hash-ref (current-metas) 'noun-plural "") #:noun-singular (hash-ref (current-metas) 'noun-singular ""))))) |
Modified keyword-index.rkt from [d37c4752] to [f1c17ea2].
︙ | ︙ | |||
104 105 106 107 108 109 110 | (define (fetch-entries) (define q ◊string-append{ SELECT entry, subentry, a.rowid, "◊web-root" || k.page || "#" || html_anchor AS href, title_plain FROM index_entries k INNER JOIN articles a ON a.page = k.page ORDER BY entry COLLATE NOCASE ASC, subentry COLLATE NOCASE ASC;}) | | | 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 | (define (fetch-entries) (define q ◊string-append{ SELECT entry, subentry, a.rowid, "◊web-root" || k.page || "#" || html_anchor AS href, title_plain FROM index_entries k INNER JOIN articles a ON a.page = k.page ORDER BY entry COLLATE NOCASE ASC, subentry COLLATE NOCASE ASC;}) (query-rows (cache-conn) q)) ;; Convert a list of vectors from the cache DB into a list of the form: ;; ((FIRST-LETTER (entries ...)) ...) ;; The method relies on the records being pre-sorted by the SQL query. (define (group-entries records) (define collated (for/fold ([entries (list (new-entry (first records)))] |
︙ | ︙ |
Modified rss-feed.rkt from [502871b7] to [c66da8d8].
︙ | ︙ | |||
62 63 64 65 66 67 68 | "" AS `updated`, `author`, `content_html` as `entry_contents` FROM `notes` WHERE (NOT (`conceal` LIKE "%all%")) AND (NOT (`conceal` LIKE "%feed%"))) ORDER BY `published` DESC LIMIT ~a --- ) | | | 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 | "" AS `updated`, `author`, `content_html` as `entry_contents` FROM `notes` WHERE (NOT (`conceal` LIKE "%all%")) AND (NOT (`conceal` LIKE "%feed%"))) ORDER BY `published` DESC LIMIT ~a --- ) (query-rows (cache-conn) (format select feed-item-limit))) (define (vector->rss-item vec) (match-define (vector path title published updated author contents) vec) (define entry-url (string-append feed-site-url web-root path)) (define update-ts (cond [(non-empty-string? updated) updated] |
︙ | ︙ |