We implement NetSuite with world-class passion and professionality, making the experience with the #1 ERP cloud software even more awesome.

Emulate the nlapiYieldScript API in SuiteScript 2.x

This is a follow-up on our previous post where we have announced the release of a process for migrating any script from SS1 to SS2 without re-implementing the logic (https://www.ketka.eu/2021/08/03/migrate-from-suitescript-1-0-to-2-x-in-the-blink-of-an-eye/).

While most of the scripts we have migrated so far are a one-click operation, in some cases the code must be adjusted in order to keep working after the migration.
One of theses case is a scheduled scripts that uses the nlapiYieldScript API.

Let's take the following sample pseudo-code, which represents the entry point of a SS1 scheduled script.

function execute() {
  
  var transactionIDs = [...]; // array of transaction IDs loaded via a search, script parameter, etc.
  
  // loop over the transaction IDs
  for (var i = 0; i < transactionIDs.length; i++) {
  
    // load / set / submit current transaction ID + other I/O operations
    [...]
    
    // is we are below a certain usage threshold, yield the script
    if (nlapiGetContext().getRemainingUsage() < 1000) {
      nlapiYieldScript();
    }
    
  }
  
}

In order to migrate this script to SS2, we need to create a mechanism that, when the nlapiYieldScript API is called:

  • stores the current script advancement status in NetSuite
  • re-schedules the script execution
  • when the execution restarts, loads the previously stored status

We have created utility functions in order to support the above changes in a scheduled script.
Taking again the example above, the code should be rewritten in the following form, after that it is possible to convert the script to SS2 with our 1-click tool.

// global variable that must contain the relevant information describing the script execution status
ss2YieldScript_Status = {
  transactionIDs: null,
  currentTransaction: 0
};
// wrapper to the original entry point function
function execute() {
  ss2YieldScript_Handle(function() {
    execute_OLD();
  });
}
  
function execute_OLD() {
  
  var transactionIDs = null;
  if (ss2YieldScript_Status.transactionIDs != null) {
    transactionIDs = [...]; // array of transaction IDs loaded via a search, script parameter, etc.
  }
  
  // loop over the transaction IDs
  for (var i = ss2YieldScript_Status.currentTransaction; i < transactionIDs.length; i++) {
  
    // load / set / submit current transaction ID + other I/O operations
    [...]
    
    ss2YieldScript_Status.currentTransaction++;
    
    // is we are below a certain usage threshold, yield the script
    if (nlapiGetContext().getRemainingUsage() < 1000) {
      nlapiYieldScript();
    }
    
  }
  
}

Some explanations on how it practically works.

  • We have re-implemented the nlapiYieldScript, and it simply throws an error with a very specific code.
  • The ss2YieldScript_Handle wraps the whole entry point with a try/catch block, and if the caught error has that specific code set by nlapiYieldScript, then the function ss2YieldScript_Handle stores the value of the global object ss2YieldScript_Status in the file cabinet, and reschedules the execution of the current script / deployment
  • The ss2YieldScript_Handle also takes care of checking if a state was previously stored in the file cabinet, and if that's the case, it loads with that state the global object ss2YieldScript_Status before calling the entry point function

This is just a very simple example, we have migrated very complex scheduled scripts where the state was a much bigger object, and they work like a charm, and can now be enhanced using SS2 libraries :)

More in general, this mechanism allows to continue using the yield-script approach while writing SuiteScript 2.x code, for those who prefer it over other alternatives.

alessio |
August 20, 2021

Leave a Reply

Your email address will not be published. Required fields are marked *