cancel
Showing results for 
Search instead for 
Did you mean: 
cancel
3624
Views
10
Helpful
15
Replies

Global Session

tim.moomaw
Level 1
Level 1

Hello All,

I have quite a few applications that query XML documents for Holidays and to check if a service area is experiencing an outage.  If there is an outage then the outage notification plays until the supervisor calls in and disables it.  Apparently all these XML checks are increasing the HEAP memory within the UCCX environment and I have received the infamous "It is not recommended to update the application as Engine heap memory usage exceeded configured threshold....." warning.

I read Bug CSCtf13713 and the last 'workaround' mentions creating a global session.

I'm assuming the global session/mapping needs to be configured in the calling script?  Can someone shed light on how to use the session mapping, get session, and other scripting objects needed to configure a "global session?"

Also - the bug writeup states that the xml file would be read into memory for 30 minutes and would not time out if contacts continuously called in (it would only be re-read if the object in memory expired after 30 minutes).  Does that mean that if the supervisor disables the outage notification and the application has a high call volume throughout the day that the session mapping would not get updated once the supervisor changes the status?

I've already taken a look at the standard guides on the UCCX support page...getting started with scripts, etc....

UCCX 7.01 SR5

Thanks for any input.

15 Replies 15

Anthony Holloway
Cisco Employee
Cisco Employee

Basically you are taking the first caller of the day, borrowing their session object (which lasts for 30 minutes by default) to hold repo data, and letting other callers read the session variable(s) instead of an XML document out of the repo.

I think TAC is handing out copies of this technique as a workaround.  Maybe a lurking TAC person can confirm.

And yes, since you load the repo data into the session variable(s), and only read from the repo after the session expires, then for a period of 30 minutes, the data will remain unchanged.

The concept is simple, but the implementation is a little more complex.  For every call, you would have to consider the following:

Does anyone have an example (script) that is using the global session for xml data?

Thanks,

Joe

Hi Joe,

Here is the implementation I have created to support a global session object cache.

The script is attached, and written in UCCX 8.5.  For those of you on lower versions, or without CCX Editor installed, I am also including a screen shot for your convenience.

The script documents its usage within the comments section, however I will just recap it here for searchability:

  • This script is meant to be used as a subflow.
  • You pass it the name of the document you wish to read.
  • It will then either pull the document contents from cache or from the repository
  • It will return the contents of your document to you
  • It will also tell you if the contents came from cache or from the repo
  • By default, the contents will remain in cache until a 30 minute period of inactivity
  • You can adjust the timer for session expiration in System Parameters within AppAdmin
  • If you need to immediately refresh the documents in cache, you can change the value of the variable the_session_mapping to some other word; then save and upload the script; then refresh the script; then refresh your applications which reference this subflow.

If you have questions on how this works, please ask.  Good luck and happy caching!

Anthony Holloway

Please use the star ratings to help drive great content to the top of searches.

Anthony, I realize this is an old post, but I do have a question.  Is there any way to keep a global session active?  I understand that the session will timeout after 30 minutes of inactivity, but is there anything I can do to fake activity?  I was considering creating a global session and then triggering an application that updated a timestamp ever 10 minutes or so.  The triggered application would then keep running until either the object goes away or I reset a variable within the session.

Hi Randy,

That sounds like that would work.  How would you trigger the app?  HTTP?  A phone call?

Let's assume two things for a moment:

1) Your desire to keep a sesison alive is only for business hours

2) During business hours, at least one of your many triggers are being accessed every 20 minutes at minimum

With the above setup, you could actually "touch" the session in all of your scripts to keep it alive.  Even script that do not necssarily need to use the Session, they're just helping keep it alive.

Thanks for asking the question.

Anthony Holloway

Please use the star ratings to help drive great content to the top of searches.

Anthony,

Thanks for the reply.  So, here's the use case.  In all of our queueing scripts, we have an exit point that gets checked every time we loop the hold message.  The exit point is meant to break people out of the queue in the rare instance of a situation where agents cannot get logged into CCX (it has happened) and sends them to a hunt group.  The exit point is triggered by a boolean that we would like to store in a session -  we thought it would be better to use something stored in memory so that we didn't cause unneccessary disk IO.

Here's how I hoped it could all work.  We would have an application "A" where we would set the boolean inside of a global session (AKA send out the bat signal).  Application "A" would launch the keepalive application "B" via "trigger application" asynchronously, which would touch the global session ever 20 minutes or so.  Application "B" would keep running until either the bat signal boolean gets turned off again by application "A" or the global session is gone.

Meanwhile the queues that are watching for the bat signal assume that it is off if the global session is not available, or when it is available obey the boolean.

With all of that said...I have never really like that design as it seems a little shaky having to rely on the keepalive.  I have since found your code for the global_session.  I am now going the route of having application "A" write to an XML file, then call your global_session app with a parameter that forces it to refresh from file.  Then all of the queueing apps are calling the global_session app to get the cached data vs. getting it from file.  It's not all quite done yet, but pretty sure it will work great from the testing I've done so far.

Thanks for the global_session code...it works great.

Randy

Hi Randy, it actually sounds like you could get away with a much simpler solution, which also does not use disk I/O.

It is my understanding that all scripts in the repository are loaded into memory when the Engine starts.  This is why it's a bad idea to have a bunch of stale scripts laying around in your repository.  Think version control for three years and how many past versions would be laying around.

Anyway, if I'm right about that, and I think I'll run a test or two to try and prove it, then using the Call Subflow step could substitute the Global Session.

Example:

Say you had a subflow called global_variables.aef and in it you have the following variables:

boolean exit_flag = true

...and the following script steps (spoiler alert: there aren't any):

Start

End

Then say you had 20 or so applications which all need to know if this flag is true or false, well in each of them you would have the following variables:

boolean exit_flag = false

Tthe default false value is important, because if for some reason the subflow cannot be executed properly, you're default action should be (or not) to allow the calls to queue.  That of course is a business decision, just like your "If the global session is not present, we assume the flag is not set" comment.

...and the following script steps (just focusing on what you would add in):

...

exit_flag = Call Subflow (SCRIPT[global_variables.aef], exit_flag)

If (exit_flag)

  True

    /* The global exit flag is set, use alternate routes */

    ...

  False

    /* The global exit flag is no set, use normal routes */

...

When you need to "flag" all script to exit, you simply change the value of the flag in the global_variables.aef script, upload, and refresh, and the rest of the script will pick up the new value.

You could even expand this into other uses like, zero out operator extension, holidays, etc.

You're welcome for the global session script, and I'm glad to hear you got it working.

Take care, and talk to you soon.

Anthony Holloway

Please use the star ratings to help drive great content to the top of searches.

Anthony, wouldn't you then need to also refresh the 20 applications that call the subflow?  If so, this would be too time consuming and defeat the purpose.

There is a "Refresh All" button if that is the case.  And now that you mention it, I have had mixed results with refreshing subflow scripts.  I'll run a few tests and report back.

EDIT:  I ran some tests.

For the below tests I used the following two scripts, change the value within the subflow script variable named i, to a different number each time:

Subflow Script

Variables

int i = 135

Script

Start

End

Calling Script

Variables

int i = 0

Script

Start

Accept (--Triggering Contact--)

i = Call Subflow (SCRIPT[test-subflow.aef], i)

Play Prompt (--Triggering Contact--, dp[1000] + n[i] + dp[1000])

Terminate (--Triggering Contact--)

End

This way I can call the calling script and it will speak the number from the subflow to me, confirming if it picked up the changes or not.

Test Cases

  1. Modifying and saving the changes to the subflow script
    • Changes are not picked up by the calling script (I expected this result, just left it in for completeness)
  2. Modifying and saving the changes to the subflow script, then refreshing the subflow script
    • Changes are not picked up by the calling script (This is the one I wish would have worked)
  3. Modifying and saving the changes to the subflow script, then refreshing the calling script
    • Changes are not picked up by the calling script
  4. Modifying and saving the changes to the subflow script, then refreshing the calling script and the subflow script
    • Changes are not picked up by the calling script (I'm surprised this one didn't work)
  5. Modifying and saving the changes to the subflow script, then refreshing the calling application
    • Changes are picked up by the calling script
  6. Modifying and saving the changes to the subflow script, then refreshing the calling application and the subflow script
    • Changes are picked up by the calling script (no surprise here since it worked in previous test and they overlap, again completeness)

Since #5 is all you need to have the changes picked up, and there is a button to Refresh all scripts, which is non service impacting in and of itself, I see no reason to NOT use the subflow method.  It has less overhead, and it quite simply easier to implement and support.

Anthony Holloway

Please use the star ratings to help drive great content to the top of searches.

Anthony,

Sorry to bring this up after such a long time, but I do have a question concerning your example script.  We use an xml document to restrict specific ext's from being able to be dialed from the AA.  This list has grown to a point that it causing issues with the HEAP.  We are looking @ moving this to a global session, right now we utilize:

The above calls the xml file and parses through it to determine if the number is in the list, if it is, it is plays a prompt that call can't be completed from the AA and transferes the caller to the corporate switchboard.  This UCCX 7.X therefore the file is located in c:\program.files\wavid\ ...should we move the file the repository and present it as the input to the subflow?  From the example above what would be output of the sublow, crcblocknum? 

Thanks inadvance,

Joe

I would suggest maybe stepping away from an XML document, but if you must, then yes, move it to the repository where it will be backed up with BARS/DRS and also replicated if you have HA.  Also, move away from looping the entire document as well.  You may need to restructure your XML document though.

Here's an example of not looping the XML document looking for a record:

XML

  true

  true

  true

Variables

String caller_input = "1005"

Script

xpath_result = Get XML Document Data (xml_doc, "//number[@value='" + caller_input + "']")

If (xpath_result != null && xpath_result.trim() != "")

  True

    /* Caller entered an invalid number */

  False

    /* Caller entered a valid number */

If you wanted to explore a non-XML option, see this example:

Variables

String[] invalid_numbers = new String[] {"1000", "1005", "1017"}

String caller_input = "1005"

Script

If (Arrays.asList(invalid_numbers).contains(caller_input))

  True

    /* Caller entered an invalid number */

  False

    /* Caller entered a valid number */

Anthony Holloway

Please use the star ratings to help drive great content to the top of searches.

Anthony,

I like the non-XML option, I doing something similar with an array for dates and Holidays.  Is there a limit to the length of othe array?  I would assume we could create a sub flow script that checks if the string caller_input is in  the array and returns back if true or false, the parent script would then allow or disallow the call.  We have several scripts that utilize the xml file as it is now and would like to have one spot that would need to be edited for all scripts.  Will the sub flow work the same?

EDIT:

When I attempt to create the If statement in the editor I get an Unable to Parse.

I have attached a screenshot.

Thanks,

Joe

My apologies.  UCCX makes you spell out the name space.

Try it this way:

java.util.Arrays(...)

Anthony Holloway

Please use the star ratings to help drive great content to the top of searches.

joeharb wrote:

Is there a limit to the length of othe array?

Not one that's imposed on you.  Of course, nothing is limitless.

joeharb wrote:

I would assume we could create a sub flow script that checks if the string caller_input is in  the array and returns back if true or false, the parent script would then allow or disallow the call.  We have several scripts that utilize the xml file as it is now and would like to have one spot that would need to be edited for all scripts.  Will the sub flow work the same?

Yes it would, but keep in mind that an update to the subflow requires a refresh of any app which references it.  Whereas, an update to an XML document does not.  It's a six of one, a half dozen of the other type of thing.

Anthony Holloway

Please use the star ratings to help drive great content to the top of searches.

Getting Started

Find answers to your questions by entering keywords or phrases in the Search bar above. New here? Use these resources to familiarize yourself with the community: