Shared, reference-counted stateful resources, such as subscriptions to a database or poll loops.
There is one physical resource per key, however many sessions watch it. It
opens on the first subscriber. After the last subscriber leaves, it lingers for
linger-ms and then closes, unless someone subscribes again first. The linger
absorbs remount churn: switching back and forth, navigation, and reconnects.
A resource is opened by a subject, (fn [emit!] undo), as in Missionary's
observe. Keys are a call site and its args. Islands subscribe with
co.multiply.tropical.hooks/observe, which
holds a subscription for as long as the island's renders keep asking for it: a
render that stops, or the island unmounting, releases it. Nobody calls
release! by hand.
The instances of shared states (co.multiply.tropical.shared) are resources
too, under keys of their own: they open holding a value, with a linger of
their state's, and change by its swap!, not by a subject.
A resource whose task fails is closed: its value becomes Failed, so its
readers throw, and the next subscriber to its key opens a new one.
For a view of what is open, use-summary gives the registry, live, of the
whole server or of what one session's islands hold, and describe says
what opened each.
Shared, reference-counted stateful resources, such as subscriptions to a database or poll loops. There is one physical resource per key, however many sessions watch it. It opens on the first subscriber. After the last subscriber leaves, it lingers for `linger-ms` and then closes, unless someone subscribes again first. The linger absorbs remount churn: switching back and forth, navigation, and reconnects. A resource is opened by a subject, `(fn [emit!] undo)`, as in Missionary's `observe`. Keys are a call site and its args. Islands subscribe with `co.multiply.tropical.hooks/observe`, which holds a subscription for as long as the island's renders keep asking for it: a render that stops, or the island unmounting, releases it. Nobody calls `release!` by hand. The instances of shared states (`co.multiply.tropical.shared`) are resources too, under keys of their own: they open holding a value, with a linger of their state's, and change by its `swap!`, not by a subject. A resource whose task fails is closed: its value becomes `Failed`, so its readers throw, and the next subscriber to its key opens a new one. For a view of what is open, `use-summary` gives the registry, live, of the whole server or of what one session's islands hold, and `describe` says what opened each.
The open resources, for display: an atom of a map keyed by
resource, which changes only as a resource opens, lingers or closes. Watch
it through summary: (use-watch resource/!entries resource/summary).
The open resources, for display: an atom of a map keyed by resource, which changes only as a resource opens, lingers or closes. Watch it through `summary`: `(use-watch resource/!entries resource/summary)`.
How many resources have opened and closed since the JVM started,
as an atom of {:opened :closed}.
How many resources have opened and closed since the JVM started,
as an atom of `{:opened :closed}`.(describe key)What opened the resource under key, as data: for an observe,
{:kind :observe, :ns, :line, :column, :args}, where :ns is a symbol,
the position its form's, or for one a macro expanded into, the macro
caller's, if known, and :args its arguments; for a shared state's
instance (co.multiply.tropical.shared), {:kind :shared, :state, :key},
where :state is the state's qualified symbol. For a key of another
shape, {:kind :other, :key key}.
What opened the resource under `key`, as data: for an `observe`,
`{:kind :observe, :ns, :line, :column, :args}`, where `:ns` is a symbol,
the position its form's, or for one a macro expanded into, the macro
caller's, if known, and `:args` its arguments; for a shared state's
instance (`co.multiply.tropical.shared`), `{:kind :shared, :state, :key}`,
where `:state` is the state's qualified symbol. For a key of another
shape, `{:kind :other, :key key}`.How long, in ms, a resource lingers after its last reader leaves, unless it
was opened with a :linger-ms of its own.
How long, in ms, a resource lingers after its last reader leaves, unless it was opened with a `:linger-ms` of its own.
(summary)(summary entries)The open resources, for display: key -> {:state :subscribers}, the state
:connecting, :live or :lingering. Of the registry, or of entries, a
value it held.
The open resources, for display: key -> `{:state :subscribers}`, the state
`:connecting`, `:live` or `:lingering`. Of the registry, or of `entries`, a
value it held.(use-summary)(use-summary scope)The open resources, as summary gives them, kept current: the island
renders again as one opens, gains or loses a reader, lingers or closes.
:server, the default: every resource open on this server, each
counting every island that reads it, in any session.
:session: the resources this session's islands hold, each counting
those islands only. A resource the session no longer holds is gone from
it, though it may linger for others.
(let [open (resource/use-summary :session)] [:ul (for [[k {:keys [state subscribers]}] open :let [{:keys [ns line]} (resource/describe k)]] [:li (str ns ":" line) " " (name state) " " subscribers])])
The server's view holds every user's reads, their arguments among them, so show it only to whoever may see them all. The session's view holds only this tab's reads, but their arguments are the server's values, and can hold what the page never shows, such as a database connection: print them through a filter of the app's own. For a diagnostic: it is worked out again over the whole registry each time it changes. A hook: call it during the render.
The open resources, as `summary` gives them, kept current: the island
renders again as one opens, gains or loses a reader, lingers or closes.
- `:server`, the default: every resource open on this server, each
counting every island that reads it, in any session.
- `:session`: the resources this session's islands hold, each counting
those islands only. A resource the session no longer holds is gone from
it, though it may linger for others.
(let [open (resource/use-summary :session)]
[:ul (for [[k {:keys [state subscribers]}] open
:let [{:keys [ns line]} (resource/describe k)]]
[:li (str ns ":" line) " " (name state) " " subscribers])])
The server's view holds every user's reads, their arguments among them,
so show it only to whoever may see them all. The session's view holds only
this tab's reads, but their arguments are the server's values, and can
hold what the page never shows, such as a database connection: print them
through a filter of the app's own. For a diagnostic: it is worked out again
over the whole registry each time it changes. A hook: call it during the
render.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 |