/// <summary> /// Removes a pending request for an Agent match from the queue /// </summary> private bool RemoveFromQueue(PendingAgentMatchRequestQueueItem queueItem) { if (null != queueItem) { lock (_syncRoot) { if (_matchMakerState != MatchMakerState.Terminating && _matchMakerState != MatchMakerState.Terminated) { // if not terminating, process the queue removal else this will be // done by the shutdown operation. return(_pendingAgentRequestQueueItems.Remove(queueItem)); } } } return(false); }
internal void Process() { Agent agent = null; // Try to find a match synchronously agent = MatchAndAllocate(); if (agent != null) { // Completes the operation synchronously this.SetAsCompleted(agent, false); } else { //Add the agent match request to the list of pending requests and start a timer lock (_matchMaker._syncRoot) { if (_matchMaker._matchMakerState < MatchMakerState.Terminating) { // Using the match maker timer wheel to trigger the operation time out. TimerItem timerItem = new TimerItem(_matchMaker._timerWheel, new TimeSpan(0, 0, 0, _matchMaker._configuration.MaxWaitTimeOut, 0)); timerItem.Expired += new EventHandler(HandlePendingRequestTimeOut); timerItem.Start(); //create a queue item and cache a reference _queueItem = new PendingAgentMatchRequestQueueItem(_requestor, this, timerItem); //add the queueItem to the queue _matchMaker._pendingAgentRequestQueueItems.Add(_queueItem); return; } } this.SetAsCompleted(new OperationFailureException("AcdAgentMatchMaker is terminating and cannot process any new async requests"), false); } }
/// <summary> /// Determines whether an agent who becomes available has the correct skillset to be connected /// to a customer who is waiting. If it does, the agent is allocated. /// </summary> internal void HandleNewAvailableAgent(Agent agent) { PendingAgentMatchRequestQueueItem pendingRequestToBeRemoved = null; lock (_syncRoot) { foreach (PendingAgentMatchRequestQueueItem pendingRequestQueueItem in _pendingAgentRequestQueueItems) { // Retrieve the associated asyncResult from the item in the queue FindAgentAsyncResult asyncResult = pendingRequestQueueItem.FindAgentAsyncResult; if (null == asyncResult) { continue; } //Check if the agent is a match for the current pending request if (asyncResult.IsAgentMatch(agent)) { //It is a match, allocate the Agent _logger.Log("Allocating Agent " + agent.SignInAddress); try { //It is a match, allocate the Agent agent.Allocate(pendingRequestQueueItem._Requestor); _logger.Log("Agent " + agent.SignInAddress + " is allocated to :" + agent.Owner.ToString()); } catch (InvalidOperationException ex) { //this is a race condition where an agent got allocated while the pending // request was still in the queue _logger.Log("AcdAgentMatchMaker failed allocation of Agent " + agent.SignInAddress, ex); return; } // if we allocate the agent, we need to remove the pending request from the queue pendingRequestToBeRemoved = pendingRequestQueueItem; //Stop the timer TimerItem tmrItem = pendingRequestQueueItem._TmrItem; if (null != tmrItem) { tmrItem.Stop(); } break; } } //Attempt to remove the pending operation from the queue //If it fails removing the pending request, the match maker is probably in terminating state //in which case, shut down will take care of the clean up. if (null != pendingRequestToBeRemoved) { //let's remove the pend operation first to ensure that the async result does not //get executed twice in a row. this.RemoveFromQueue(pendingRequestToBeRemoved); //Complete the async operation with success pendingRequestToBeRemoved.FindAgentAsyncResult.SetAsCompleted(agent, false); } } }