A Hierarchical Perishable Lock Service
Perishable locks are locks with a relatively short time to live (usually about a minute or so), and which are expected to be refreshed via some keep-alive or polling process until they are no longer required.
The intended use is for continuous builds via jenkins or similar services.
Builds are notoriously fickle, and crash or are terminated by impatient users. Builds also make use of shared resources, and sometimes require exclusive access. Using traditional locking mechanisms requires cleanup to avoid stale locks.
This service works around the problem of stale locks by incorporating the cleanup mechanism and releasing locks that haven't been refreshed within a given timespan.
- Hierarchical locking structure via resource paths. The last item in the path gets an exclusive lock, and the items in the path get shared locks.
- Queues for every resource ensure "first come first serve", as opposed to "whoever shows up at the right time gets it".
- REST api using simple GET requests returning JSON responses.
- Pure in memory state, no databases or files required.
- Clean shutdown to preserve continuous service even during upgrades.
- Support for long term locking (e.g. code freeze / maintenance) by setting lock expiration time into the future.
- Client "keepalive" process monitors parent process and is able to run a cleanup script should the parent process die or be killed.
|grab.js||Node script containing the actual server code. Run "node grab.js --help" to see the configuration options.|
|grab.py||Python client script. Run "python grab.py --help" to see the options.|
|restart.sh||Wrapper script to cleanly restart the service.|
|runtest.sh||Unit test runner.|
|sample.sh||Sample grab() and release() shell functions using the locking service with keep-alive process.|
First ensure you have python and node installed, then:
- start the service by running ./restart.sh
- optionally, in a separate window, tail -f ./log
- run the sample script: ./sample.sh
- try more experiments by using grab.py
- stop the service: ./grab.py shutdown
- inspect the log file: