<div dir="ltr">Tanner, I ran a test and actually, anything inside the Do step will block events.<div><br></div><div>As a test, I used this Do step:</div><div><br></div><div>Do {</div><div> int i = 0;</div><div> do {</div><div> i++;</div><div> } while (i <= 100000000);</div><div>}</div><div><br></div><div>And then hang up the a call during the do step, and see that nothing happens; no interrupt. However, the label we ask the script to goto on CIE is then the label which is executed next. This seems obvious when you consider that there isn't a toggle-able option for interrupt handling on the Do step.</div><div><br></div><div>But back to your method of handling callbacks, because I find it so interesting.</div><div><br></div><div>I found that if in script 2, if the Agent just hangs up, you cannot re-queue the call, because CL2 is now dead. And in order to generate a new active Contact Leg, you'd need to re-do the place call step, which means you would need to signal something back to script 1.</div><div><br></div><div>Signaling between two running scripts is non-trivial and requires polling, since Cisco hasn't implemented promises yet. ;)</div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Mon, Nov 11, 2019 at 2:13 PM Anthony Holloway <<a href="mailto:avholloway%2Bcisco-voip@gmail.com">avholloway+cisco-voip@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr">Tanner, That was tongue in cheek my man. I was really looking forward to having more of a conversation with you about the thread locking solution, and balancing the pros and the cons with it.<div><br></div><div>Also, I'm still confused how you are doing your solution, pertaining specifically to keeping script 1 alive, as I have found that it needs to remain alive, else you lose Leg 1's Contact (likely due to it being Garbage Collected).</div><div><br></div><div><br></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Fri, Nov 8, 2019 at 11:43 AM Anthony Holloway <<a href="mailto:avholloway%2Bcisco-voip@gmail.com" target="_blank">avholloway+cisco-voip@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div><img src="cid:ii_k2qfi9pg0" alt="image.png" width="311" height="366"><br></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Wed, Nov 6, 2019 at 6:18 PM Anthony Holloway <<a href="mailto:avholloway%2Bcisco-voip@gmail.com" target="_blank">avholloway+cisco-voip@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr">To your last point about CIE: it doesn't work for me anyway, and I'm not trying to have the script do anything else, so threadlocking doesn't sound all that bad. Unless of course you're trying to tell me that it's not just the thread my script is running within, but the entire CCX Engine as a thread, then yeah, that's pretty terrible. Though, I just did a test, where I thread slept for 100 seconds in script A, and during that time, called into script B, and made sure everything worked fine while the threadlocking should have been taking place. So, I would say it's not the CCX Engine as a whole, and likely each script is executed in its own thread. This should be acceptable in this one use case.<div><br></div><div>It's still a mystery to me how you're handling script 1.<div><br></div><div>It kind of sounds like you are doing a 999s delay loop, but are you checking for the contact to be active still with the Get Contact Info step? So, essentially the same thing I was doing, but with script steps instead (and less frequently)? If so, then your script 1 stays active for ~15 minutes, worst case scenario, after the callback has been completed, correct?</div><div><br></div><div>E.g.,</div><div><font face="monospace"><br></font></div><div><font face="monospace">CL1 = Place Call ()</font></div><div><font face="monospace"> Successful</font></div><div><font face="monospace"> LABEL0:</font></div><div><font face="monospace"> Delay 999s</font></div><div><font face="monospace"> is_active = Get Contact Info (CL1)</font></div><div><font face="monospace"> If (is_active)</font></div><div><font face="monospace"> True</font></div><div><font face="monospace"> Goto LABEL0</font></div><div><font face="monospace">End</font><br></div></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Wed, Nov 6, 2019 at 5:55 PM Tanner Ezell <<a href="mailto:tanner.ezell@gmail.com" target="_blank">tanner.ezell@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr">I place an exception handler for contact inactive, checking for the callback contact via get Contact Info step to make sure the caller hanging up didn't catch the exception.<div><br></div><div>From there I have programmed in resiliency for the callback to be hung up by the agent, but beyond that there is a Delay 999s loop. You'll never hit the limit as you've discovered.</div><div><br></div><div>Would not recommend Thread.sleep inside your code as it will thread lock the task and may interfere; for example, it may prevent the CIE to be caught properly in that script. Use Delay step, it's thread safe and is built in a way that allows exceptions to be handled.</div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Wed, Nov 6, 2019 at 4:46 PM Anthony Holloway <<a href="mailto:avholloway%2Bcisco-voip@gmail.com" target="_blank">avholloway+cisco-voip@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr">Ok, so I solved the looping thing by...well...looping. :/<div><br></div><div>So, loops themselves are not the problem, rather it's the finite script steps we can execute which are the problem...err...challenge.</div><div><br></div><div>Since the CIE doesn't get thrown in script 1 properly (bug?), I used a Do step in the success branch of the Place Call step to wait for the active state of CL1 to change. Like so:</div><div><br></div><div><font face="monospace">Do {<br> <font color="#0000ff">do</font> {<br> java.lang.Thread<font color="#ff9900">.sleep(</font><font color="#6aa84f">1000</font><font color="#ff9900">)</font>;<br> } <font color="#0000ff">while</font> (contact_leg_1<font color="#ff9900">.isActive()</font>);<br>}</font><br></div><div><br></div><div>CL1 only becomes inactive once the Agent acknowledges the callback and the call redirect is successful. Therefore, I get all the benefits of Tanner's solution, plus I can keep the max steps at 1,000, and technically queue for 12 hours (the CallManager default max call timer).</div><div><br></div><div>I think this should work just fine, though, more rigorous testing will be needed. What do you think?</div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Wed, Nov 6, 2019 at 5:10 PM Anthony Holloway <<a href="mailto:avholloway%2Bcisco-voip@gmail.com" target="_blank">avholloway+cisco-voip@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div>I see that the contact in both scripts is actually the same contact, but each script views the contact from a different leg/sequence number (I.e., Outbound leg versus Inbound leg)<br></div><div><br></div><div><u>Contact Created with Place Call Step (AKA CL1 for Call Leg 1)</u></div><div><u><br></u></div><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><div><font face="monospace">§com.cisco.wf.subsystems.jtapi.CallImpl§JTAPICallContact[<span style="background-color:rgb(255,242,204)">id=155</span>,<span style="background-color:rgb(217,234,211)">implId=633001</span>/1,state=STATE_ANSWERED_IDX,<span style="background-color:rgb(252,229,205)">inbound=false</span>,App name=App1,task=26000000240,session=3000000115,<span style="background-color:rgb(207,226,243)">seq num=0</span>,cn=2411,dn=null,cgn=2402,ani=null,dnis=null,clid=null,<span style="background-color:rgb(234,209,220)">atype=OUTBOUND</span>,lrd=null,ocn=2411,route=RP[num=0000],OrigProtocolCallRef=null,DestProtocolCallRef=000000000009A8A902F728A200000000,TP=2402]§</font></div></blockquote><div><font face="monospace"><br></font></div><div><font face="arial, sans-serif"><u>--Triggering Contact-- in the Queuing Script (AKA CL2 for Call Leg 2)</u></font></div><div><font face="arial, sans-serif"><u><br></u></font></div><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><div><font face="monospace">§com.cisco.wf.subsystems.jtapi.CallImpl§JTAPICallContact[</font><span style="font-family:monospace;background-color:rgb(255,242,204)">id=156</span><font face="monospace">,</font><span style="font-family:monospace;background-color:rgb(217,234,211)">implId=633001</span><font face="monospace">/1,state=STATE_ANSWERED_IDX,</font><span style="font-family:monospace;background-color:rgb(252,229,205)">inbound=true</span><font face="monospace">,App name=App2,task=26000000241,session=3000000115,</font><span style="font-family:monospace;background-color:rgb(207,226,243)">seq num=1</span><font face="monospace">,cn=2411,dn=2411,cgn=2402,ani=null,dnis=null,clid=null,</font><span style="font-family:monospace;background-color:rgb(234,209,220)">atype=DIRECT</span><font face="monospace">,lrd=null,ocn=2411,route=RP[num=2411],OrigProtocolCallRef=000000000009A8A902F728A400000000,DestProtocolCallRef=null,TP=2401]§</font></div></blockquote><div><br></div><div>So, things like Set/Get Enterprise Call Info work on the same contact, because they are leg independent, whereas things requiring media, like Play Prompt, are call leg dependent, and need to reference the correct call leg of the contact. Hence, you have to pass the CL1 object into Script 2, in order to interact with the Agent from CL1.</div><div><br></div><div>Unfortunately, if script 1 ends, there seems to be some clean up tasks which run at the end of script 1 to unload CL1 from memory, and I am getting an abort event in script 2, when trying to reference CL1. As is the case when I try to play media to the Agent or Call Redirect them to the callback number. If prevent script 1 from ending, and thus cleaning up after itself, CL1 stays alive and script 2 works great. The question for me now is, how do I release script 1, without also releasing CL1?</div><div><br></div><div>One thought I had was to setup a Contact Inactive listener in script 1, and use the Delay step in script 1 for an absurd amount of time, like 12 hours, and then rely on the fact that once CL1 transfers the Agent to the callback number, CL1 goes inactive, and thus the 12 hour delay is interrupted and script 1 can now end. In theory that is. In practice, script 1 never receives a CIE event, and the delay continues for the 12 hours. No Beuno.</div><div><br></div><div>Second thought was to signal something from script 2 to script 1, but that requires looping in script 1 (polling). No beuno.</div><div><br></div><div>Which by the way, I should mention, I am looking at your solution as a way to avoid looping, though you didn't specifically say that you have figured out a way to avoid looping. I was just being hopeful that somehow your method did avoid looping.</div><div><br></div><div>Like Brian Meade already mentioned, we have solved the "only once an Agent answers" dilemma by using polling in script 1, and setting a flag in script 2 once the agent answers, using Enterprise variables. Polling solves the Agent only hearing the message from the top, versus in the middle, but it doesn't solve the finite script steps issue.</div><div><br></div><div>Therefore, I am wondering how you are handling script 1, post successful place call.</div><div><br></div><div>Don't get me wrong, I'm still #TeamTanner, and will be converting my callback method to yours, since there are some advantages. I just have to solve the script 1 clean up problem first.</div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Wed, Nov 6, 2019 at 4:09 PM Anthony Holloway <<a href="mailto:avholloway%2Bcisco-voip@gmail.com" target="_blank">avholloway+cisco-voip@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr">I actually got that part to work. What I'm wondering about is what you are doing in script 1 (place call script) after the successful branch. Like, are you looping, are you delaying, are just ending?</div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Wed, Nov 6, 2019 at 3:52 PM Tanner Ezell <<a href="mailto:tanner.ezell@gmail.com" target="_blank">tanner.ezell@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr">It's really not all that complicated. Think of it this way, the place call is the contact the agent is exposed to when they answer the queued call, which of course is just the IVR.<div><br></div><div>Pass the generated contact to the agent script (the one that has the select resource), under the connected branch is when you know that your other IVR application contact (from place call), connected to the agent. Use the passed contact and play media just like you would any other contact. In essence, you take the agent menu out of script 1 and put it in script 2 :)</div><div><br></div><div>With all that you can do some cool stuff, like ensuring the agent doesn't just hang up (aka callback resiliency) and what to do if they do (like re-queue, email a supervisor, re-call the agent, etc), can control if the designated callback destination doesn't answer and some other fun stuff.</div><div><br></div><div>happy hacking!</div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Wed, Nov 6, 2019 at 2:20 PM Anthony Holloway <<a href="mailto:avholloway%2Bcisco-voip@gmail.com" target="_blank">avholloway+cisco-voip@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div>Tanner, Can you describe, or show what you're doing in script 1, which has the Place Call step, inside the Successful branch?<br></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Tue, Nov 5, 2019 at 4:30 PM Tanner Ezell <<a href="mailto:tanner.ezell@gmail.com" target="_blank">tanner.ezell@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr">Pssshhht....I'll share a "secret" for playing the agent menu only when the agent answers..<div><br></div><div>Pass the contact to the agent script, then play your agent menu after they connect.</div><div><br></div><div>Ez pz.</div><div><br></div><div>Regards,</div><div>Tanner Ezell</div><div><br></div><div><br></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Tue, Nov 5, 2019 at 2:54 PM Brian Meade <<a href="mailto:bmeade90@vt.edu" target="_blank">bmeade90@vt.edu</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr">Anthony,<div><br></div><div>I'm curious how you handle catching when the agent answers the callback request.</div><div><br></div><div>I've got my scripts checking to see if the CallBack contact was answered by setting some Enterprise Info in my callback queue script but I still have to check every few seconds to see if that Enterprise Info is set.</div><div><br></div><div>I just max out the max steps to account for that.</div><div><br></div><div>Thanks,</div><div>Brian Meade</div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Tue, Nov 5, 2019 at 4:19 PM Anthony Holloway <<a href="mailto:avholloway%2Bcisco-voip@gmail.com" target="_blank">avholloway+cisco-voip@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr">Hi Tim,<div><br></div><div>I think the idea of a flawless script is in the eyes of the beholder.</div><div><br></div><div>I don't personally use the example script from the repo; are you talking about the one here:</div><div><br></div><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><div>script_respository_902\script_respository\release3\BaseLineAdvQueuing\BaseLineAdvQueuing.aef</div></blockquote><div><br></div><div>If so, there a few things wrong with that script.</div><div><br></div><div>For example, you said "...despite having Contact Inactive exception error handling..."</div><div><br></div><div>Yeah, they setup an exception handler at the top for ContactInactiveException, but then they never clear it, or reset it, and so if and when the caller disconnects while recording their message or listening to the "success" prompt, the whole thing falls a part and fails, sending script execution down to the ExceptionCIE label.</div><div><br></div><div>Another thing wrong with it is that the waiting mechanism for the Agent is such that it plays a relatively short prompt, waits 3 seconds for input from the Agent, then repeats.</div><div><br></div><div>If you consider every application has a max 1,000 steps it can execute, and you subtract off the overhead of just getting the call to this point (say 21 steps in the most streamlined of scenarios), that leaves you with 32 minutes to queue a call, otherwise the call will be aborted. Since most people are only interested in callback when they have queue hold time problems, this is likely to cause more issues than it solves.</div><div><br></div><div>"...I’ve read that the Call Control Group and Dialog Group should be different from the trigger on the originating application..."<br></div><div><br></div><div>Can you link the source?</div><div><br></div></div><div dir="ltr"></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Tue, Nov 5, 2019 at 10:59 AM Johnson, Tim <<a href="mailto:johns10t@cmich.edu" target="_blank">johns10t@cmich.edu</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<div lang="EN-US">
<div>
<p class="MsoNormal">Anyone have a callback script that is working flawlessly? We have implemented the solution in Cisco’s Advanced Queueing script and it’s seems to be working, but I’m seeing Contact Inactive Exceptions and Contact Creation errors in syslog
each time the callback is used, despite having Contact Inactive exception error handling.<u></u><u></u></p>
<p class="MsoNormal"><u></u> <u></u></p>
<p class="MsoNormal">It seems that the issue may be related to the Place Call step which calls the trigger of the callback application. I’ve read that the Call Control Group and Dialog Group should be different from the trigger on the originating application
(which is what we have setup), but I’m curious if those should also be different from what’s used on the callback application. If so, can I use the same CCG and DG from the original trigger, on the callback trigger?<u></u><u></u></p>
<p class="MsoNormal"><u></u> <u></u></p>
<p class="MsoNormal">For example, I have the following setup: <u></u><u></u></p>
<p class="MsoNormal">App_A application has a trigger that uses CCG #8 and Dialog Group #0. In its script, it uses the Place Call step with CCG #25 and Dialog Group #3. This places the call to App_Callback application which has a trigger that uses CCG #25 and
Dialog Group #3.<u></u><u></u></p>
<p class="MsoNormal"><u></u> <u></u></p>
<p class="MsoNormal"><span style="font-size:10pt;font-family:Consolas">Tim Johnson<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:10pt;font-family:Consolas">Voice & Video Engineer<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:10pt;font-family:Consolas">Central Michigan University<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:10pt;font-family:Consolas">Phone: <a>
+19897744406@cmich.edu</a><u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:10pt;font-family:Consolas">Fax: +19897795900<u></u><u></u></span></p>
<p class="MsoNormal"><a href="https://cmich.webex.com/meet/johns10t" target="_blank"><span style="font-size:10pt;font-family:Consolas;color:rgb(5,99,193);text-decoration:none"><img border="0" width="157" height="22" style="width: 1.6354in; height: 0.2291in;" id="gmail-m_-8111309163641345854gmail-m_7738977984811839511gmail-m_2909790835117804795gmail-m_-7501282816072899130gmail-m_-4487813699210221302gmail-m_-3372475205002302135gmail-m_5748072738684722703gmail-m_-6955199157880387211gmail-m_-2307887150172359415gmail-m_-1099450097877851445gmail-m_3249623970829652500gmail-m_7324855503632035213gmail-m_6772783291753767223gmail-m_-8154566266809588421gmail-m_-8979221485623659886Picture_x0020_1" alt="webexemailsig"></span></a><u></u><u></u></p>
<p class="MsoNormal"><u></u> <u></u></p>
</div>
</div>
_______________________________________________<br>
cisco-voip mailing list<br>
<a href="mailto:cisco-voip@puck.nether.net" target="_blank">cisco-voip@puck.nether.net</a><br>
<a href="https://puck.nether.net/mailman/listinfo/cisco-voip" rel="noreferrer" target="_blank">https://puck.nether.net/mailman/listinfo/cisco-voip</a><br>
</blockquote></div>
_______________________________________________<br>
cisco-voip mailing list<br>
<a href="mailto:cisco-voip@puck.nether.net" target="_blank">cisco-voip@puck.nether.net</a><br>
<a href="https://puck.nether.net/mailman/listinfo/cisco-voip" rel="noreferrer" target="_blank">https://puck.nether.net/mailman/listinfo/cisco-voip</a><br>
</blockquote></div>
_______________________________________________<br>
cisco-voip mailing list<br>
<a href="mailto:cisco-voip@puck.nether.net" target="_blank">cisco-voip@puck.nether.net</a><br>
<a href="https://puck.nether.net/mailman/listinfo/cisco-voip" rel="noreferrer" target="_blank">https://puck.nether.net/mailman/listinfo/cisco-voip</a><br>
</blockquote></div>
</blockquote></div>
</blockquote></div>
</blockquote></div>
</blockquote></div>
</blockquote></div>
</blockquote></div>
</blockquote></div>
</blockquote></div>
</blockquote></div>
</blockquote></div>