Legacy Dev Forum Posts

 View Only

Sign Up

Subscribe to queue event executing multiple times within seconds

  • 1.  Subscribe to queue event executing multiple times within seconds

    Posted 06-05-2025 19:24

    Magudeeswaran_N | 2023-07-09 11:06:13 UTC | #1

    Hi team,

    I am using subscribe queue event to get an event when call got answered in one of my queue. For that I am using below JavascriptSDK.

    https://developer.genesys.cloud/notificationsalerts/notifications/subscribe-to-queue

    And I do get events like "waiting in queue, alerting, accepted" events. My use case is when agent accepted the interaction I need to call one of the API called send Digit. But the problem is, this alerting event happening very often like within 1 seconds its giving us almost 5 events. So because of this, our send Digit API is getting hit multiple times. IS there any way we can control this event like only give one event at a time.

    becuase of this multiple accepted events within milliseconds, our Send digit API alos excecuting same times. So our callers hearing so many digits.

    Thanks,

    Magu


    Declan_ginty | 2023-07-10 09:32:33 UTC | #2

    Hi Magu,

    Would you be able to send on your code so I can get a better understanding of what is happening.

    Thanks, Declan


    tim.smith | 2023-07-10 13:47:03 UTC | #3

    It's not clear what notification topic you're using, so it's hard to suggest why it's being raised multiple times. However, in general, what you see as duplicate notifications may be completely normal. There is not a constraint internally in Genesys Cloud that notification events be unique or non-repeated. Eventing conditions can occur that will result in the same notification payload being sent for each event so they appear duplicated even though the events that triggered them were unique. If you can provide the notification topic you're using, we may be able to shed some additional light on the situation.

    To resolve this issue, your app should keep track of its state so it can debounce these events. When your app decides to take action for a particular participant in a conversation, it should remember this so it doesn't do it again for the same participant if another event is received.


    Magudeeswaran_N | 2023-07-10 15:41:22 UTC | #4

    Hi tim and Declan,

    Thanks for your responses. I somehow managed to handle the duplicate. But my concern is, if multiple conversation request coming in, I don't think this script can handle it. Because based on how I handled it, if more conversation coming at same time, the variables can conflict each other. If you have better way to handle this please suggest me guys.

    My Javascript code:

    const platformClient = require('purecloud-platform-client-v2');
    var WebSocketClient = require('websocket').client;
    const client = platformClient.ApiClient.instance;
    let apiInstance = new platformClient.UsersApi();
    let apiInstanceForArchitect = new platformClient.ArchitectApi();
    
    
    require('dotenv').config();
    
    // Get client credentials from environment variables
    const CLIENT_ID = process.env.GENESYS_CLOUD_CLIENT_ID;
    const CLIENT_SECRET = process.env.GENESYS_CLOUD_CLIENT_SECRET;
    const ORG_REGION = process.env.GENESYS_CLOUD_REGION; // eg. us_east_1
    
    
    const environment = platformClient.PureCloudRegionHosts[ORG_REGION];
    if (environment) client.setEnvironment(environment);
    
    
    const websocketClient = new WebSocketClient();
    
    // API instances
    const notificationsApi = new platformClient.NotificationsApi();
    
    // Additional configuration variables
    const queueId = 'ab9700bf-c33d-459b-8e36-ef2c31ea26f8';
    const subscriptionTopic = `v2.routing.queues.${queueId}.conversations`;
    
    // Define the callbacks for the websocket listener
    websocketClient.on('connect', connection => {
    	var conversationIdForCheck;
    	var agentTrue = false;
    	console.log('WebSocket client connected and listening...');
    	connection.on('message', message => {
    		let data = JSON.parse(message.utf8Data);
    		let topic = data.topicName;
    		let eventBody = data.eventBody;
    
    		if (topic == subscriptionTopic) {
    			let conversation = eventBody;
    			let customer = conversation.participants
    				.filter(p => p.purpose == 'customer')[0];
    			let agent = conversation.participants
    				.filter(p => p.purpose == 'agent')[0];
    
    			if (agent && agent.connectedTime) {
    				console.log("agentTrue", agentTrue);
    				if (agent && (agentTrue == false) && !agent.endTime) {
    					agentTrue = true;
    					conversationIdForCheck = conversation.id;
    					console.log(`Agent ${agent.userId} has accepted conversation with ${customer.id}`);
                   //getting agent's email using userId. Because I stored Oauth 2 access token in my data table for the specific user. Oauth 2 access token only can be used to send DTMF digits.
    					getUser(agent.userId).then(data => {
    						getAccessToken(data).then(result => {
    							console.log("getAccessToken result", result);
    							sendDTMF(agent.id, conversation.id, result);
    						})
    					})
    				}
    				else if (conversationIdForCheck == conversation.id) {
    					console.log("-------------Same conversation------------");
    				}
    				else if (conversationIdForCheck != conversation.id) {
    					console.log("-------------New conversation------------");
    					agentTrue = false;
    				}
    				else {
    					console.log("-------------Last------------");
    				}
    			}
    			else {
    				console.log("---------Second time-------------");
    			}
    		}
    		// For heartbeats
    		if (topic == 'channel.metadata') {
    			console.log(eventBody.message);
    		}
    	});
    });
    
    async function getUser(agentUserId) {
    
    	var userEmail;
    	let userId = agentUserId; // String | User ID
    	let opts = {
    		"state": "active" // String | Search for a user with this state
    	};
    
    	await apiInstance.getUser(userId, opts)
    		.then((data) => {
    			//console.log(`getUser success! data: ${JSON.stringify(data, null, 2)}`);
    			userEmail = data.email;
    			console.log("email", userEmail);
    
    		})
    		.catch((err) => {
    			console.log("There was a failure calling getUser");
    			console.error(err);
    		});
    
    	return userEmail;
    }
    
    async function getAccessToken(userMail) {
    
    	var user_access_token;
    	console.log("-----------------------Inside token--------------------")
    	let datatableId = "5d9ea952-f03b-4de0-8c72-b17adaf9fa22"; // String | id of datatable
    	let rowId = userMail; // String | The key for the row
    	let opts = {
    		"showbrief": false // Boolean | if true returns just the key field for the row
    	};
    	await apiInstanceForArchitect.getFlowsDatatableRow(datatableId, rowId, opts)
    		.then((data) => {
    			//console.log(`getFlowsDatatableRow success! data: ${JSON.stringify(data, null, 2)}`);
    			user_access_token = data.access_token;
    		})
    		.catch((err) => {
    			console.log("There was a failure calling getFlowsDatatableRow");
    			console.error(err);
    		});
    	// Returns a specific row for the datatable
    
    
    	return user_access_token;
    }
    
    async function sendDTMF(participantId, conversationId, oauthToken) {
    	const platformClientDtmf = require('purecloud-platform-client-v2');
    	const clientDtmf = platformClientDtmf.ApiClient.instance;
    
    	clientDtmf.setEnvironment(platformClientDtmf.PureCloudRegionHosts.us_west_2);
    
    	console.log("OauthToken", oauthToken);
    	clientDtmf.setAccessToken(oauthToken);
    	let apiInstanceConversation = new platformClientDtmf.ConversationsApi();
    
    	let opts = {
    
    		"body": {
    			"digits": "22"
    		}
    
    	};
    	await apiInstanceConversation.postConversationParticipantDigits(conversationId, participantId, opts)
    		.then(() => {
    			console.log("postConversationParticipantDigits returned successfully.");
    		})
    		.catch((err) => {
    			console.log("There was a failure calling postConversationParticipantDigits");
    			console.error(err);
    		});
    
    	// Sends DTMF to the participant
    
    }
    
    
    websocketClient.on('connectFailed', function (error) {
    	console.log('Connect Error: ' + error.toString());
    });
    
    // Set environment
    
    // Log in with Client Credentials
    client.loginClientCredentialsGrant(CLIENT_ID, CLIENT_SECRET)
    	.then((result) => {
    		console.log("result", result);
    		client.setAccessToken(result.accessToken);
    		console.log('Authentication successful');
    
    
    		return notificationsApi.postNotificationsChannels()
    	})
    	.then(data => {
    		console.log('Channel created');
    
    
    		let websocketUri = data.connectUri;
    		let channelId = data.id;
    		websocketClient.connect(websocketUri);
    
    		// Add the subscription for queue events
    		let topic = [{ id: subscriptionTopic }];
    		return notificationsApi.postNotificationsChannelSubscriptions(channelId, topic);
    	})
    	.then(data => {
    		console.log('Subscribed to Queue');
    
    	})
    	.catch(e => console.error(e));
    
    
    // NOTE: This next line is a simple way to make sure the app runs 'forever'
    // In production you'd want the actual code running as a process/service
    setInterval(() => { }, 1 << 30);

    ` `


    tim.smith | 2023-07-10 15:41:01 UTC | #5

    Magudeeswaran_N, post:4, topic:20909
    if multiple conversation request coming in, I don't think this script can handle it.

    Keep track of your actions for the participant ID of the agent. I would suggest managing those IDs in a collection and set a TTL for each item to be removed so the list doesn't grow infinitely as the app runs.

    Magudeeswaran_N, post:4, topic:20909
    .filter(p => p.purpose == 'agent')[0];

    Just a heads up, this is likely to be a bug in your code for conversations that have been handled by multiple agents. You're correct to check purpose in this way, but you should also validate that the segment hasn't ended. To ensure you're handling the right user in a conference, additionally check that the user ID on the segment matches the logged in user's user ID.


    system | 2023-08-10 15:41:26 UTC | #6

    This topic was automatically closed 31 days after the last reply. New replies are no longer allowed.


    This post was migrated from the old Developer Forum.

    ref: 20909