|Alex Williams e5543716ab||1 year ago|
|.github/workflows||1 year ago|
|test||1 year ago|
|.gitignore||1 year ago|
|CHANGELOG.md||1 year ago|
|LICENSE||1 year ago|
|Makefile||1 year ago|
|README.md||1 year ago|
|clihelpers.l||1 year ago|
|module.l||1 year ago|
|supervisor.l||1 year ago|
|test.l||1 year ago|
|testapp.l||1 year ago|
This program mimics functionality of Unicorn, without being limited to HTTP applications.
supervisor.l can be used to spawn multiple worker processes which perform tasks in an infinite loop.
This library is written in pure PicoLisp and contains no external dependencies.
To ensure everything works on your system, run the tests first:
Launch the Supervisor with:
./supervisor.l --app testapp.l
You'll see output showing 1 worker "Performing a task" in a loop. Wait until it completes a task or two, then press
Ctrl+C or send an
INT signal to tell the parent process to exit, along with its worker.
# example output ./supervisor.l --app testapp.l --workers 2 parent process ready pid=814 spawning 2 missing workers: worker spawning.. worker spawning.. worker spawned pid=815 worker pid=815 do this after forking worker ready worker pid=815 Performing a task: sleeping for 12 seconds worker spawned pid=816 worker pid=816 do this after forking worker ready worker pid=816 Performing a task: sleeping for 9 seconds worker pid=816 Performing a task: sleeping for 16 seconds ^Cworker exited worker exited parent exited
Feel free to observe the example code in testapp.l.
The supervisor runs in the foreground and simply manages the worker processes. If a worker (child process) exits, it will be re-spawned automatically by the supervisor. The supervisor periodically checks for missing workers, depending on the
# supervisor.l Usage: ./supervisor.l --app <yourapp> [option] [arguments] Example: ./supervisor.l --app app.l --workers 4 --poll 1 Options: --help show this help message and exit --app <yourapp> Filename of the app which contains (worker-start) --poll <seconds> Number of seconds to poll for missing workers (default: 30) --preload Load the app in the parent before forking the worker process (default: No) --workers <number> Number of workers to spawn (default: 1)
--app: This option accepts 1 argument, a PicoLisp
.lfile. It will be
(load)ed in the forked process of each worker (each time a worker is spawned), unless
--preloadis specified. Once the process is forked, the
(worker-start)function will be called automatically, so that needs to be defined in your worker app.
--preload: This options takes no arguments. If
--preloadis specified, the worker app will be loaded only once, in the parent process. Its code will be inherited by each worker process as it's spawned. This should be more memory efficient (and faster) for large applications, but prevents changing the worker app "on the fly" (without restarting the supervisor).
--poll: This option accepts 1 argument, the number of seconds where the
parentprocess will sleep before checking for any missing workers. For processes which take a long time to complete, or for non-busy servers, it's probably safe to set the polling interval a bit higher (ex:
60seconds). If there's a need to know almost "right away" when a worker is missing, it is safe to set it to
--workers: This option accepts 1 argument, the number of workers which should be spawned. The supervisor will remember this number and always ensure that it's maintained. If 3 or 4 workers happen to exit, the supervisor will notice and respawn 3 workers.
This section will explain some important technical details about the code, and limitations on what this app can and can't do.
*SV_, and functions are prefixed with
(after-fork)hooks which will be called if they're defined in your app (totally optional). Of course,
(before-fork)happens in the parent process, right before the child is forked, and
(after-fork)happens in the child process, right after it's forked.
(before-fork)hook will only be called when
--preloadis provided, since there's no way to call the function before the code is even loaded.
(after-fork). This can be used in the app to conditionally perform tasks based on its ID (ex: worker ID 0 could verify the integrity of a database, while the other workers simply query it).
kill -KILL), and the workers will continue their work and exit cleanly when they're done.
kill -TERM) will terminate all workers and the parent immediately.
supervisor.lin PicoLisp, feel free to use those techniques if you prefer.
This library comes with very basic integration tests. To run the tests, type:
(native)) should conditionally check for OS support.
Copyright (c) 2020 Alexander Williams, On-Prem email@example.com