How to understand LockService and implement it correctly?
So I think I have found an issue with the locking system. That is, when you trigger a popup box(that appears within a sheet) in the script, it scraps the lock... Or something like that, because it definitely doesn't keep the lock. I have a segment of code I am trying to run and basically without the popup box, the locking system works. There is no issue, the haslock will indeed return false when the first user has the lock... but then you introduce a popup box and the locking system doesn't work like it should, and grants a lock to the 2nd user even tho the popup box and that line of code, or any lines of code after it for that matter, have not been executed.. I tried it with a delay after the popup box because I originally thought that maybe it's not waiting for the input back so therefore it just kinda skips over the popup box after it has pushed it out to the sheet... but even with a long delay after the popup box portion of the code(and script is still running right in front of my face) the 2nd user is still granted a lock.. Maybe I am doing this wrong but the popup box is the only thing that throws my code off. I tried the try, catch, and if, if else... and no luck, i even tried just an if,else... I know it is not because the trylock/waitlock is too long, or too short I've tried a range of values, I also know it is not the sleep bc I've tried a range of values, as well as different placements within my code. Tested these quite heavily, on different google user accounts on multiple different days bc I originally thought it was me just being dumb or something.. but it really just seems like the popup box is the only thing that sends it off the reservation.. Examples of when the locking system works
function myFunction() {
var lock = LockService.getScriptLock();
lock.tryLock(5000);
if (!lock.hasLock()) {
Logger.log('Could not obtain lock after 5 seconds.');
return;
}
else if (lock.hasLock()) {
Logger.log('got the lock');
//Browser.inputBox("TESTING123");
Utilities.sleep(10000);
}
lock.releaseLock();
}
2
function myFunction() {
var lock = LockService.getScriptLock();
lock.tryLock(5000);
if (!lock.hasLock()) {
Logger.log('Could not obtain lock after 5 seconds.');
}
else {
Logger.log('got the lock');
//Browser.inputBox("TESTING123");
Utilities.sleep(10000);
}
lock.releaseLock();
}
with the proposed try,catch statement
function myFunction() {
var lock = LockService.getScriptLock();
try {
lock.waitLock(5000); // wait 5 seconds try to get lock
} catch (e) {
Logger.log('Could not obtain lock after 5 seconds.');
}
Utilities.sleep(10000);
//Browser.inputBox("TESTING123");
lock.releaseLock();
}
it does indeed catch the error and display the popup saying it couldn't get it
Examples when it doesnt work
function myFunction() {
var lock = LockService.getScriptLock();
lock.tryLock(5000);
if (!lock.hasLock()) {
Logger.log('Could not obtain lock after 5 seconds.');
return;
}
else if (lock.hasLock()) {
Logger.log('got the lock');
Browser.inputBox("TESTING123");
Utilities.sleep(10000);
}
lock.releaseLock();
}
2
function myFunction() {
var lock = LockService.getScriptLock();
lock.tryLock(5000);
if (!lock.hasLock()) {
Logger.log('Could not obtain lock after 5 seconds.');
}
else {
Logger.log('got the lock');
Browser.inputBox("TESTING123");
Utilities.sleep(10000);
}
lock.releaseLock();
}
with the proposed try catch statement
function myFunction() {
var lock = LockService.getScriptLock();
try {
lock.waitLock(5000); // wait 5 seconds try to get lock
} catch (e) {
Logger.log('Could not obtain lock after 5 seconds.');
}
Utilities.sleep(10000);
Browser.inputBox("TESTING123");
lock.releaseLock();
}
the popup box appears in all cases. It shouldn't, because the popup box hasn't been filled in and resolved... even with putting a delay after the popup box line. I have decided to take to making my own locking system as it doesnt seem that the google system will be working for me since I need the lock to remain valid after popups.
In the above pseudo code, once the script doesn't get a lock it will still proceed to run the code. Is that the intended behavior? It is a better practice or option to throw a server busy message to the user. Like so:
var active_spreadsheet = SpreadsheetApp.openById("bbb");
// BEGIN - start lock here
var lock = LockService.getScriptLock();
try {
lock.waitLock(30000); // wait 30 seconds for others' use of the code section and lock to stop and then proceed
} catch (e) {
Logger.log('Could not obtain lock after 30 seconds.');
return HtmlService.createHtmlOutput("<b> Server Busy please try after some time <p>")
// In case this a server side code called asynchronously you return a error code and display the appropriate message on the client side
return "Error: Server busy try again later... Sorry :("
}
// note: if return is run in the catch block above the following will not run as the function will be exited
var active_sheet = active_spreadsheet.getSheetByName("ENTRIES");
var new_start_row = active_sheet.getLastRow() + 1;
// Do lots of stuff - ie apply dynamic background colors based on previous entries colors, define the target range and set values, set data validations
SpreadsheetApp.flush(); // applies all pending spreadsheet changes
lock.releaseLock();
// END - end lock here
return;