Skip to content

Instantly share code, notes, and snippets.

@Oaphi
Created August 7, 2020 13:06
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save Oaphi/df2716553bfd035ebf69d9cd5e1e5b28 to your computer and use it in GitHub Desktop.
Save Oaphi/df2716553bfd035ebf69d9cd5e1e5b28 to your computer and use it in GitHub Desktop.
PropertyLockService
var PropertyLock = (() => {
let locked = false;
let timeout = 0;
const store = PropertiesService.getScriptProperties();
const propertyName = "locked";
const triggerName = "PropertyLock.releaseLock";
const toSleep = 10;
const currentGSuiteRuntimeLimit = 30 * 60 * 1e3;
const lock = function () { };
/**
* @returns {boolean}
*/
lock.hasLock = function () {
return locked;
};
/**
* @param {number} timeoutInMillis
* @returns {boolean}
*/
lock.tryLock = function (timeoutInMillis) {
//emulates "no effect if the lock has already been acquired"
if (locked) {
return true;
}
timeout === 0 && (timeout = timeoutInMillis);
const stored = store.getProperty(propertyName);
const isLocked = stored ? JSON.parse(stored) : false;
const canWait = timeout > 0;
if (isLocked && canWait) {
Utilities.sleep(toSleep);
timeout -= toSleep;
return timeout > 0 ?
PropertyLock.tryLock(timeoutInMillis) :
false;
}
if (!canWait) {
return false;
}
try {
store.setProperty(propertyName, true);
ScriptApp.newTrigger(triggerName).timeBased()
.after(currentGSuiteRuntimeLimit).create();
console.log("created trigger");
locked = true;
return locked;
}
catch (error) {
console.error(error);
return false;
}
};
/**
* @returns {void}
*/
lock.releaseLock = function () {
try {
locked = false;
store.setProperty(propertyName, locked);
const trigger = ScriptApp
.getProjectTriggers()
.find(n => n.getHandlerFunction() === triggerName);
console.log({ trigger });
trigger && ScriptApp.deleteTrigger(trigger);
}
catch (error) {
console.error(error);
}
};
/**
* @param {number} timeoutInMillis
* @returns {boolean}
*
* @throws {Error}
*/
lock.waitLock = function (timeoutInMillis) {
const hasLock = PropertyLock.tryLock(timeoutInMillis);
if (!hasLock) {
throw new Error("Could not obtain lock");
}
return hasLock;
};
return lock;
})();
var PropertyLockService = (() => {
const init = function () { };
/**
* @returns {PropertyLock}
*/
init.getScriptLock = function () {
return PropertyLock;
};
return init;
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment