Folders and files
| Name | Name | Last commit date | ||
|---|---|---|---|---|
Repository files navigation
#+TITLE: sbcl-workers
#+STARTUP: content
=sbcl-workers= manages named, persistent SBCL subprocesses through a readable
S-expression protocol. Each worker keeps its own heap, can move between working
directories, and can be reset independently.
Process separation is a reliability boundary. Evaluated forms have the user's
privileges.
* Environment and pool
The host supplies the command that starts a pristine protocol runtime. This
keeps the library independent of any executable, build system, or application:
#+BEGIN_SRC lisp
(defparameter *environment*
(sbcl-workers:sbcl-worker-environment-create
:pristine-command '("my-lisp-application" "--worker")
:working-directory #P"/srv/project/"
:image-root #P"/srv/state/lisp-images/"))
(defparameter *pool*
(sbcl-workers:sbcl-worker-pool-create *environment*))
(defparameter *repl*
(sbcl-workers:sbcl-worker-pool-start *pool* "compiler" "pristine"))
(sbcl-workers:sbcl-worker-request
*repl* :eval '(:forms ("(+ 20 22)")))
#+END_SRC
An =:eval= or =:compile= request carries =:forms=, a non-empty list of strings
that each hold exactly one form. The worker reads and evaluates them in order,
reading a form only after the previous one ran, so a later form may use a
package an earlier one loaded. The response carries the last form's values and
the output of all of them; a failure stops the sequence, keeps the effects of
the forms before it, and reports =:form-index= and =:form-count=.
The pristine command must load =sbcl-workers= and call
=sbcl-workers:sbcl-worker-main=. It may also be a function of no arguments
returning such a list; it is called at every pristine start, so a host can boot
a prebuilt core while it is current and fall back to loading source otherwise.
Applications can configure:
- the evaluation package
- handshake tag
- protocol version
- matching SBCL source environment variable
=sbcl-worker-name-p= checks the accepted one-to-eighty character worker-name
syntax.
Requests run with the standard printer settings; only the protocol line itself
is printed readably, so user code may print conditions and other unreadable
objects. Every response carries the request's captured =:output=. An =:error=
response adds the condition's =:message= and a =:backtrace= taken where the
error was signaled, so a failed system load still shows the compiler's
diagnostics and the failing frames.
* Worker images
=sbcl-worker-save-image= forks a short-lived saver from a running worker. The
parent continues running while the library probes the unpublished core and then
atomically publishes its immutable directory and readable manifest. Manifests
record:
- the exact SBCL, operating system, and architecture
- parent image
- creation time
- durable note
- optional host source revision
Saved cores are accepted only by an exactly compatible runtime. =pristine= is a
reserved virtual base.
* Operations
The built-in runtime handles:
- evaluation and compilation
- ASDF or Quicklisp system loading
- description
- source lookup for loaded definitions, mapping SBCL's own into matching SBCL source
- ASDF tests
- image saving
Responses contain only readable Common Lisp data.
* Worker managers
A host may hold one worker, a named pool, or nothing yet. The
=sbcl-worker-manager-*= generics address all three the same way: worker,
start, reset, stop-worker, stop, change-working-directory, and render. A single
worker answers only for its own name and image and refuses operations that need
named workers; with no manager, stopping and moving do nothing and everything
else signals =sbcl-worker-error=.
* Tests
#+BEGIN_SRC lisp
(asdf:test-system :sbcl-workers)
#+END_SRC
Part of the [[https://www.lambda-symbolics.com/libraries][Lambda Symbolics library shelf]].