I have one backend function to append new rows to a Google Sheet and a lock service is used to prevent the conflicts of multiple users.
sh.appendRow(record);
Another backend function is to delete rows from the same sheet and a lock service is used as well.
sh.deleteRow(posIndex+2)
While I have concern that one user is appending a row at the same time as another user is deleting a row, will it cause any trouble? Since the lock service is used independently in these two functions, they will not lock each other.
The Lock Service has three scopes,
User
Document
Script
Using the the document scope is very likely to be the best option. For this use getDocumentLock().
Related
How to understand LockService and implement it correctly?
How to check if a function in Google App Script is already being executed by another user?
Related
My html form uploads data to a spreadsheet with a Google script. I use the following function to prevent a conflict, since many users are accessing the web app page:
function lockservice() {
var lock = LockService.getScriptLock();
lock.waitLock(30000);
lock.releaseLock();
}
I have another script to retrieve the data (separate script), that also has many users accessing it. So do I need getscriptlock for that also?
In another words, is there a conflict between users occuring when getting the data or only when uploading it? or maybe in both cases.
If you are writing data to the spreadsheet with:
sheet.appendRow(array);
then you don't need Lock Service to write data. If you are using:
sheet.getRange().setValues(array_2_D);
Then you do need Lock Service.
So, appendRow() is "atomic" and setValues() is not. Atomic meaning that each operation runs completely independent from each other.
https://developers.google.com/apps-script/reference/spreadsheet/sheet?hl=en#appendRow(Object)
Getting values should use Lock Service if you have concurrent users. There is also a quota limit for concurrent users. The limit for "Simultaneous Executions" is 30, (at the time of this post)
https://developers.google.com/apps-script/guides/services/quotas#current_limitations
I have actually have the same understanding but:
I have a script where Lock Service is used and the locked section also includes a appendRow() operation to the sheet.
The script allows up to 30 concurrent executions.
Despite knowing that appendRow()is stated to be atomic, I now experience that appendRow() actually may overwrite the last used row on a sheet!
I never experienced this behavior without making use of the Lock Service.
Anybody else observed this unexpected behavior?
In the linked screenshot you see the new Date() value of the previous record being replaced instead of an entire new row being appended below.
Any thoughts & suggestions to overcome this behavior are highly appreciated.
Screenshot: appendRow() replaces last row of sheet:
I'm programming a Telegram bot with GAS. Am I right in thinking that whenever I store something using userProperties, like
userProperties.setProperty('name', 'Alex');
the value gets stored for this particular instance of the script AND this particular user? Does it mean that if there are 10 more or less simultaneous instances of this script by ten different users, I will later be able to retrieve each user's respective name by calling
var username = userProperties.getProperty('name');
I get the impression that sometimes there's some sort of interference happening that results in retrieving values different from those stored for this or that user. Would appreciate some clarity here.
IMPORTANT:
UserProperties has been deprecated, use PropertiesService.getUserProperties() instead.
As you can see in the documentation
getUserProperties()
Gets a property store that only the current user
can access, and only within this script.
So indeed, if the script can be accessed by several users, PropertiesService.getUserProperties() will always retrieve the properties of the specific user who runs the script, and if there will be 10 simultaneous script executions - each user executing the script will retrieve different user properties.
I am familiar with the Lock Service but that is only for locking scripts.
I have some code that will "process" a large Google Sheet. My script needs to re-order the rows. I need/want to make it so while the script is running nobody else can change the order. However, I still need another script to be able to append rows.
We use a Google Form for our team's intake. It appends rows to a sheet. I have an hourly job that will go through all the rows/records and "process them". I have a column that stores the last time a record/row was "processed". I want to sort on that column such that the "oldest" records are on top and then start processing from the top down. If the script fails or times out then the next iteration will just start over...
I know I could use getValues or getDisplayValues to get an array and then write the array back but I worry what would happen if someone sorted the rows as it would muck things up when writing the array back.
Is there some way to accomplish my goal? I want to be able to process the records, and maintain row order to avoid breaking my processing.
The way to block a spreadsheet "completely" is by changing the spreadsheet sharing settings. Remove all editors or change them to viewers, once your script finish, change them back as editors. In a extreme case, usa a second account to act as the owner of the critical files / spreadsheets and only use it for this purpose,so you could block your regular account for doing changes to the spreadsheet.
NOTE: A Google Form editResponseUrl could be used to edit the linked spreadsheet.
I'm facing a similar situation but I took a different approach, I'm using an index/key column (you could use the timestamp column) and using the index/key to save each edited row to the right position, then write the whole resulting array in a single operation (by using setValues()). In my case this is simple because I only require values, I'm not worried about notes, data validation, conditional formatting, comments, etc. and there isn't a Google Form linked to my spreadsheet.
Related
Google Spreadsheet -- get sharing permissions by script
Any way to share google docs programmatically?
This question already has answers here:
build real time dashboard using google apps script
(3 answers)
Closed 2 years ago.
I'm developing a Web App using google apps script and a spreadsheet as storage.
Basically, an HTML showing some tables for the different tabs.
From my app, users can add new tasks, edit tasks, and mark tasks as completed.
Since there are many users using the app, the data showed on each client will get outdated very fast.
I would like to update the app with new records and changes to the existing ones as soon as possible.
I thought in logging the last edit tab+row in a cell and pull that data from the server every minute, but, what if many entries are added/edited during that minute?
I think WebSocket is not possible. Any other idea?
I'm using JQuery client-side.
To help avoid conflicts, give every task a unique ID. Something like creation time + random string. That way you can look it up in the spreadsheet. Also, I think the Lock Service can prevent concurrent edits temporarily to avoid conflicts:
https://developers.google.com/apps-script/reference/lock/
To check for updates, try polling the last edit time of the spreadsheet. If it's greater than the previous poll, fetch updates.
https://developers.google.com/apps-script/reference/drive/file#getLastUpdated()
No other way besides polling. You can't have sockets or callbacks from HTML service. You could poll frequently but that may run you out of quotas.
If you really want to poll and avoid quotas you can log the last edit on a published public spreadsheet and read it with ajax from the client, however published spreadsheets update every minute only.
You could try something like this:
var lock = LockService.getPublicLock();
var success = lock.tryLock(10000);
if (success) {
// check your spreadsheet for lastUpdated or PropertiesService.getScriptProperties();
}
} else {
// do something else (try it again or error msg)
}
lock.releaseLock();
I have found that it works well on my app and I have around 1000 users.
I'm new and appreciate help on my question!
My spreadsheet acts as a sales tool, where info is entered in various cells to run sensitivity analysis. Once the salesperson picks a desired option they "submit it". The data submitted is then stored on a separate sheet in the spreadsheet (call it the "database").
I want the database sheet to store all user submissions. The problem is when multiple users are using the sales tool worksheet at the same time, the info they enter gets overwritten by other user's inputs before they can submit.
I'd like multiple users to be able to use the "sales tool" sheet simultaneously without overwriting eachother, but still be able to submit data to the "database" sheet.
Appreciate ideas?
You can use the Lock Service to take a lock on the spreadsheet and then release it once you've written to it.
Besides the Lock Service (already mentioned by Srik) there's the Sheet.appendRow function, which is way easier to use and much faster. But only makes sense if you're inserting new data to a sheet and not really writing to the same cells.
Can't you use a form?
This way people could insert data without actually modify the spreadsheet...