Skip to content

Instantly share code, notes, and snippets.

@hidinginabunker
Created October 4, 2017 18:22
Show Gist options
  • Save hidinginabunker/c8446f741a30d1ebffed9b31edcbb9e4 to your computer and use it in GitHub Desktop.
Save hidinginabunker/c8446f741a30d1ebffed9b31edcbb9e4 to your computer and use it in GitHub Desktop.
Example of a global distributed lock in node using timeouts and redis for locks
const redis = require('redis')
const client = redis.createClient()
// will retry running a function until a lock is freed and it can run it
function retryUntilUnlocked(lock, func, seconds) {
client.get(lock, function (err, result) {
// while there is still a lock, keep re-trying every x seconds
if(result === 'true') {
setTimeout( () => {
retryUntilUnlocked(lock, func, seconds)
}, seconds * 1000)
} else {
// once the lock is freed, then call the function
func()
}
})
}
// uses a redis key as a distributed global lock to throttle
// a function call to only run after x seconds have elapsed since
// it was last called, any repeat calls in between reset the lock,
// keeping it from running until the last call
function throttleOnLock(seconds, func, lock) {
client.get(lock, function (err, result) {
if (err || !result) {
// if there is no lock, then we set one up and start a setTimeout loop
client.setex(lock, seconds, true, () => {
setTimeout( () => {retryUntilUnlocked(lock, func, seconds)}, seconds*1000)
})
} else {
// if there is a lock, then this call should be throttled by resetting the lock
client.setex(lock, seconds, true)
}
})
}
module.exports = {
throttleOnLock,
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment