Finesse Container Timer

Because too many timers that run concurrently can cause issues for JavaScript, you should not use setTimeout() or setInterval() directly. The Finesse container provides a service (the TimerTickEvent) that you can leverage for your third-party gadgets.

Finesse publishes the TimerTickEvent to the OpenAJAX hub every 1000 milliseconds. To use this service:

  • Have the gadget subscribe to the TimerTickEvent:

    Code Snippet
    Copyfinesse.containerservices.ContainerServices.addHandler(finesse.containerservices.ContainerServices.Topics.
    TIMER_TICK_EVENT, callback);
    
  • Define a callback method (see boilerplate gadget tick code - _timerTickHandler()) and, optionally, an update method (see boilerplate gadget tick code - _processTick()).

Cisco provides a boilerplate gadget tick code that you can use to define the callback method.

Boilerplate gadget tick code:

Code Snippet
Copy//Gadget defined field: _lastProcessedTimerTick
_lastProcessedTimerTick = null,
 
//Gadget defined field: _maxTimerCallbackThreshold
_maxTimerCallbackThreshold = 500,
 
//Gadget defined field: _forceTickProcessingEvery (10 seconds)
_forceTickProcessingEvery = 10000,
 
/**
  * Processes a timer tick - updating the UI.
  * @param start is the time that the tick was received
  * @returns {boolean} true
  */
_processTick = function (start) {
 
   //Developer's add UI update logic here
   //...
   //...
 
   _lastProcessedTimerTick = start;
 
  return true;
},
 
/**
  * Timer tick callback handler.
  * @param data
  */
_timerTickHandler  = function (timerTickEvent) {
   var start, end, diff, discardThreshold, processed;
 
  start = (new Date()).getTime();
  processed = false;
 
  //Prevent starvation of timer logic
  if (_lastProcessedTimerTick === null) {
     processed = _processTick(start);
  } else {
     if ((_lastProcessedTimerTick + _forceTickProcessingEvery) <= start) {
       //Force processing at least every _forceTickProcessingEvery milliseconds
       processed = _processTick(start);
     }
 
  end = (new Date()).getTime();
  diff = end - start;
  if (diff > _maxTimerCallbackThreshold) {
    _clientLogs.log("GadgetXYZ took too long to process timer tick (_maxTimerCallbackThreshold exceeded).");
  }
},

If you choose not to use the boilerplate gadget tick code, you should ensure the following:

  • Callback calculates entry and exit time.

  • Callback for timer tick is quick (log when callback takes to long - only when exceeding threshold).

  • Callback provides discard capability (as outlined in the boilerplate gadget tick code) to prevent events from piling up.

  • Callback adds a _lastProcessedTimerTick and uses it to force an update to occur at regular intervals (such as every 10 seconds). The intent is to prevent starvation in a heavily-loaded system that cannot respond quickly enough, such that all events are being discarded.

Note

Because the timer callback triggers every 1 second and the JavaScript engine is single-threaded, it is important to process as quickly as possible. Using the boilerplate code makes gadget development issues more obvious and easier to debug.