Liking cljdoc? Tell your friends :D

hive-hot.protocols

The protocol interlock for a scoped reload, read off the LIVE image.

Reloading a namespace that defines a protocol (defprotocol) or an interface (definterface) replaces the protocol object / interface class. Every implementation built against the OLD one is orphaned: a defrecord compiled against the old interface no longer implements the new one, and the protocol's fresh :impls map has forgotten every extend. The symptom reads as a defect in the implementor - "No implementation of method: :m of protocol #'p/P found for class: x.Rec" - for a class that plainly implements it.

clj-reload already reloads the require-graph dependents of a changed namespace, but only the ones in loaded-libs, and only the ones the require graph can see. An implementor that extends a protocol it reached through requiring-resolve, a live namespace an earlier failed pass dropped from loaded-libs, or a dependent a failed pass left unloaded all escape it. This namespace names, BEFORE a pass, every namespace that has to be reloaded after each protocol definer the pass would reload, so the pass can be checked - and completed - against that list afterwards.

It also decides which definers must NOT be reloaded in place: one outside the roots being reloaded (a co-tenant's or a pinned SPI port, which this reload has no business replacing), and one whose implementors include a namespace clj-reload does not track (a jar, a REPL-made namespace): those could never be reloaded, so replacing the protocol would orphan them for good. Such a definer is PINNED for the pass and reported.

Pure reads of the image: no var is dereferenced except a protocol var, whose value is the protocol map itself.

The protocol interlock for a scoped reload, read off the LIVE image.

Reloading a namespace that defines a protocol (defprotocol) or an interface
(definterface) replaces the protocol object / interface class. Every
implementation built against the OLD one is orphaned: a defrecord compiled
against the old interface no longer implements the new one, and the
protocol's fresh :impls map has forgotten every extend. The symptom reads as
a defect in the implementor - "No implementation of method: :m of protocol
#'p/P found for class: x.Rec" - for a class that plainly implements it.

clj-reload already reloads the require-graph dependents of a changed
namespace, but only the ones in *loaded-libs*, and only the ones the require
graph can see. An implementor that extends a protocol it reached through
requiring-resolve, a live namespace an earlier failed pass dropped from
*loaded-libs*, or a dependent a failed pass left unloaded all escape it.
This namespace names, BEFORE a pass, every namespace that has to be reloaded
after each protocol definer the pass would reload, so the pass can be
checked - and completed - against that list afterwards.

It also decides which definers must NOT be reloaded in place: one outside
the roots being reloaded (a co-tenant's or a pinned SPI port, which this
reload has no business replacing), and one whose implementors include a
namespace clj-reload does not track (a jar, a REPL-made namespace): those
could never be reloaded, so replacing the protocol would orphan them for
good. Such a definer is PINNED for the pass and reported.

Pure reads of the image: no var is dereferenced except a protocol var,
whose value is the protocol map itself.
raw docstring

analyzeclj

(analyze
  {:keys [candidates deps tracked? in-roots? no-reload]
   :or {tracked? (constantly true) in-roots? (constantly true) no-reload #{}}})

The protocol interlock for one pass.

candidates are the namespaces the pass may reload (its cascade). Each LIVE one that defines a protocol or interface is a definer, with the namespaces that must be reloaded after it: its implementors (see implementors) plus its live direct require-graph dependents (deps, clj-reload's dependees map {ns #{dependent}}), whose compiled call sites hold the old method vars.

A definer is PINNED, with a reason, when :no-reload the host already pins it (config :no-reload) :outside-roots in-roots? says it lives outside the reloaded roots :untracked-implementors an implementor is not tracked?, so could never be reloaded after it

Returns {:definers {ns #{must-follow ...}} - definers the pass reloads :pinned {ns {:reason kw :implementors [ns ...]}}}

The protocol interlock for one pass.

`candidates` are the namespaces the pass may reload (its cascade). Each LIVE
one that defines a protocol or interface is a definer, with the namespaces
that must be reloaded after it: its implementors (see `implementors`) plus
its live direct require-graph dependents (`deps`, clj-reload's dependees
map {ns #{dependent}}), whose compiled call sites hold the old method vars.

A definer is PINNED, with a reason, when
  :no-reload              the host already pins it (config :no-reload)
  :outside-roots          `in-roots?` says it lives outside the reloaded roots
  :untracked-implementors an implementor is not `tracked?`, so could never be
                          reloaded after it

Returns {:definers {ns #{must-follow ...}}       - definers the pass reloads
         :pinned   {ns {:reason kw :implementors [ns ...]}}}
sourceraw docstring

defines-protocol?clj

(defines-protocol? ns-sym)

Does the loaded namespace ns-sym define a protocol or an interface?

Does the loaded namespace `ns-sym` define a protocol or an interface?
sourceraw docstring

implementorsclj

(implementors ns-sym)

Live namespaces, other than ns-sym, holding an implementation of a protocol or interface ns-sym defines:

inline - a class the namespace defined (defrecord / deftype) that implements one of the interfaces extended - the namespace whose fns sit in a protocol's :impls (extend, extend-type, extend-protocol)

Namespaces under clojure.* are never counted.

Live namespaces, other than `ns-sym`, holding an implementation of a
protocol or interface `ns-sym` defines:

  inline   - a class the namespace defined (defrecord / deftype) that
             implements one of the interfaces
  extended - the namespace whose fns sit in a protocol's :impls
             (extend, extend-type, extend-protocol)

Namespaces under clojure.* are never counted.
sourceraw docstring

interfacesclj

(interfaces ns-sym)

The interfaces ns-sym defined and imported (definterface / gen-interface), plus the backing interface of every protocol it defines.

The interfaces `ns-sym` defined and imported (definterface / gen-interface),
plus the backing interface of every protocol it defines.
sourceraw docstring

pinned-reportclj

(pinned-report pinned)

Wire-safe projection of the pinned definers.

Wire-safe projection of the pinned definers.
sourceraw docstring

protocolsclj

(protocols ns-sym)

The protocol maps ns-sym defines, found through the :protocol metadata defprotocol stamps on each method var it interns. Empty when the namespace is not loaded.

The protocol maps `ns-sym` defines, found through the `:protocol` metadata
defprotocol stamps on each method var it interns. Empty when the namespace
is not loaded.
sourceraw docstring

stale-followersclj

(stale-followers definers loaded)

Given the definers an analyze call returned and the ordered loaded namespaces of a pass, every namespace that had to be reloaded AFTER a definer the pass loaded, but was not: never loaded, or loaded before it. Answers {definer #{ns ...}} with empty entries dropped.

Given the definers an `analyze` call returned and the ordered `loaded`
namespaces of a pass, every namespace that had to be reloaded AFTER a
definer the pass loaded, but was not: never loaded, or loaded before it.
Answers {definer #{ns ...}} with empty entries dropped.
sourceraw 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