Voiceglue Logger says Maximum loop count exceeded. There is probably an infinite loop of in your VXML document - asterisk

Can Any please explain why this is happening. what are the possibilities of errors that are been counted as I have set maxerrorcount = 3
EROR OPEN_VXI luke---- callid=[68] |1098905920|68|CRITICAL|com.vocalocity.vxi|216|VXIinterpreterRun: Maximum loop count exceeded. There is probably an infinite loop of in your VXML document.|URL
Please let me know if any further details are required.

Perhaps, "infinite loop" means to call same form again and again,
And it was not inserted caller input process(menu, field and record form) in this loop.
For example
<form id="errorForm"><!-- Loop Start -->
<block>
<!-- something -->
</block>
<block>
<goto next="errorForm" /><!-- Loop End -->
</block>
</form>

Bladean's answer is probably the correct one. There is an alternate possibility. If an application is structured has looping logic that cycles through the same form or page as it processes data (e.g. a long list), you can trigger these types of checks. I have had to increase a similar loop counter, for some applications, on another platform.

Voice browser all have infinte loop detection to save them from pitfalls .
It could be something as simple as the "goto where I am coming from example" within the same VXML document example provided here by Bladean Mericle .
It could be burried deeper in a global catch that routes calls to a catch all sub application which in turn bring the flow back to the originating dialog .
Definetely Infinite Loops will never work in VXML .

Related

SendGrid Handle bars variable in json not show up when used a second time

I have this handle bars statement in SendGrid. When using the variable taskCount the value is only used in the greaterThan block. The other 2 times it is used it appears to be null.
Here is the json data
{
"Username":"ChampCbg",
"JoinedAt":"12/1/2020",
"DaysSinceJoined":"20",
"taskCount":5
}
here is statement with handlebars
{{#greaterThan taskCount 0}}
Congrats on starting {{insert taskCount "default=1"}} task{{#greaterThan taskCount 1}} (s){{/greaterThan}} and taking the first small step.
{{else}}
You have not started a task yet. What are you waiting for? It has been {{DaysSinceJoined}} days since you joined on {{JoinedAt}}.
You have missed {{DaysSinceJoined}} days where you could been making Small Steps towards the dreams of you better tomorrow.
{{/greaterThan}}
Here is the end result
Hello ChampCbg!
Congrats on starting 1 task and taking the first small step.
Don't let another day pass you by. Start designing you vision board
today.
As the results show the greaterThan block selects the correct statement, but then next times taskCount is used the default value and null value are chosen.
What is the cause of this?
Twilio SendGrid developer evangelist here.
Honestly, I thought your template would work as you wrote it. But I tried it out and it did not (not that I didn't believe you, I just had to do that to work out what to do!).
So, the way to deal with this is to refer to the variables in your data using the #root object within the greaterThan conditional (or other conditionals).
Try this as your template:
{{#greaterThan taskCount 0}}
Congrats on starting {{insert #root.taskCount "default=1"}} task{{#greaterThan #root.taskCount 1}} (s){{/greaterThan}} and taking the first small step.
{{else}}
You have not started a task yet. What are you waiting for? It has been {{#root.DaysSinceJoined}} days since you joined on {{#root.JoinedAt}}.
You have missed {{#root.DaysSinceJoined}} days where you could been making Small Steps towards the dreams of you better tomorrow.
{{/greaterThan}}

IBM Watson Assistant - Return after digression without responding again

I'm wondering if I can use a digression with a return to the previous flow, without having the bot responding again.
For the details, I'm using digressions so the user can jump from a child node to a root node (for example "wait"). The problem is that the conversation looks like this :
Hello, I'm Watson.
How are you ?
Fine and you ?
Wait a second... // Digression to node 'wait'
I'll hold on. // Digression back to previous node
Fine and you ? // I would like this not to be said again.
Any way of doing so without catching the "digression event" in back-end and manually delete the second "Fine and you ?" ?
Put <? clearDialogStack() ?> and digression will be cleared.

How to create an alert to notify an user when some amount % of threshold reached DailyAsyncApex Executions

On 2 occasions in the past month, we have managed to hit our daily limit on asynchronous apex executions. Salesforce temporarily increased our limit to 425000 but it will be scaled down to 250000 in a week's time. Once we reach the limit, a lot of the SF functions will fail and this has tremendously impacted both internal staff and external customers.
So to prevent this from happening in the future, we need to create some kind of alert in Salesforce to monitor our daily asynchronous apex method executions. Our maximum daily limit is 250000. The alert will need to create a P3 helpdesk ticket and notify couple of users say USER A and USER B once it reaches 70% threshold.
Kindly advise what is possible to achieve the same
Thanks & Regards,
Harjeet
There's a promising Limits method but it doesn't seem to work currently ("reserved for future use"): System.debug(Limits.getAsyncCalls() + ' / ' + Limits.getLimitAsyncCalls());
There's an idea you can upvote: https://success.salesforce.com/ideaView?id=0873A0000003VIFQA2 ;)
You could query SELECT COUNT() FROM AsyncApexJob WHERE ... but that sounds like a bad idea ;)
I think your best course of action is to use SF REST API. There's a "limits" resource you can fetch. You could do it from SF itself (bad idea because if you'd schedule it to run every hour then well, of course it will contribute to the limit consumption too ;)) or from some external app that'd connect to your SF...
https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/dome_limits.htm
You can quickly try it out for example in workbench.developerforce.com before you decide you do want to deep dive into coding it.
Of course if you have control over your batch jobs, queuable, schedulable & #future calls you could implement some rough counter of executions in a helper object for example... won't help you much if most of the jobs are coming from managed packages though...
Got 1 more idea but it's pretty hardcore - you should be able to make a REST API call from javascript. so you could create a simple VF page (even without any apex controller), put JS callout on it, have it check every 5 mins and do something if threshold is hit... But that means IT person would have to have this page open all the time (perhaps as a home page component)... Messy :)
I was having the exact same issue so I created a simple JsForce script in NodeJS to monitor the call to the /limits endpoint.
You can connect a Free Monitoring service like UpTimerobot.com or PingDom.com and get an email when you find the Word "Warning" >50% or "Error" > 80%.
async function getSfLimits() {
try {
//Let's login into salesforce
const login = await conn.login(SF_USERNAME, SF_PASSWORD+SF_SECURITY_TOKEN);
//Call the API
const sfLimits = await conn.requestGet('/services/data/v51.0/limits');
return sfLimits;
} catch(err) {
console.log(err);
}
}
https://github.com/carlosdevia/salesforcelimits

Change music on hold during Dial()

I'm using the parameter m(mymusic) in my call to Dial() to let the caller hear some music instead of the boring ring tone. However I'd like to have a different music file after some time. The time when the music changes should easily be changeable (by editing a variable), so it is no option to just create a music-on-hold-file which has X seconds of music 1 and then Y seconds of music 2.
What I want is basically this, but without a second Dial() and without an actual second call to ${device}, because that creates two "missed call" entries for one missed call, and it interrupts the phone's ring tone.
Set(time_until_new_music=20);
Dial(${device},${time_until_new_music},gm(music1));
if ( "${DIALSTATUS}" == "NOANSWER" ) {
Dial(${device},,m(music2));
}
Is this possible somehow?
Hold class can have unlimited number of different sound file of any length
Number of musiconhold classes also unlimited. So you can create your own set for every need
However you can't control from dialplan class info. You can use external steaming app and forward to that app param you need. Require expert level in both asterisk and linux.
Something like this may work:
s,1,Set(time_until_new_music=20)
s,2,Dial(${device},${time_until_new_music},gm(music1))
s,3,GotoIf($[${DIALSTATUS}=NOANSWER]?s,4:s,5)
s,4,Dial(${device},,m(music2))
s,5,Hangup()

VBScript Out Of Memory Error

I have a classic ASP CRM that was built by a third party company. Currently, I have access to the source code and am able to make any changes required.
Randomly throughout the day, usually after some prolonged usage by users, most of my pages start getting an Out of Memory error.
The way that the application is built, is all the pages and scripts pull core functions from a Global.asp file. In that file are embeds to other global files as well, but the error presented shows
Out Of Memory
WhateverScriptYouTriedToRun.asp Line 0
Line 0 is the include for the global.asp file. Once the error occurs, after an unspecified amount of time the error occurence subsides for some time but then begins to reoccur again. With how the application is written, and the functions it uses, and the "diagnostics" I've already done - it seems to be a common used function that is withholding data such as recordset or something of that nature and then not releasing it properly. Other users then try to use the same function and eventually it just fills up causing the error. The only way for me to effectively clear the error is to actually restart IIS, Recycle the App Pool, and Restart the SQL Server Services.
Needless to say, myself and my users are getting annoyed....
I can't pinpoint the error due to the actual error message presented being Line 0 - but from there I have no idea where in the 20K lines of code it could be hanging up. Any thoughts or ideas on how to isolate or at least point me in the right direction to begin clearing this up? Is there a way for me to increase "memory" size for VBScript? I know there is a limitation but is it set at say...512K and you can increase it to 1GB?
Here are things I have tried:
Removing SQL Inline statements into Views
Going through several hundred scripts and ensuring that every OpenConnection & OpenRecordSet is followed by an appropriate Close.
Going through the Global File and commenting out any large SQL statements such as ApplicationLog (A function that writes the executed query into a table).
Some smaller script edits.
Common Memory Leak
You say you are closing all recordsets and connections which is good.
But are you deleting objects?
For example:
Set adoCon = new
Set rsCommon = new
'Do query stuff
'You do this:
rsCommon.close
adocon.close
'But do you do this?
Set adoCon = nothing
Set rsCommon = nothing
No garbage collection in classic ASP, so any objects not destroyed will remain in memory.
Also, ensure your closes/nothings are run in every branch. For example:
adocon.open
rscommon.open etc
'Sql query
myData = rscommon("condition")
if(myData) then
response.write("ok")
else
response.redirect("error.asp")
end if
'close
rsCommon.close
adocon.close
Set adoCon = nothing
Set rsCommon = nothing
Nothing is closed/destroyed before the redirect so it will only empty memory some of the time as not all branches of logic lead to the proper memory clearance.
Better Design
Also unfortunately it sounds like the website wasn't designed well. I always structure my classic ASP as:
<%
Option Explicit
'Declare all vars
Dim this
Dim that
'Open connections
Set adoCon...
adocon.open()
'Fetch required data
rscommon.open strSQL, adoCon
this = rsCommon.getRows()
rsCommon.close
'Fetch something else
rscommon.open strSQL, adoCon
that = rsCommon.getRows()
rsCommon.close
'Close connections and drop objects
adoCon.close
set adoCon = nothing
set rscommon = nothing
'Process redirects
if(condition) then
response.redirect(url)
end if
%>
<html>
<body>
<%
'Use data
for(i = 0 to ubound(this,2)
response.write(this(0, i) & " " & this(1, i) & "<br />")
next
%>
</body>
</html>
Hope some of this helped.
Have you looked at using a memory monitoring tool to see how much memory fragmentation is happening? My guess at a possible cause is that some object of a size is trying to be created but there isn't enough room in the memory to store it as one contiguous chunk. Imagine needing room to store an object that would take 100 MB and while there may be several hundred megabytes free, the largest contiguous chunk is 90MB then this doesn't fit.
Debug Diagnostic Tool v1.1 would be a tool where Bernard's articles may help in understanding how to use the tool.
Another thought is the question of how much string concatenation is there in the code? I remember where I used to work had problems with doing a lot of string concatenation operations that sucked up memory that may be another idea to consider.
Yeah, I could see some shock at that kind of number the first few times you see it but then if you understand what the code is doing it may make sense for why so much space gets reserved right off the bat at times.
I haven't used that debug tool specifically but I did have a tool that took a snapshot of memory when pages were hung so I couldn't tell if there was a performance impact of the tool or not. Course in my case I used a similar tool in 2004 so it has been a few years since I've had to research this kind of issue.
Just going to throw this in here, but this problem has taken a long time to solve. Here's a breakdown of what we did:
We took all the inline SQL and made SQL Views, every SELECT statement is now handled with a VIEW first.
I took every single SQL INSERT and UPDATE (as much as I could without breaking the system) and put them into Stored Procedures.
#2 was the one item that really made the biggest difference
Went through several thousand scripts, and ensured that variables were properly disposed of, and all the DB Open Connections were followed correctly with a Close Connection and same with Open/Close RecordSet.
One of the slow killers was doing something like:
ID = Request.QueryString("ID)
at the top of the page. Before redirecting, or closing a page, there is always a:
Set ID = Nothing
or the complete removal of the inference.

Resources