I have 3 functions mapped to buttons in google sheets and I am trying to prevent multiple instances of any of the three from running concurrently. Here is an attempt to quickly summarize my code currently:
function import() {
const lock = LockService.getUserLock();
lock.tryLock(5000);
if (lock.hasLock()) {
// do stuff
sort(); // call the sort function
// do more stuff
lock.releaseLock();
}
}
function sort() {
const lock = LockService.getUserLock();
lock.tryLock(5000);
if (lock.hasLock()) {
// do some other stuff
lock.releaseLock();
}
}
function fixDates() {
const lock = LockService.getUserLock();
lock.tryLock(5000);
if (lock.hasLock()) {
// do more stuff
lock.releaseLock();
}
}
Currently, clicking on the "Import" button several times seems to be working as I intended where the next call will only run after the first one has finished. However, there is also a call to the sort() function which also uses a lock. Is this second lock the same as the first lock or completely independent?
And in the case where a user presses the "Import" button and then immediately follows by clicking the "Sort" button, will the manual sort() call only run after the import() function has finished running?
i.e. the order would be import() -> sort(), inside import -> sort(), manually called
CodePudding user response:
Issue:
Each lock in your code protects a specific section of your code. Two locks declared in different sections of your code are completely independent from each other (each lock protects its corresponding section).
Therefore, if you want to avoid concurrently executing any of these 3 functions (so, for example, you don't want fixDates
and sort
to be executing at the same time), you should create a single lock that protects all three functions.
Solution:
I'd suggest the following workflow.
- Have a single function which can call any of these three functions depending on the argument passed to the function. That is
callFunction
on the sample below. This will be the function that will acquire the lock, and thus protect the three functions with a single lock. - When the lock is acquired, the function would call one of the three functions depending on the argument that has been passed.
switch
would be useful here. - Now, since you are calling these functions via buttons, you cannot provide arguments to the called functions, so you should assign not
callFunction
to your buttons, but three different functions which would callcallFunction
with the corresponding argument. That would becallSort
,callImport
andcallFixDates
in the sample below. - You can now remove the lock part from your original 3 functions, since all these will be protected by the lock in
callFunction
.
Code sample:
function callSort() {
callFunction("sort");
}
function callImport() {
callFunction("import");
}
function callFixDates() {
callFunction("fix dates");
}
function callFunction(arg) {
const lock = LockService.getUserLock();
lock.tryLock(5000);
if (lock.hasLock()) {
switch (arg) {
case "sort":
sort();
break;
case "import":
import();
break;
case "fix dates":
fixDates();
break;
}
lock.releaseLock();
}
}
function import() {
// IMPORT ACTIONS (NO NEED FOR LOCK HERE)
}
function sort() {
// SORT ACTIONS (NO NEED FOR LOCK HERE)
}
function fixDates() {
// FIXDATES ACTIONS (NO NEED FOR LOCK HERE)
}