rwlockfile
Version:
lockfile utility with reader/writers
81 lines (62 loc) • 3.85 kB
Markdown
rwlockfile
==========
[](https://github.com/prettier/prettier)
[](https://greenkeeper.io/)
[](https://codecov.io/gh/jdxcode/rwlockfile)
[](https://circleci.com/gh/jdxcode/rwlockfile)
[](https://ci.appveyor.com/project/Heroku/rwlockfile/branch/master)
[](https://npmjs.org/package/rwlockfile)
[](https://npmjs.org/package/rwlockfile)
[](https://github.com/jdxcode/rwlockfile/blob/master/package.json)
node utility for read/write lockfiles
This is the only node package as of this writing I'm aware of that allows you to have read/write lockfiles. If you're looking for a simpler solution, check out [proper-lockfile](https://www.npmjs.com/package/proper-lockfile). Use this package if you need read/write lock support.
This follows the standard [Readers-Writers Lock design pattern](https://en.wikipedia.org/wiki/Readers–writer_lock). Any number of readers are allowed at one time. 1 writer is allowed at one time iff there are no current readers.
Usage
=====
```js
const {RWLockfile} = require('rwlockfile')
// 'myfile' is the path to a file to use as the base for the lockfile
// it will add '.lock' to the end for the actual lockfile, so in this case 'myfile.lock'
let lock = new RWLockfile('myfile', {
// how long to wait until timeout. Default: 30000
timeout: 30000,
// mininum time to wait between checking for locks
// automatically adds some noise and duplicates this number each check
retryInterval: 10,
})
// add a reader async or synchronously. If the count is >= 1 it creates a read lock (see note below)
await lock.add('read')
lock.addSync('read')
// remove a reader async or synchronously. If the count == 0 it creates removes the read lock
await lock.remove('read')
lock.removeSync('read')
// add a writer async or synchronously
await lock.add('write')
lock.addSync('write')
```
Behavior Note
=============
The use of `.add()` and `.remove()` may be a bit misleading but allow me to attempt to explain what it means. It's designed to make it easy to add try/finally steps around locking. Each instance of RWLockfile has a count of readers and writers. The file itself has it's own count of readers and writers. When you increment the count, what you're doing is adding to the count of *just* that instance.
In other words, you can do `lock.add('write')` multiple times on the same instance. That instance will create the write lock if the count is greater than 1 but no other instances will be allowed to increase the count above 0.
Why? Because this way you can have functions in your code like this:
```js
async function doAThing() {
await lock.add('write')
try {
// do something while locked
doAnotherThing()
} finally {
await lock.remove('write')
}
}
async function doAnotherThing() {
await lock.add('write')
try {
// do something else while locked
} finally {
await lock.remove('write')
}
}
```
This will only create a single write lock which will be removed after doAThing() is done. This way you can call doAnotherThing() and it ensures it has a lock if it doesn't exist, but will only remove the write lock if nothing it's using also has a write lock.
I've found this behavior to be perfect for working with, but this sort of nesting lock logic is a little difficult to explain.