Last active
September 3, 2015 16:06
-
-
Save peter/ec5504713e2d3f0ca501 to your computer and use it in GitHub Desktop.
Hack to prevent JavaScript function from executing concurrently (to avoid race conditions etc.)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 'use strict'; | |
| // NOTE: this in memory locking approach will only work with a single process | |
| // You might use something like Redis och memcachached for storing the lock if you need to lock | |
| // across several processes. | |
| var synchronizedFunction = function(lockIdFn, fn) { | |
| var locks = {}; | |
| var synchronized = function() { | |
| var args = Array.prototype.slice.call(arguments), | |
| lockId = lockIdFn.apply(null, args); | |
| if (locks[lockId]) { | |
| setTimeout(function() { | |
| synchronized.apply(null, args); | |
| }, 1); | |
| } else { | |
| locks[lockId] = new Date(); | |
| var result = fn.apply(null, args); | |
| delete locks[lockId]; | |
| return result; | |
| } | |
| }; | |
| return synchronized; | |
| }; | |
| // Example Usage - avoiding double inserts with PostgreSQL. A better solution is | |
| // probably to use database level locking and/or an upsert (coming in PG 9.5), i.e. see: | |
| // http://www.the-art-of-web.com/sql/upsert | |
| var storeLockId = function(params) { | |
| return params.key; | |
| }; | |
| var store = synchronizedFunction(storeLockId, function(params, callback) { | |
| db().events.find({key: params.key}, function(err, event) { | |
| if (err) return callback(err); | |
| if (event) { | |
| db().events.update( | |
| {key: params.key}, | |
| params, | |
| callback); | |
| } else { | |
| db().events.insert( | |
| params, | |
| callback); | |
| } | |
| }); | |
| }); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment