Pause/Wait in a Map Reduce script

I have a Map/Reduce script that maps a list of customers, generating a unique report and emailing to each customer.

In the past I’ve noticed that without any delay, many emails won’t be delivered since the script is attempting to send multiple every minute. I found a post somewhere that suggested using the following function to add pauses:

function pause(waitTime) {
	try {
		var endTime = new Date().getTime() + waitTime * 1000;
		var now = null;
		do {
			now = new Date().getTime();
		} while (now < endTime);
	} catch (e) {
		log.error('ERROR', 'not enough sleep');
	}
}

Which worked well in the past when I was usually doing 30/45 second pauses at the end of each map.

I now have a scenario where I may need to send a few emails in a single map function. By pausing in between each send, the necessary wait time becomes 90-120 seconds.

Unfortunately, it becomes unpredictable but usually after 70-80 seconds the function errors with “SSS_INSTRUCTION_COUNT_EXCEEDED”. As mentioned in the NetSuite Help docs:

NetSuite has put internal mechanisms in place to detect “runaway scripts” that include infinite loops. When they are caught, the execution of these scripts is terminated and an SSS_INSTRUCTION_COUNT_EXCEEDED error message is thrown. If you receive this error, you should examine all of the execution loops in your script to ensure that they contain either a terminating condition or a condition that can be met.

Is there anything I may be able to do to prevent this error? When I add a counter to the pause function, it is reaching ~30 million executions. Is there some complex computation that could be added so each loop of the pause function takes longer? Other suggestions?

Beginner Asked on January 22, 2020 in SuiteScript.
Add Comment
2 Answer(s)

The answer is that you probably shouldn’t be sending that many emails through a map / reduce.  The email function has a limit of 10 recipients  (recipient + cc + bcc) and a size limit. If you are exceeding any of these limits that may explain why your emails aren’t sending. Inboxes might also be seeing your emails as spam and throwing them out. Keep in  mind if you are working in a sandbox your emails might not be behaving like they would in production.

In any case there is no server side pause method BUT you can do something like a saved search on all Customers or Transactions if you want the script to waste time without using too much usage or instructions but its inadvisable. You could also have the script run for an arbitrary amount and then reschedule itself in the summary stage to keep running if it hasn’t finished emailing everyone and that should waste time as well. Take a look at the task module

You may want to consider reworking your design. You could put a UE on a customer record that sends an email and do a mass update / touch each customer record using a map / reduce to trigger each record to send an email.

Beginner Answered on January 23, 2020.
Add Comment

The wait methodology seems like a hack to me.

Can you not attack the underlying issue with email sending instead? Was this simply a speed issue with the mail queue struggling to cope with the volume, or an actual send rate error?

Which method were you using to send – email.send, email.sendBulk, email.sendBulk.promise, etc?

Beginner Answered on January 23, 2020.

Many emails show up in the Undelivered Emails list with Reason: “Not sent: Blocked by mail filter”.

I’ve been using email.send since the bounce notifications are typically necessary.

on January 23, 2020.
on January 23, 2020.

From this thread it looks like the inbox is the issue not the timing in the Map/Reduce. You’ll likely need to figure out the reasoning behind it rejecting your emails and fix that. Once resolved you can likely keep your map/reduce as is.

on January 24, 2020.

battk’s suggestion is probably along the right lines. I’ve had similar issues in the past with stock status emails. Adding a unique document number in each subject line stopped the issue.

on January 27, 2020.
Add Comment

Your Answer

By posting your answer, you agree to the privacy policy and terms of service.
  • This site made possible by our sponsors: Tipalti