The :local-process target-type: the target runs as a separate OS process
on this machine, and Lite runs it -- starts it, holds its handle, and can
signal it.
This is the first target-type where Lite owns something the operating system
will kill for it, and that is the whole point of it. :in-process can
simulate a crash by destroying an object and building another, which
exercises a target's recovery code but not the process boundary; :http
can't crash anything at all. Here crash is SIGKILL -- a real kill -9,
with no chance to flush, close files or run shutdown hooks -- followed by a
real restart that has to find its data on disk. pause is SIGSTOP and
SIGCONT: the process is still there, still holding its port, and simply
stops answering.
What it does not test: loss of writes that reached the OS but were never fsynced. SIGKILL kills the process, not the kernel, so the page cache is still written back. It tests process death, restart and recovery -- real and worth testing -- and it catches data buffered in the target's own memory. True power-loss testing needs a fault injector below the filesystem.
Config:
{:type :local-process :command ["java" "-cp" ... "-m" "my.driver" "--port" "8080"] :url "http://127.0.0.1:8080" ; how to tell it has come up :dir "/tmp/target" ; working directory; optional :env {"FOO" "bar"} ; extra environment; optional :log "/tmp/target.log" ; where its output goes; optional :ready-timeout 30000} ; ms to wait for it to listen
:command must be the target's own process, not a shell that launches it:
Lite signals the process it started, and a shell wrapper would take the
signal instead of the target.
The `:local-process` target-type: the target runs as a separate OS process
on this machine, and Lite runs it -- starts it, holds its handle, and can
signal it.
This is the first target-type where Lite owns something the operating system
will kill for it, and that is the whole point of it. `:in-process` can
simulate a crash by destroying an object and building another, which
exercises a target's recovery code but not the process boundary; `:http`
can't crash anything at all. Here `crash` is `SIGKILL` -- a real `kill -9`,
with no chance to flush, close files or run shutdown hooks -- followed by a
real restart that has to find its data on disk. `pause` is `SIGSTOP` and
`SIGCONT`: the process is still there, still holding its port, and simply
stops answering.
What it does *not* test: loss of writes that reached the OS but were never
fsynced. SIGKILL kills the process, not the kernel, so the page cache is
still written back. It tests process death, restart and recovery -- real and
worth testing -- and it catches data buffered in the *target's own* memory.
True power-loss testing needs a fault injector below the filesystem.
Config:
{:type :local-process
:command ["java" "-cp" ... "-m" "my.driver" "--port" "8080"]
:url "http://127.0.0.1:8080" ; how to tell it has come up
:dir "/tmp/target" ; working directory; optional
:env {"FOO" "bar"} ; extra environment; optional
:log "/tmp/target.log" ; where its output goes; optional
:ready-timeout 30000} ; ms to wait for it to listen
`:command` must be the target's own process, not a shell that launches it:
Lite signals the process it started, and a shell wrapper would take the
signal instead of the target.(alive? target)Is the target process running?
Is the target process running?
(crash! {:keys [adapter config process conn paused crashes lifecycle-lock]})A real crash: SIGKILL, then start it again.
No chance to flush, close a file, or run a shutdown hook -- whatever the target hadn't got onto disk is gone, and whether that costs it any acknowledged writes is the question the run is asking. Ops that land while it is down get a connection error and are recorded honestly by the wrapper: refused means the op certainly never happened, a timeout means nobody knows.
The new connection is published before the old one is closed, so there is never a moment with no connection at all -- ops in the window should meet a dead target, which is the truth, rather than a nil one.
A real crash: SIGKILL, then start it again. No chance to flush, close a file, or run a shutdown hook -- whatever the target hadn't got onto disk is gone, and whether that costs it any acknowledged writes is the question the run is asking. Ops that land while it is down get a connection error and are recorded honestly by the wrapper: refused means the op certainly never happened, a timeout means nobody knows. The new connection is published before the old one is closed, so there is never a moment with no connection at all -- ops in the window should meet a dead target, which is the truth, rather than a nil one.
(crash-count target)How many times this target has been killed and restarted.
How many times this target has been killed and restarted.
(pause! {:keys [process paused lifecycle-lock]})SIGSTOP: the process stays alive and keeps its port, and stops answering. Ops that land in the window wait, and time out -- which is indeterminate, not failure: a paused target may well apply the request once it wakes.
Returns the pid it stopped. Keep it a number, as with crash!: checkers
read every op in the history, nemesis ops included, and some are strict
about what an op's value may be.
SIGSTOP: the process stays alive and keeps its port, and stops answering. Ops that land in the window wait, and time out -- which is indeterminate, not failure: a paused target may well apply the request once it wakes. Returns the pid it stopped. Keep it a number, as with `crash!`: checkers read every op in the history, nemesis ops included, and some are strict about what an op's value may be.
(pid target)The OS process id of the target as it is running now, or nil if it isn't.
The OS process id of the target as it is running now, or nil if it isn't.
(resume! {:keys [process paused lifecycle-lock]})SIGCONT: the process picks up where it left off, including any requests that were queued on its socket while it slept. Returns the pid it continued.
SIGCONT: the process picks up where it left off, including any requests that were queued on its socket while it slept. Returns the pid it continued.
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 |