Live conversation atom + http-kit lifecycle.
Three atoms live here:
| atom | shape | purpose |
|---|---|---|
!conversations | {cid → conv} | the live conversation values |
!sse-sessions | {cid → sse-gen} | the open browser connections |
!mounts | {path → flow-id} | the routes registered with mount! |
Timers, pub/sub, and the pending-flow baton moved to
dev.zeko.stube.async — this namespace owns conversation storage and
the http-kit server. All the http handlers live in
dev.zeko.stube.http; this namespace only exposes the functions
they need, so the http layer never reaches into raw atoms.
Live conversation atom + http-kit lifecycle.
Three atoms live here:
| atom | shape | purpose |
|--------------------|----------------------|--------------------------------------------|
| `!conversations` | `{cid → conv}` | the live conversation values |
| `!sse-sessions` | `{cid → sse-gen}` | the open browser connections |
| `!mounts` | `{path → flow-id}` | the routes registered with [[mount!]] |
Timers, pub/sub, and the pending-flow baton moved to
[[dev.zeko.stube.async]] — this namespace owns conversation storage and
the http-kit server. All the http handlers live in
[[dev.zeko.stube.http]]; this namespace only exposes the functions
they need, so the http layer never reaches into raw atoms.(active-conversations)Return a snapshot of all active conversations keyed by cid.
Return a snapshot of all active conversations keyed by cid.
(apply-conv! cid f)Apply (f conv) → [conv' fragments] under cid with kernel bindings
in scope, push any fragments to the open SSE, and end the conversation
if the kernel marked it ended. Returns [conv' fragments] or nil if
cid is unknown.
Single chokepoint for every code path that mutates a live
conversation: run-effects!, dispatch!, and the SSE-attach
boot/resume in the http layer.
Apply `(f conv) → [conv' fragments]` under `cid` with kernel bindings in scope, push any fragments to the open SSE, and end the conversation if the kernel marked it ended. Returns `[conv' fragments]` or nil if `cid` is unknown. Single chokepoint for every code path that mutates a live conversation: [[run-effects!]], [[dispatch!]], and the SSE-attach boot/resume in the http layer.
(conversation cid)Snapshot of the named conversation, or nil.
Snapshot of the named conversation, or nil.
(create-conversation! flow-id)(create-conversation! flow-id owner-token)Mint a fresh conversation, remember its pending root flow, and return
the new cid. The flow is only instantiated when the browser opens
the SSE stream — at that point the kernel runs boot against this
empty conversation.
Mint a fresh conversation, remember its pending root flow, and return the new cid. The flow is only *instantiated* when the browser opens the SSE stream — at that point the kernel runs `boot` against this empty conversation.
(current-store)The store currently in use. Exposed for tests and tooling; the http layer never needs to call it.
The store currently in use. Exposed for tests and tooling; the http layer never needs to call it.
(dispatch! cid {:keys [instance-id] :as event})Dispatch one event into conversation cid outside the request path.
Used by timers, uploads, and publish/subscribe delivery. Stale cid/iid
pairs are ignored.
Dispatch one event into conversation `cid` outside the request path. Used by timers, uploads, and publish/subscribe delivery. Stale cid/iid pairs are ignored.
(enable-halos! cid)Set :conv/halos? true on the live conversation cid, emitting no
fragments. The shell handler calls this when ?halos=1 is on the URL
and the server is started with halos enabled.
Set `:conv/halos? true` on the live conversation `cid`, emitting no fragments. The shell handler calls this when `?halos=1` is on the URL and the server is started with halos enabled.
(enable-halos-and-redraw! cid)Set :conv/halos? true on cid and push a freshly-decorated frame
to the open SSE so the page picks up halo data-attrs without a hard
reload. Called from the http handler that backs the dev-mode pill.
Set `:conv/halos? true` on `cid` *and* push a freshly-decorated frame to the open SSE so the page picks up halo data-attrs without a hard reload. Called from the http handler that backs the dev-mode pill.
(end! cid)Public admin wrapper around end-conversation!.
Public admin wrapper around [[end-conversation!]].
(end-conversation! cid)Drop a conversation, any SSE binding, and the persisted copy.
Drop a conversation, any SSE binding, and the persisted copy.
(halos?)True when the server is willing to serve the dev halos overlay.
Off by default; opt in with :halos? true on start!. Per-conv
activation also requires ?halos=1 on the shell URL.
True when the server is willing to serve the dev halos overlay. Off by default; opt in with `:halos? true` on [[start!]]. Per-conv activation also requires `?halos=1` on the shell URL.
(inspect cid)Pretty-print and return a compact summary of live conversation cid.
Returns nil if the conversation is not active. Summary shape lives
in dev.zeko.stube.halos alongside the rest of the REPL/dev tooling.
Pretty-print and return a compact summary of live conversation `cid`. Returns nil if the conversation is not active. Summary shape lives in [[dev.zeko.stube.halos]] alongside the rest of the REPL/dev tooling.
(mount! path flow-id)Register a flow at a URL path. After start!, GET <path> will
serve the shell page and pre-bind the resulting conversation to the
named flow.
Register a flow at a URL path. After [[start!]], `GET <path>` will serve the shell page and pre-bind the resulting conversation to the named flow.
Push kernel fragments to an open Datastar SSE generator.
Re-export of dev.zeko.stube.fragments/push!.
Push kernel fragments to an open Datastar SSE generator. Re-export of [[dev.zeko.stube.fragments/push!]].
(reap! ttl)End conversations whose :conv/touched is older than ttl.
ttl is a java.time.Duration or millisecond integer. Returns the
vector of cids that were reaped.
End conversations whose `:conv/touched` is older than `ttl`. `ttl` is a `java.time.Duration` or millisecond integer. Returns the vector of cids that were reaped.
(reset-state!)Wipe all in-memory state. Intended for tests and REPL iteration.
Wipe all in-memory state. Intended for tests and REPL iteration.
(run-effects! cid effects)Fold effects into conversation cid, push any fragments, and end
the conversation if the kernel marks it ended.
Fold `effects` into conversation `cid`, push any fragments, and end the conversation if the kernel marks it ended.
(start!)(start! {:keys [port store ui-css? halos? conversation-ttl reaper-interval]
:or {port 8080 ui-css? true halos? false}})Start http-kit on port (default 8080). Idempotent: a second call
with the server already running stops the old one first.
Options:
| key | default | meaning |
|---|---|---|
:port | 8080 | TCP port |
:store | (store/in-memory-store) | persistence backend (slice 3) |
:ui-css? | true | link the stock /stube/ui.css file |
:halos? | false | enable dev halos (per-conv via ?halos=1) |
:conversation-ttl | nil | reaper TTL (Duration or millis) |
:reaper-interval | 60000 | reaper interval (Duration or millis) |
When a :store is supplied, [[load-all]] runs before the http
listener accepts requests, so any persisted conversations are live
in memory by the time the first browser reconnects.
Start http-kit on `port` (default 8080). Idempotent: a second call with the server already running stops the old one first. Options: | key | default | meaning | |------------|-------------------------------|---------------------------------------| | `:port` | 8080 | TCP port | | `:store` | `(store/in-memory-store)` | persistence backend (slice 3) | | `:ui-css?` | true | link the stock `/stube/ui.css` file | | `:halos?` | false | enable dev halos (per-conv via `?halos=1`) | | `:conversation-ttl` | nil | reaper TTL (`Duration` or millis) | | `:reaper-interval` | 60000 | reaper interval (`Duration` or millis)| When a `:store` is supplied, [[load-all]] runs *before* the http listener accepts requests, so any persisted conversations are live in memory by the time the first browser reconnects.
(stop!)Stop the running server, if any.
Stop the running server, if any.
(swap-conv! cid f)Atomically apply f (which must return [conv' fragments]) to the
conversation under cid, install conv', persist it via the
configured store, and return the full [conv' fragments] pair so
the caller can act on the fragments.
f may be retried by swap! under CAS contention; its only side
effect should be the data it returns. The store's save! runs
outside the swap retry loop, so it sees only the final value.
Atomically apply `f` (which must return `[conv' fragments]`) to the conversation under `cid`, install `conv'`, persist it via the configured store, and return the full `[conv' fragments]` pair so the caller can act on the fragments. `f` may be retried by `swap!` under CAS contention; its only side effect should be the data it returns. The store's `save!` runs *outside* the swap retry loop, so it sees only the final value.
(ui-css?)True when the stock stube stylesheet should be linked from shells.
True when the stock stube stylesheet should be linked from shells.
(with-kernel-bindings cid f)Run f with the render cid and async hooks the kernel needs while
folding effects for cid.
Run `f` with the render cid and async hooks the kernel needs while folding effects for `cid`.
cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |