In my Google Apps Script application, there's a place where I generate a unique, incrementing order number. To achieve this, I make use of the builtin LockService
and PropertiesService
.
I store a number as a script property. When I need a new order number, the application fetches the current value, increments it, and saves the new value for next time. To make sure that two people running the application don't get the same number, access to the script property is placed inside of a script lock, or mutex.
This works well, and hundreds of calls go through the function each day. But twice in the past month, two users have ended up with the same order number.
// Increment the existing value, and return our new value.
function getPropIncrementViaMutex(propId) {
try {
var scriptProperties = PropertiesService.getScriptProperties();
var lock = LockService.getScriptLock();
var success = false;
var prevValue = null;
var newValue = null;
var wasSet = null;
while (!success) {
success = lock.tryLock(500);
if (!success) {
Utilities.sleep(1000);
} else {
prevValue = Number(scriptProperties.getProperty(propId));
scriptProperties.setProperty(propId, prevValue + 1);
newValue = Number(scriptProperties.getProperty(propId));
lock.releaseLock();
wasSet = (newValue === (prevValue + 1));
}
}
if (wasSet) {
return newValue;
} else {
throw new Error("Error incrementing order number. Previous Value: " + prevValue + " New Value: " + newValue);
}
} catch(e) {
if (lock) {
lock.releaseLock();
}
throw e;
}
}
Is there something I'm doing wrong here? Is the problem on Google's end?
A colleague suggested increasing the lock time in lock.tryLock(500)
to something higher like lock.tryLock(800)
.
He also suggests that when releasing the lock, to call Utility.sleep(300)
beforehand, so the script has enough time to update the property.
He thinks the release is happening before the the property update.
I'm going to try implementing his suggestions, as they can't hurt, but I'd like to hear any other thoughts on the problem.