Liking cljdoc? Tell your friends :D

vaelii.impl.feed

The change feed's registry and its accumulator — the leaf seam a settle files its relabelled region into, and the one place a listener list lives.

An application driving the KB otherwise learns that belief changed only by asking again, which misses whatever happened between two asks and costs the most on the KBs where the least is moving. Everything a feed needs is already computed: a settle knows the region it relabelled and which of that region was believed when it first touched it (jtms/touched / jtms/touched-in), and it throws both away. This namespace catches them.

Why here. vaelii.impl.observe is the precedent and the shape is the same: a choke point deep in the stack has to reach a consumer defined above it, so the indirection is a leaf both can see. What differs is the altitude. observe's observers fire on storage, which is what an alpha memory mirrors; a feed is about belief, and belief is decided at settle time — an assert can store a sentex whose label several later justifications settle. So nothing here is notified from kb/create-sentex, and the region is the unit rather than the record.

What is split where. The registry, the accumulator and the reentrancy guard are here, on the KB's :feed atom. Turning a region into the {:believed-added :believed-removed} entries a listener receives is vaelii.core's job — those are preview's entry shapes, built from why-not and the supporting justifications, and they belong beside the code that already renders them. core installs that renderer with install-dispatch! when it loads, and deliver! calls it.

What a KB with no listener pays. note-region! is one deref and a seq on the listener vector, and nothing accumulates. A KB with one pays per relabelled region — the same region a preview diffs — and never per stored sentex; see lein perf's feed-listener-scaling. See docs/feed.md.

The change feed's registry and its accumulator — the leaf seam a settle files its
relabelled region into, and the one place a listener list lives.

An application driving the KB otherwise learns that belief changed only by asking
again, which misses whatever happened between two asks and costs the most on the KBs
where the least is moving.  Everything a feed needs is already computed: a settle
knows the **region** it relabelled and which of that region was believed when it
first touched it (`jtms/touched` / `jtms/touched-in`), and it throws both away.  This
namespace catches them.

**Why here.**  `vaelii.impl.observe` is the precedent and the shape is the same: a
choke point deep in the stack has to reach a consumer defined above it, so the
indirection is a leaf both can see.  What differs is the altitude.  `observe`'s
observers fire on *storage*, which is what an alpha memory mirrors; a feed is about
**belief**, and belief is decided at settle time — an `assert` can store a sentex whose
label several later justifications settle.  So nothing here is notified from
`kb/create-sentex`, and the region is the unit rather than the record.

**What is split where.**  The registry, the accumulator and the reentrancy guard are
here, on the KB's `:feed` atom.  Turning a region into the `{:believed-added
:believed-removed}` entries a listener receives is `vaelii.core`'s job — those are
`preview`'s entry shapes, built from `why-not` and the supporting justifications, and
they belong beside the code that already renders them.  `core` installs that renderer
with `install-dispatch!` when it loads, and `deliver!` calls it.

**What a KB with no listener pays.**  `note-region!` is one deref and a `seq` on the
listener vector, and nothing accumulates.  A KB *with* one pays per relabelled region
— the same region a `preview` diffs — and never per stored sentex; see
`lein perf`'s `feed-listener-scaling`.  See docs/feed.md.
raw docstring

*enabled?*clj

Does a settle file its region into the feed at all?

True everywhere except inside core/preview, which stores, settles, reads the diff and then takes every write back. A preview that fed listeners would tell an application that belief changed and then that it changed back, which is worse than silence: the application learned nothing and has probably already acted. Bound around the rollback too, since the rollback is the half that would send the retraction.

Does a settle file its region into the feed at all?

True everywhere except inside `core/preview`, which stores, settles, reads the diff
and then takes every write back.  A preview that fed listeners would tell an
application that belief changed and then that it changed back, which is worse than
silence: the application learned nothing and has probably already acted.  Bound
around the rollback too, since the rollback is the half that would send the
retraction.
raw docstring

*held?*clj

Is delivery deferred to an enclosing operation?

Most mutations settle once, so the settle is the operation and its region is the whole story. A teardown is the exception: core/retract! and core/edit settle, re-derive what the removal released, and settle again — and a datum that goes OUT in the first pass and revives in the second moved no net belief at all. Delivering per settle would report both halves of that flicker. So those two hold the feed for their duration; the regions union, and one event is delivered with the batch's net answer, which is the same answer core/edit-with-consequences gives for the same batch.

Nests: an inner hold is a no-op wrapper (remove-orphaned-nats! retracts inside a retraction), and the outermost one delivers.

Is delivery deferred to an enclosing operation?

Most mutations settle once, so the settle *is* the operation and its region is the
whole story.  A teardown is the exception: `core/retract!` and `core/edit` settle,
re-derive what the removal released, and settle again — and a datum that goes OUT in
the first pass and revives in the second moved no net belief at all.  Delivering per
settle would report both halves of that flicker.  So those two hold the feed for
their duration; the regions union, and one event is delivered with the batch's net
answer, which is the same answer `core/edit-with-consequences` gives for the same
batch.

Nests: an inner hold is a no-op wrapper (`remove-orphaned-nats!` retracts inside a
retraction), and the outermost one delivers.
raw docstring

create-feedclj

(create-feed)

The atom a KB's :feed slot holds.

The atom a KB's `:feed` slot holds.
raw docstring

deliver!clj

(deliver! kb)

Hand every accumulated region to the installed renderer, then let go of the claim. Called at the tail of every settle — after the relabel is finished, the caches are reconciled and the touched set is cleared, so a listener that writes starts a fresh settle rather than relabelling inside one.

A no-op while *held?* (an enclosing teardown owns the delivery), while *enabled?* is false, when nothing above this layer installed a renderer, and when nothing accumulated — four cheap reads, in that order.

Re-drains until the accumulator is empty, so a listener's own writes are reported too, and gives up at max-delivery-rounds with a :warn rather than spinning.

Hand every accumulated region to the installed renderer, then let go of the claim.
Called at the tail of every settle — after the relabel is finished, the caches are
reconciled and the touched set is cleared, so a listener that writes starts a fresh
settle rather than relabelling inside one.

A no-op while `*held?*` (an enclosing teardown owns the delivery), while `*enabled?*`
is false, when nothing above this layer installed a renderer, and when nothing
accumulated — four cheap reads, in that order.

Re-drains until the accumulator is empty, so a listener's own writes are reported
too, and gives up at `max-delivery-rounds` with a `:warn` rather than spinning.
raw docstring

install-dispatch!clj

(install-dispatch! f)

Register the renderer deliver! hands each region to — vaelii.core's, once, when it loads. Global rather than per-KB for observe's reason: the function dispatches on the kb it is handed, so every live KB shares one installation and each keeps its own listeners.

Register the renderer `deliver!` hands each region to — `vaelii.core`'s, once, when
it loads.  Global rather than per-KB for `observe`'s reason: the function dispatches
on the `kb` it is handed, so every live KB shares one installation and each keeps its
own listeners.
raw docstring

listenersclj

(listeners kb)

The registered listeners, in registration order.

The registered listeners, in registration order.
raw docstring

note-region!clj

(note-region! kb region was-in)

A settle relabelled region, of which was-in was believed when first touched. Union both into the accumulator, for the next delivery.

Accumulates rather than queues, and that is what makes an event the net answer: two regions unioned and diffed once against belief-now reports what changed, where two separately-diffed regions would report a datum that went OUT and came back as a removal followed by an addition. Union is also why order does not matter — the event's content is a function of the state the delivery reads, never of which settle filed which handle.

Called behind wants-region?, which is what keeps the caller from assembling a region for a KB nobody is listening to — the re-check here is so this is safe to call anyway, not the gate that makes it free.

A settle relabelled `region`, of which `was-in` was believed when first touched.
Union both into the accumulator, for the next delivery.

Accumulates rather than queues, and that is what makes an event the *net* answer:
two regions unioned and diffed once against belief-now reports what changed, where
two separately-diffed regions would report a datum that went OUT and came back as a
removal followed by an addition.  Union is also why order does not matter — the
event's content is a function of the state the delivery reads, never of which settle
filed which handle.

Called behind `wants-region?`, which is what keeps the caller from *assembling* a region
for a KB nobody is listening to — the re-check here is so this is safe to call anyway,
not the gate that makes it free.
raw docstring

register!clj

(register! kb entry)

Add entry — a map carrying at least :f, plus :goal / :context for a standing query — and return its token. Appended, so the vector is registration order, which is the order deliver! calls in.

Add `entry` — a map carrying at least `:f`, plus `:goal` / `:context` for a standing
query — and return its token.  Appended, so the vector is registration order, which
is the order `deliver!` calls in.
raw docstring

unregister!clj

(unregister! kb token)

Drop the listener token names; true if there was one. Idempotent — a token already dropped, or one from another KB, removes nothing and says so.

Drop the listener `token` names; true if there was one.  Idempotent — a token
already dropped, or one from another KB, removes nothing and says so.
raw docstring

wants-region?clj

(wants-region? kb)

Would a region filed now reach anybody? The gate settle-finish reads before assembling one, so a KB nobody is listening to never builds the two sets it would have had nowhere to put — see note-region!. Whether the feed is on is the feed's own question, which is why both halves of it live here rather than at the call site.

Would a region filed now reach anybody?  The gate `settle-finish` reads **before**
assembling one, so a KB nobody is listening to never builds the two sets it would have
had nowhere to put — see `note-region!`.  Whether the feed is on is the feed's own
question, which is why both halves of it live here rather than at the call site.
raw docstring

watched?clj

(watched? kb)

Is anything listening? One deref and a seq — what a KB with no listener pays for the whole feature.

Is anything listening?  One deref and a `seq` — what a KB with no listener pays for
the whole feature.
raw docstring

with-one-eventcljmacro

(with-one-event kb & body)

Run body with delivery deferred, then deliver once — the teardown's shape (see *held?*). Returns body's value.

The delivery runs even when body throws, so a half-applied batch still reports the belief it did move. Often that is nothing: core/edit throws during its deferred phase, before any settle, so no region was ever filed — and nothing is lost, because the touched set is still uncleared and the next settle reports it.

Run `body` with delivery deferred, then deliver once — the teardown's shape (see
`*held?*`).  Returns `body`'s value.

The delivery runs even when `body` **throws**, so a half-applied batch still reports the
belief it did move.  Often that is nothing: `core/edit` throws during its deferred
phase, before any settle, so no region was ever filed — and nothing is lost, because the
touched set is still uncleared and the next settle reports it.
raw docstring

cljdoc builds & hosts documentation for Clojure/Script libraries

Keyboard shortcuts
Ctrl+kJump to recent docs
Move to previous article
Move to next article
Ctrl+/Jump to the search field
× close