host: durable lazy sessions — logins survive a restart
Sessions were in-memory, so a restart logged everyone out (same class as the relation wipe). Move them to the durable store, but LAZILY so anonymous/crawler traffic doesn't spam it: session/create mints a sid with no row; the row appears on the first session/set (a login). A per-boot epoch (one durable write at startup, host/session-init!) keeps sids unique across restarts without a write per request. - lib/host/session.sx: lazy backend (create = no row, set = create row, exists = row written) + epoch/in-memory-counter sid generation. - serve.sh: point the session store at the durable backend + host/session-init!. - blog.sx: host/current-principal is now a durable read, so host/auth-footer (home + post footers) had to move OUT of the quasiquote into let bindings — a perform during page-tree build raises VmSuspended (the whole site 500'd for a beat). Principal computed once per page. - 2 session tests: create writes no row, set creates the row. 249/249. Verified live: site renders (anon + authed), login + footer survive a container force-recreate. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -326,26 +326,28 @@
|
||||
(let ((slug (dream-param req "slug")))
|
||||
(let ((r (host/blog-get slug)))
|
||||
(if r
|
||||
;; Compute the rendered body + related block in let bindings BEFORE the
|
||||
;; quasiquote — host/blog--related-block does durable reads, and IO must
|
||||
;; happen in the handler body, not while the page tree is being built.
|
||||
(let ((body-html (host/blog-render r))
|
||||
(related-block (host/blog--related-block slug
|
||||
(not (nil? (host/current-principal req))))))
|
||||
(dream-html
|
||||
(host/blog--page (get r :title)
|
||||
(quasiquote
|
||||
(div
|
||||
(article (raw! (unquote body-html)))
|
||||
(unquote related-block)
|
||||
(p :style "margin-top:2em;font-size:0.9em;opacity:0.8"
|
||||
(a :href (unquote (str "/" slug "/source")) "view source")
|
||||
" · "
|
||||
(a :href (unquote (str "/" slug "/edit")) "edit")
|
||||
" · "
|
||||
(a :href "/" "all posts")
|
||||
" · "
|
||||
(unquote (host/auth-footer req))))))))
|
||||
;; Compute everything that does durable reads — body, related block, AND
|
||||
;; the auth footer (a durable session read now) — in let bindings BEFORE
|
||||
;; the quasiquote. IO must run in the handler body, never while the page
|
||||
;; tree is built (a perform there raises VmSuspended under http-listen).
|
||||
(let ((principal (host/current-principal req)))
|
||||
(let ((body-html (host/blog-render r))
|
||||
(related-block (host/blog--related-block slug (not (nil? principal))))
|
||||
(auth-foot (host/auth-footer req)))
|
||||
(dream-html
|
||||
(host/blog--page (get r :title)
|
||||
(quasiquote
|
||||
(div
|
||||
(article (raw! (unquote body-html)))
|
||||
(unquote related-block)
|
||||
(p :style "margin-top:2em;font-size:0.9em;opacity:0.8"
|
||||
(a :href (unquote (str "/" slug "/source")) "view source")
|
||||
" · "
|
||||
(a :href (unquote (str "/" slug "/edit")) "edit")
|
||||
" · "
|
||||
(a :href "/" "all posts")
|
||||
" · "
|
||||
(unquote auth-foot))))))))
|
||||
(dream-html-status 404
|
||||
(host/blog--page "Not found"
|
||||
(quasiquote
|
||||
@@ -364,7 +366,10 @@
|
||||
posts)))
|
||||
(let ((listing (if (> (len posts) 0)
|
||||
(list (quote ul) items)
|
||||
(quote (p "No posts yet.")))))
|
||||
(quote (p "No posts yet."))))
|
||||
;; auth-footer does a durable session read — bind it BEFORE the
|
||||
;; quasiquote (a perform during tree-build raises VmSuspended).
|
||||
(auth-foot (host/auth-footer req)))
|
||||
(dream-html
|
||||
(host/blog--page "Blog"
|
||||
(quasiquote
|
||||
@@ -372,7 +377,7 @@
|
||||
(unquote listing)
|
||||
(p (a :href "/new" "+ New post"))
|
||||
(p :style "margin-top:2em;font-size:0.9em;opacity:0.8"
|
||||
(unquote (host/auth-footer req))))))))))))
|
||||
(unquote auth-foot)))))))))))
|
||||
|
||||
(define host/blog-index (fn (req) (host/ok (host/blog-list))))
|
||||
|
||||
|
||||
Reference in New Issue
Block a user