Embeddable stube runtime instances.
dev.zeko.stube.kernel remains the pure effect fold. This namespace
holds the small amount of mutable runtime state needed to embed that
fold in a host Ring app: live conversations, SSE channels, timers,
subscriptions, and the pending-root baton between shell render and
first SSE attach.
Embeddable stube runtime instances. `dev.zeko.stube.kernel` remains the pure effect fold. This namespace holds the small amount of mutable runtime state needed to embed that fold in a host Ring app: live conversations, SSE channels, timers, subscriptions, and the pending-root baton between shell render and first SSE attach.
(active-conversations k)Snapshot of all active conversations in kernel k.
Snapshot of all active conversations in kernel `k`.
(apply-conv! k cid f)Apply (f conv) → [conv' fragments], push fragments over SSE, and
end the conversation if the kernel marked it ended.
Apply `(f conv) → [conv' fragments]`, push fragments over SSE, and end the conversation if the kernel marked it ended.
(authorized? k request cid)True when request owns conversation cid under kernel k.
True when `request` owns conversation `cid` under kernel `k`.
(conversation k cid)Snapshot of conversation cid in kernel k, or nil.
Snapshot of conversation `cid` in kernel `k`, or nil.
(create-conversation! k root-id)(create-conversation! k root-id owner-token)Compatibility helper for standalone server code that already resolved the owner token.
Compatibility helper for standalone server code that already resolved the owner token.
(dispatch! k cid {:keys [instance-id] :as event})Dispatch one event into a live conversation and return the fragments produced. Also pushes those fragments to an open SSE stream.
Dispatch one event into a live conversation and return the fragments produced. Also pushes those fragments to an open SSE stream.
(end-conversation! k cid)Drop a conversation, any SSE binding, pending root, timers, subscriptions, and persisted copy.
Drop a conversation, any SSE binding, pending root, timers, subscriptions, and persisted copy.
(ensure-session k request)Return [sid set-cookie-header-or-nil] for request under kernel
k. Kernels with a custom :session-id-fn default to host-managed
sessions and do not mint a stube cookie.
Return `[sid set-cookie-header-or-nil]` for `request` under kernel `k`. Kernels with a custom `:session-id-fn` default to host-managed sessions and do not mint a stube cookie.
(halt! k)Drain a kernel. Sequence:
:stop hooks for every live instance (children before
their frame, top stack frame first).:close fragment.save! per conversation.Returns nil. Idempotent: subsequent calls on the same kernel are cheap no-ops.
Drain a kernel. Sequence:
1. Mark the kernel as shutting down so HTTP adapters can refuse
new conversation mints.
2. Cancel pending scheduled events.
3. Run `:stop` hooks for every live instance (children before
their frame, top stack frame first).
4. Drain open SSE streams with a final `:close` fragment.
5. Flush the store with one last `save!` per conversation.
6. Clear per-kernel runtime registries.
Returns nil. Idempotent: subsequent calls on the same kernel are
cheap no-ops.(head-tags k)Return Hiccup head nodes required by shell-for for kernel k.
Return Hiccup head nodes required by [[shell-for]] for kernel `k`.
(make-kernel)(make-kernel opts)Create an embeddable stube runtime instance.
Stable embedder options:
:context-fn — (fn [request] ctx) stored on each conversation and
readable in handlers with (s/context self).:app — opaque host value (typically a small map of dependencies
such as {:db ds :mail mailer}). Read from component code with
(s/app). Not persisted; rebuild from live JVM state on each
make-kernel call.:principal-fn — (fn [request] principal-or-nil) invoked once at
mint time. Result is persisted on the conversation as
:conv/principal; component code reads it with (s/principal).
Re-authentication is the host's job — if the principal needs to
change, end the conversation and re-mint.:store — persistence backend from dev.zeko.stube.store.:base-path — URL prefix used by shell/render helpers.:session-id-fn — host session lookup; defaults to stube_sid.:on-conv-mint — optional (fn [conv request] conv') hook.:on-error — reserved hook for adapter error reporting.:base-css — vector of stylesheet URLs (strings) that
head-tags should emit unconditionally, before any
component-derived stylesheet. Use this when the host has
page-wide CSS that must appear on every page — including pages
that do not embed a stube shell (so component-scoped
stube_styles/<ns>/<name>.css is not enough). URLs are emitted
verbatim; relative URLs resolve against the host page, absolute
URLs are passed through unchanged.:eager-scripts — vector of inline JS snippets (strings)
head-tags should emit as synchronous <script> blocks in
<head> before any type="module" script. Use this to seed
window.<X> namespaces that inline Datastar expressions
(data-on:input="window.X.foo(...)") need available from
frame 1, before the deferred ESM module graph finishes. Snippets
are emitted verbatim and concatenated into a single <script>
block; the host is responsible for the contents (no escaping).:sse-keepalive-ms — interval in milliseconds for the SSE
heartbeat that keeps reverse-proxy idle timers happy. Defaults
to 15000. Set to nil or 0 to disable (e.g. when the host's proxy
has no idle timeout, or in tests).Create an embeddable stube runtime instance.
Stable embedder options:
* `:context-fn` — `(fn [request] ctx)` stored on each conversation and
readable in handlers with `(s/context self)`.
* `:app` — opaque host value (typically a small map of dependencies
such as `{:db ds :mail mailer}`). Read from component code with
`(s/app)`. Not persisted; rebuild from live JVM state on each
`make-kernel` call.
* `:principal-fn` — `(fn [request] principal-or-nil)` invoked once at
mint time. Result is persisted on the conversation as
`:conv/principal`; component code reads it with `(s/principal)`.
Re-authentication is the host's job — if the principal needs to
change, end the conversation and re-mint.
* `:store` — persistence backend from `dev.zeko.stube.store`.
* `:base-path` — URL prefix used by shell/render helpers.
* `:session-id-fn` — host session lookup; defaults to `stube_sid`.
* `:on-conv-mint` — optional `(fn [conv request] conv')` hook.
* `:on-error` — reserved hook for adapter error reporting.
* `:base-css` — vector of stylesheet URLs (strings) that
[[head-tags]] should emit unconditionally, before any
component-derived stylesheet. Use this when the host has
page-wide CSS that must appear on every page — including pages
that do not embed a stube shell (so component-scoped
`stube_styles/<ns>/<name>.css` is not enough). URLs are emitted
verbatim; relative URLs resolve against the host page, absolute
URLs are passed through unchanged.
* `:eager-scripts` — vector of inline JS snippets (strings)
[[head-tags]] should emit as synchronous `<script>` blocks in
`<head>` *before* any `type="module"` script. Use this to seed
`window.<X>` namespaces that inline Datastar expressions
(`data-on:input="window.X.foo(...)"`) need available from
frame 1, before the deferred ESM module graph finishes. Snippets
are emitted verbatim and concatenated into a single `<script>`
block; the host is responsible for the contents (no escaping).
* `:sse-keepalive-ms` — interval in milliseconds for the SSE
heartbeat that keeps reverse-proxy idle timers happy. Defaults
to 15000. Set to nil or 0 to disable (e.g. when the host's proxy
has no idle timeout, or in tests).(mint-conversation! k root-id request)(mint-conversation! k root-id init-args request)(mint-conversation! k root-id init-args request owner-token)Register a new conversation for root-id and return its cid.
The 4-arity calls ensure-session internally; the 5-arity accepts
a pre-computed owner-token from a caller that already ran
ensure-session and needs the conversation to be owned by that
exact session (otherwise ensure-session, called with a still-
cookieless request, would mint a second sid and own the conv with
one the browser will never present).
Register a new conversation for `root-id` and return its cid. The 4-arity calls [[ensure-session]] internally; the 5-arity accepts a pre-computed `owner-token` from a caller that already ran ensure-session and needs the conversation to be owned by *that* exact session (otherwise ensure-session, called with a still- cookieless request, would mint a second sid and own the conv with one the browser will never present).
(pending-root k cid)Pop and return the root embed/flow for cid, if any.
Pop and return the root embed/flow for `cid`, if any.
(publish! k topic msg)Asynchronously deliver msg to every live subscriber of topic in
kernel k.
Asynchronously deliver `msg` to every live subscriber of `topic` in kernel `k`.
(reap! k ttl)End conversations whose :conv/touched is older than ttl.
End conversations whose `:conv/touched` is older than `ttl`.
(replay-with k root-id events)Purely replay events against a fresh conversation rooted at
root-id, using k's render configuration but mutating no runtime
state. See dev.zeko.stube.embed/replay-with for the public-facing
forwarder.
Purely replay `events` against a fresh conversation rooted at `root-id`, using `k`'s render configuration but mutating no runtime state. See [[dev.zeko.stube.embed/replay-with]] for the public-facing forwarder.
(schedule-event! k {:keys [cid instance-id delay-ms event]})Schedule a future event for a cid/iid within kernel k.
Schedule a future event for a cid/iid within kernel `k`.
(shell-for k cid)Return the embeddable Hiccup shell fragment for conversation cid.
Return the embeddable Hiccup shell fragment for conversation `cid`.
(shutting-down? k)True once halt! has begun the shutdown sequence for k. HTTP
adapters should refuse new conversation mints (typically 503) while
this is true.
True once [[halt!]] has begun the shutdown sequence for `k`. HTTP adapters should refuse new conversation mints (typically 503) while this is true.
(subscribe! k {:keys [cid instance-id topic event]})Subscribe cid/iid to topic within kernel k.
Subscribe cid/iid to `topic` within kernel `k`.
(swap-conv! k cid f)Apply (f conv) → [conv' fragments] to conversation cid under the
per-cid lock, then atomically commit conv'. f is called exactly
once — unlike a bare swap! whose retry semantics would re-run f
(and its side effects) under contention.
Apply `(f conv) → [conv' fragments]` to conversation `cid` under the per-cid lock, then atomically commit `conv'`. `f` is called exactly once — unlike a bare `swap!` whose retry semantics would re-run `f` (and its side effects) under contention.
(unsubscribe! k {:keys [cid instance-id topic]})Remove one cid/iid subscription. If topic is nil, remove all of
the instance's subscriptions.
Remove one cid/iid subscription. If `topic` is nil, remove all of the instance's subscriptions.
(with-kernel-bindings k cid f)Run f with render URL context and async hooks for kernel k.
Run `f` with render URL context and async hooks for kernel `k`.
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 |