Effectful ITransport: a long-lived OS process running the opaque kernel binary, spoken to over line-oriented EDN on its stdin and stdout.
This is the transport a marketplace artifact actually mounts through. The process is LONG-LIVED on purpose: a cljw binary costs roughly 36ms to start, which is invisible once per mount and ruinous once per tool call.
JVM-only (.clj, not .cljc). It is the one namespace in the opaque subsystem that names host classes, which is precisely why the seam above it is a protocol: nothing else has to care that this exists.
The kernel's stderr is INHERITED rather than piped. A piped stderr that nobody drains fills its buffer and deadlocks the kernel mid-call, and a proprietary binary's diagnostics belong in the host's log anyway.
Every request is bounded by a DEADLINE, and requests are serialized: the
line protocol has no request ids, so one exchange at a time is what keeps
answers paired with their requests. See subprocess-transport for what a
missed deadline does.
Effectful ITransport: a long-lived OS process running the opaque kernel binary, spoken to over line-oriented EDN on its stdin and stdout. This is the transport a marketplace artifact actually mounts through. The process is LONG-LIVED on purpose: a cljw binary costs roughly 36ms to start, which is invisible once per mount and ruinous once per tool call. JVM-only (.clj, not .cljc). It is the one namespace in the opaque subsystem that names host classes, which is precisely why the seam above it is a protocol: nothing else has to care that this exists. The kernel's stderr is INHERITED rather than piped. A piped stderr that nobody drains fills its buffer and deadlocks the kernel mid-call, and a proprietary binary's diagnostics belong in the host's log anyway. Every request is bounded by a DEADLINE, and requests are serialized: the line protocol has no request ids, so one exchange at a time is what keeps answers paired with their requests. See `subprocess-transport` for what a missed deadline does.
Deadline, in ms, for the FIRST request after the kernel process starts. That request also pays the process start and load, and in the proxy's lifecycle it is always :addon/initialize!. Overridden by :opaque/init-timeout-ms.
Deadline, in ms, for the FIRST request after the kernel process starts. That request also pays the process start and load, and in the proxy's lifecycle it is always :addon/initialize!. Overridden by :opaque/init-timeout-ms.
Deadline, in ms, for one request to a kernel that has already answered once. Overridden per kernel by :opaque/request-timeout-ms.
Deadline, in ms, for one request to a kernel that has already answered once. Overridden per kernel by :opaque/request-timeout-ms.
(subprocess-transport argv)(subprocess-transport argv opts)An ITransport that runs argv as a subprocess on first -start!. argv is
the whole command vector (executable first), so a kernel that needs flags,
a licence file path or a data directory gets them without this namespace
knowing what any of them mean.
opts may carry :request-timeout-ms and :init-timeout-ms (positive ms); a
nil or absent one takes default-request-timeout-ms / default-init-timeout-ms.
The init deadline bounds the first request after each start, the request
deadline every later one.
A request that misses its deadline throws ex-info whose message names the deadline, after stopping the kernel (stdin closed, then the process and its descendants destroyed forcibly). The process is never reused: the line protocol is desynced by then, and a late answer would be read as the next request's. Until the next -start! the transport is not alive, -down-reason answers the reason, and every -request! throws it WITHOUT restarting the kernel. -start! restarts it, and OpaqueAddon/initialize! is what calls -start!, so a restarted kernel always receives :addon/initialize! before it serves another tool. -start! likewise restarts a kernel that exited.
An ITransport that runs `argv` as a subprocess on first -start!. `argv` is the whole command vector (executable first), so a kernel that needs flags, a licence file path or a data directory gets them without this namespace knowing what any of them mean. `opts` may carry :request-timeout-ms and :init-timeout-ms (positive ms); a nil or absent one takes `default-request-timeout-ms` / `default-init-timeout-ms`. The init deadline bounds the first request after each start, the request deadline every later one. A request that misses its deadline throws ex-info whose message names the deadline, after stopping the kernel (stdin closed, then the process and its descendants destroyed forcibly). The process is never reused: the line protocol is desynced by then, and a late answer would be read as the next request's. Until the next -start! the transport is not alive, -down-reason answers the reason, and every -request! throws it WITHOUT restarting the kernel. -start! restarts it, and OpaqueAddon/initialize! is what calls -start!, so a restarted kernel always receives :addon/initialize! before it serves another tool. -start! likewise restarts a kernel that exited.
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 |