I have created an scheduled script to perform some...
# suitescript
r
I have created an scheduled script to perform some logic in a record that runs out of units when performed in a User Event Script for a transaction with many lines. It is trigger in an afterSubmit in an user event script. That UE script is the last one to execute in the Sales Order. That UE script, the context has been adjusted to NOT run when triggered via SCHEDULED context execution, thus preventing double execution/submission of the Scheduled Script. The Scheduled Script takes as a parameter the ID of the order, and it loads the record, performs some logic and changes on it, and then save it. If you run the Scheduled Script on demand, adding manually a Sales Order parameter, it runs smoothly with no problem. However, if you run it via the User Interface (so, upon clicking on Save, which triggers the UE than the submits in afterSubmit the scheduled script), sometimes you might get the following error: Error | {"NAME":"RCRD_HAS_BEEN_CHANGED","MESSAGE":"Record has been changed","SUITESCRIPT": Which seems due to a race condition, that somehow the original order has not yet being fully saved by NetSuite when the scheduled script has load the record (and then having the error upon saving in the scheduled script). So, as a temporally solution I am putting to sleep the scheduled script for 20 seconds before loading the record, and that is doing the trick to avoid the issue, saving without problems. Those 20 seconds waiting have no impact in the remaining usage limit (I have check this by printing it). Is there other way?
Also, if not, I was thinking whether it would be possible to make the sleep dynamically, in the sense of somehow only triggering the scheduled script when the Transaction is fully saved and no collusion is possible. So if it only needs to sleep 7 seconds, then do not wait 13 more seconds, for example. Also, I am putting a try/catch in the Schedule Script, so even if it fails the status is Complete. I guess this error would make the script to be set to "Failed" Another option that might be interesting is if somehow I could manually put the status to "Retry" - -> Retry. This status indicates that the script entered the processing state, but failed to complete normally. In this case, the script is eligible to be retried. The script will be retried automatically — you do not need to create a new deployment. Review the script execution log to help you determine why the script initially failed (for example, a timeout problem occurred).
c
Add a flag on the record that the scheduled script loads The UE script will tick the flag AfterSubmit.
Then get the scheduled script to load a saved search which will include records with your 'needs processing' flag checked. The scheduled script will untick that flag after processing.
You'll now never process a record that isn't ready for processing
Outside of a re-architecture of your solution, not sure what might be better.
b
you will probably need to figure out what is making the update that is causing your error
hopefully you can use something like the last modified date (you will not enjoy using the system notes)
s
I also don't know any legitimate way to 'sleep 20 seconds' with SuiteScript so I concur with trying to find root cause.
s
What exactly are you doing in a userevent that could consume all the points. Maybe you should completely offload the work to scheduled (to avoid conflicts), or optimize/combine whatever data retrieval pieces to reduce the point usage.
r
Thank you @Craig for your suggestion. Thing is that I am afraid I might end up in the same situation. Since theoretically, the afterSubmit my User Event Script is like the last custom line of code that should be executed, the one that submit the scheduled script, and I am not executing a saving or something like that after it, so from the script side it should not trigger the RCRD_HAS_BEEN_CHANGED error. However, as @battk Batk pointed out, it would be interesting to see what's causing the issue, the RCRD_HAS_BEEN_CHANGED. And I have realized that there are some workflows with some logic in afterSubmit (in the account where I have noticed the error, in other one it was not popping up). I could not find an article to see what goes first, if afterSubmit scripts or workflows, but I believe that might be what is causing the record change error. Anyone knows about this? @Sandii there is a lot of custom records created, look-ups and searches. Definitely some optimization could be done. But pretty much now all the work is offloaded to the scheduled script at this point, but is still being submitted from the UE. Also the issue about all the points being consumen only happened for non-common cases ( > 20 lines in a transaction)
@stalbert this works fine in the scheduled script (see code below). If you would use it in a, for example, client script, I guess you would block the whole thread and it would be impossible to work in the page. But since it is in the schedule script, I believe is ok, even thought I would like a better approach. Basically now, the scheduled script, if it detects the record change error the 1st time it is submitted (which at the moment I presume is due to workflows), it resubmits again itself 20 seconds later. The 2nd time always works fine, as the original record is fully solved at that point
Copy code
function sleep(milliseconds) {
                    const date = Date.now();
                    var currentDate = null;
                    do {
                            currentDate = Date.now();
                    } while (currentDate - date < milliseconds);
            }
I could not figure out how to set the retry status for a scheduled script. I guess only NS can do that. If I get the record change error at saving, and I do not put a try catch, then the scheduled scripts gets status failed. That's why I am doing the "resubmit" thing myself. I am referring to this comment I wrote before: Another option that might be interesting is if somehow I could manually put the status to "Retry" - -> Retry. This status indicates that the script entered the processing state, but failed to complete normally. In this case, the script is eligible to be retried. The script will be retried automatically — you do not need to create a new deployment. Review the script execution log to help you determine why the script initially failed (for example, a timeout problem occurred).
s
IMHO, this
sleep()
approach is NOT ok. It blatantly wastes computing resources on the account.
r
Agreed, that's why I was seeking for advise, I was hopeful of the retry status of the scheduled script would be an option for example. That being said, so far in all my testing the sleep function is only happening once, second time it always works as expected, and I am reducing it to 10 seconds.
s
the best idea I've heard for a 'blocking' delay in a script is to use https to call out to some service that simply performs the delay. e.g. have some external service that takes a delay parameter and simply waits that long before returning a value to the caller.
r
That's very interesting, but I am not sure if it will be feasible in my case since is important to not relay in a 3rd party service to perform some logic within NetSuite
s
aye, it's a tradeoff.
b
although not documented, suitescript entry points run before workflow entry points
so workflows that have actions that run in after record submit that change the saved record trigger another save
dont interpret that to mean that workflow before record submit run after user event after submit
r
Ah great to know @battk, I believe this is what causes the change in the record and therefore the error, because the account does have workflows in afterSubmit that changes the record