/// <summary> /// Attempts to find an agent available to serve a customer. The operation may time out if no agent /// is available within a configurable max duration. /// </summary> internal IAsyncResult BeginFindAgent(AcdCustomerSession owner, List <Agent> exclusionList, List <AgentSkill> requestedSkills, AsyncCallback callback, object state) { var result = new FindAgentAsyncResult(callback, state, owner, this, exclusionList, requestedSkills); ThreadPool.QueueUserWorkItem((waitState) => { var tempAr = waitState as FindAgentAsyncResult; tempAr.Process(); }, result); return(result); }
private void CleanupPendingRequests() { lock (_syncRoot) { //flush the queue of pending requests foreach (PendingAgentMatchRequestQueueItem queueItem in _pendingAgentRequestQueueItems) { queueItem.StopTimer(); FindAgentAsyncResult asyncResult = queueItem.FindAgentAsyncResult; if (null != asyncResult) { //Complete the async operation with failure asyncResult.SetAsCompleted(new OperationFailureException("Acd Agent Match Maker is shutting down"), false); } } } }
internal PendingAgentMatchRequestQueueItem(AcdCustomerSession requestor, FindAgentAsyncResult findAgentAsyncResult, TimerItem tmrItem) { _Requestor = requestor; this.FindAgentAsyncResult = findAgentAsyncResult; _TmrItem = tmrItem; }
/// <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); } } }
/// <summary> /// Completes the FindAgent Operation. /// </summary> internal Agent EndFindAgent(IAsyncResult result) { FindAgentAsyncResult asyncResult = result as FindAgentAsyncResult; return(asyncResult.EndInvoke()); }