Home > Blockchain >  Understanding LockService behavior
Understanding LockService behavior

Time:08-07

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();
    }
}

3 buttons, 3 functions

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 call callFunction with the corresponding argument. That would be callSort, callImport and callFixDates 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)
}

Reference:

  • Related