Name

global.AWAQueueTimeoutUtility

Description

No description available

Script

var AWAQueueTimeoutUtility = Class.create();
AWAQueueTimeoutUtility.prototype = {

  initialize: function() {
  	this.logger = new GlideChatbotLoggerSetupUtil("com.glide.interaction.awa").setup();
  },

  _getFlowRecord: function(flowId) {
  	if (!flowId) {
  		return null;
  	}
  	var flowGr = new GlideRecord('sys_hub_flow');
  	flowGr.addActiveQuery();
  	flowGr.addQuery('sys_id', flowId);
  	flowGr.query();
  	if (flowGr.next()) {
  		return flowGr;
  	}
  },

  _getFlowInternalNameWithScope: function(flowRecord) {
  	var scopeGr = new GlideRecord('sys_scope');
  	scopeGr.addActiveQuery();
  	scopeGr.addQuery('sys_id', flowRecord.getValue('sys_scope'));
  	scopeGr.query();
  	if (scopeGr.next()) {
  		return scopeGr.getValue('scope') + '.' + flowRecord.getValue('internal_name');
  	}
  },

  _invokeFlow: function(flowType, flowNameWithScope, inputs) {
  	if (!flowType || !flowNameWithScope) {
  		return;
  	}
  	try {
  		switch(flowType) {
  			case 'flow':
  				sn_fd.FlowAPI.getRunner()
  					.flow(flowNameWithScope)
  					.inBackground()
  					.run();
  				break;
  			case 'subflow':
  				sn_fd.FlowAPI.getRunner()
  					.subflow(flowNameWithScope)
  					.inBackground()
  					.withInputs(inputs)
  					.run();
  				break;
  		}
  	} catch (err) {
  		this.logger.error("Triggering flow/subflow by queue trigger failed: {0}", err);
  	}
  },

  _getWaitTimeTriggers: function() {
  	var gr = new GlideRecord('awa_queue_trigger');
  	gr.addActiveQuery();
  	gr.addQuery('trigger_type', 'wait');
  	gr.addQuery('trigger_time', '>', new GlideDuration(0));
  	gr.orderBy('trigger_time');
  	gr.query();
  	return gr;
  },

  triggerWaitTimeMessages: function() {
  	var triggerGr = this._getWaitTimeTriggers();
  	var triggersProcessed = 0;

  	while (triggerGr.next()) {
  		var triggerTime = new GlideDateTime(triggerGr.getValue('trigger_time')).getNumericValue();
  		var currentTime = new GlideDateTime().getNumericValue();
  		var message = triggerGr.getValue('trigger_message');

  		var workItemGr = new GlideRecord('awa_work_item');
  		workItemGr.addActiveQuery();
  		workItemGr.addQuery('document_table', 'interaction');
  		workItemGr.addQuery('state', 'IN', 'queued,pending_accept');
  		workItemGr.addQuery('queue', triggerGr.getValue('queue'));
  		workItemGr.addQuery('wait_message_triggered_count', '<=', triggersProcessed.toString());
  		workItemGr.addQuery('sys_created_on', '<=', new GlideDuration(currentTime - triggerTime));
  		workItemGr.query();
  		triggersProcessed++;

  		var flowId, flowRecord, flowNameWithScope, flowType;
  		flowId = triggerGr.getValue('trigger_flow');
  		flowRecord = this._getFlowRecord(flowId);
  		if (flowRecord) {
  			flowNameWithScope = this._getFlowInternalNameWithScope(flowRecord);
  			flowType = flowRecord.getValue('type');
  		}

  		while (workItemGr.next()) {
  			workItemGr.setValue('wait_message_triggered_count', triggersProcessed.toString());
  			workItemGr.update();

  			var interactionGr = new GlideRecord('interaction');
  			interactionGr.get(workItemGr.document_id);
  			interactionGr.next();

  			var conversationId = interactionGr.channel_metadata_document;
  			var conversation = sn_connect.Conversation.get(
  				conversationId,
  				interactionGr.channel_metadata_table
  			);
  			conversation.sendMessage({
  				body: message,
  				system: true
  			});

  			var flowInputs = {};
  			flowInputs['conversation_id'] = conversationId;
  			this._invokeFlow(flowType, flowNameWithScope, flowInputs);
  		}
  	}
  },

  _getQueuesWithMaxWaitTime: function() {
      var gr = new GlideRecord('awa_queue');
      gr.addEncodedQuery("service_channel.typeINchat,messaging,phone,video");
      gr.addActiveQuery();
      gr.addQuery('max_wait_time', '>', new GlideDuration(0));
      gr.query();
      return gr;
  },

  _getMaxWaitTimeTriggers: function(queueID) {
  	var gr = new GlideRecord('awa_queue_trigger');
  	gr.addActiveQuery();
  	gr.addQuery('queue', queueID);
  	gr.addQuery('trigger_type', 'max_wait');
  	gr.query();
  	return gr;
  },

  _switchToMaxWaitTopic: function(interactionGr, maxWaitMessage) {
  	interactionGr.setValue('agent_chat', 'false');  // this prevents the interaction from being close by a br
  	interactionGr.update();

  	// Send the max wait time message
  	var conversationId = interactionGr.channel_metadata_document;
  	var conversation = sn_connect.Conversation.get(
  		conversationId,
  		interactionGr.channel_metadata_table
  	);
  	conversation.sendMessage({
  		body: maxWaitMessage,
  		system: true
  	});

  	// Switch into the max wait topic
  	var result = sn_cs.VASystemObject.switchTopicAtMaxWaitTime(conversationId);
  	return result;
  },

  timeoutWorkItems: function() {
      var queueGr = this._getQueuesWithMaxWaitTime();
      while (queueGr.next()) {
          var maxWaitTime = new GlideDateTime(queueGr.getValue('max_wait_time')).getNumericValue();
  		var maxWaitMessage = queueGr.getValue('max_wait_time_message');
          var currentTime = new GlideDateTime().getNumericValue();
  		var triggerGr = this._getMaxWaitTimeTriggers(queueGr.getValue('sys_id'));
  		var flowId, flowRecord, flowNameWithScope, flowType;
  		var hasMaxWaitTopic = false;

  		// get trigger topic and flow
  		if (triggerGr.next()) {
  			hasMaxWaitTopic = triggerGr.getValue('trigger_topic') != null;
  			flowId = triggerGr.getValue('trigger_flow');
  		}
  		flowRecord = this._getFlowRecord(flowId);
  		if (flowRecord) {
  			flowNameWithScope = this._getFlowInternalNameWithScope(flowRecord);
  			flowType = flowRecord.getValue('type');
  		}

          var workItemGr = new GlideRecord('awa_work_item');
          workItemGr.addActiveQuery();
          workItemGr.addQuery('document_table', 'interaction');
          workItemGr.addQuery('state', 'IN', 'queued,pending_accept');
          workItemGr.addQuery('queue', queueGr.getUniqueValue());
          workItemGr.addQuery('sys_created_on', '<=', new GlideDuration(currentTime - maxWaitTime));
          workItemGr.query();
          while (workItemGr.next()) {
  			var interactionGr = new GlideRecord('interaction');
  			interactionGr.get(workItemGr.document_id);

  			// Switch to max wait topic if configured
  			if (hasMaxWaitTopic) {
  				this._switchToMaxWaitTopic(interactionGr, maxWaitMessage);
  			}

  			// Cancel the work item
  			workItemGr.setValue('state', 'cancelled');
  			workItemGr.setValue('cancelled_reason', 'timeout');
  			workItemGr.update();

  			// invoke max wait flow
  			var flowInputs = {};
  			flowInputs['conversation_id'] = interactionGr.channel_metadata_document;
  			this._invokeFlow(flowType, flowNameWithScope, flowInputs);
          }
      }
  },
  type: 'AWAQueueTimeoutUtility'
};

Sys ID

5a336cfab3203300fcfb6e5f26a8dc06

Offical Documentation

Official Docs: