private bool ParseCallbackSettingsXML() { Trace.TraceInformation("Enter."); try { if (xmlDoc == null) { Trace.TraceWarning("xmlDoc is null."); return(false); } System.Xml.XmlNodeReader reader = new System.Xml.XmlNodeReader(xmlDoc); List <CallbackContactServiceQueue> _TempQueues = new List <CallbackContactServiceQueue>(); CallbackContactServiceQueue _cbCSQ = null; CallbackContactServiceQueueSettingsProfile _profile = null; CallbackBackupCSQ _bckCSQ = null; CallbackAlgorithmFilter _filter = null; bool bAcceptCallbacksTimeframeElementEnded = true; bool bCallbackProcessingTimeframeEnded = true; bool bCallbackReentryAlgorithmElementBegan = false; bool bCallbackOfferedAlgorithmElementBegan = false; while (reader.Read()) { switch (reader.NodeType) { case System.Xml.XmlNodeType.Element: if (reader.Name.Equals("csq")) { _cbCSQ = new CallbackContactServiceQueue(); _cbCSQ.Name = reader.GetAttribute("name"); bCallbackReentryAlgorithmElementBegan = false; bCallbackOfferedAlgorithmElementBegan = false; } if (reader.Name.Equals("CallbackEnabled")) { try { _cbCSQ.CallbackEnabled = bool.Parse(reader.ReadString()); } catch { _cbCSQ.CallbackEnabled = false; } } if (reader.Name.Equals("CallerRecording")) { if (_profile == null) { _profile = new CallbackContactServiceQueueSettingsProfile(); } try { _profile.CallerRecording = bool.Parse(reader.ReadString()); } catch { _profile.CallerRecording = false; } } if (reader.Name.Equals("RetentionPeriod")) { if (_profile == null) { _profile = new CallbackContactServiceQueueSettingsProfile(); } try { _profile.RetentionPeriod = int.Parse(reader.ReadString()); } catch { _profile.RetentionPeriod = 7; } } if (reader.Name.Equals("AppServerURLPrefix")) { if (_profile == null) { _profile = new CallbackContactServiceQueueSettingsProfile(); } _profile.AppServerURLPrefix = reader.ReadString(); } if (reader.Name.Equals("EmailAlerts")) { if (_profile == null) { _profile = new CallbackContactServiceQueueSettingsProfile(); } try { _profile.EmailAlerts = bool.Parse(reader.ReadString()); } catch { _profile.EmailAlerts = false; } } if (reader.Name.Equals("AdminEmail")) { if (_profile == null) { _profile = new CallbackContactServiceQueueSettingsProfile(); } _profile.AdminEmail = reader.ReadString(); } if (reader.Name.Equals("CallerIDVerify")) { if (_profile == null) { _profile = new CallbackContactServiceQueueSettingsProfile(); } try { _profile.CallerIDVerify = bool.Parse(reader.ReadString()); } catch { _profile.CallerIDVerify = false; } } if (reader.Name.Equals("AbandonCallback")) { if (_profile == null) { _profile = new CallbackContactServiceQueueSettingsProfile(); } try { _profile.AbandonCallback = bool.Parse(reader.ReadString()); } catch { _profile.AbandonCallback = false; } } if (reader.Name.Equals("AbandonCBMinQTime")) { if (_profile == null) { _profile = new CallbackContactServiceQueueSettingsProfile(); } try { _profile.AbandonCBMinQTime = int.Parse(reader.ReadString()); } catch { _profile.AbandonCBMinQTime = 0; } } if (reader.Name.Equals("AbandonCBMinInterCallTime")) { if (_profile == null) { _profile = new CallbackContactServiceQueueSettingsProfile(); } try { _profile.AbandonCBMinInterCallTime = int.Parse(reader.ReadString()); } catch { _profile.AbandonCBMinInterCallTime = 0; } } if (reader.Name.Equals("CBQueue")) { if (_profile == null) { _profile = new CallbackContactServiceQueueSettingsProfile(); } _bckCSQ = new CallbackBackupCSQ(); _bckCSQ.Name = reader.GetAttribute("csq"); try { _bckCSQ.OverflowTime = int.Parse(reader.GetAttribute("overflowtime")); } catch { _bckCSQ.OverflowTime = 0; } _profile.BackupCSQs.Add(_bckCSQ); _bckCSQ = null; } if (reader.Name.Equals("AcceptCallbacksTimeframe")) { if (_profile == null) { _profile = new CallbackContactServiceQueueSettingsProfile(); } bAcceptCallbacksTimeframeElementEnded = false; } if (reader.Name.Equals("Begin")) { if (!bAcceptCallbacksTimeframeElementEnded) { _profile.AcceptCallbacksTimeframeBegin = reader.ReadString(); } if (!bCallbackProcessingTimeframeEnded) { _profile.CallbackProcessingTimeframeBegin = reader.ReadString(); } } if (reader.Name.Equals("End")) { if (!bAcceptCallbacksTimeframeElementEnded) { _profile.AcceptCallbacksTimeframeEnd = reader.ReadString(); } if (!bCallbackProcessingTimeframeEnded) { _profile.CallbackProcessingTimeframeEnd = reader.ReadString(); } } if (reader.Name.Equals("CallbackOfferedAlgorithm")) { bCallbackOfferedAlgorithmElementBegan = true; } if (reader.Name.Equals("CallbackReentryAlgorithm")) { bCallbackReentryAlgorithmElementBegan = true; } if (reader.Name.Equals("TotalInQueue") || reader.Name.Equals("CSQAgentsReady") || reader.Name.Equals("CSQCallsWaiting") || reader.Name.Equals("AgentsLoggedIn") || reader.Name.Equals("CallsWaiting") || reader.Name.Equals("LongestQueueTime") || reader.Name.Equals("CallbackRequests")) { if (_profile == null) { _profile = new CallbackContactServiceQueueSettingsProfile(); } _filter = new CallbackAlgorithmFilter(); _filter.Name = reader.Name; try { _filter.Enabled = bool.Parse(reader.GetAttribute("Enabled")); } catch { _filter.Enabled = false; } _filter.Operation = reader.GetAttribute("Operation"); try { _filter.Value = int.Parse(reader.GetAttribute("Value")); } catch { _filter.Value = 0; } if (bCallbackOfferedAlgorithmElementBegan) { _profile.OfferedAlgorithmFilters.Add(_filter); } if (bCallbackReentryAlgorithmElementBegan) { _profile.ReentryAlgorithmFilters.Add(_filter); } _filter = null; } if (reader.Name.Equals("CallbackProcessingTimeframe")) { if (_profile == null) { _profile = new CallbackContactServiceQueueSettingsProfile(); } bCallbackProcessingTimeframeEnded = false; } if (reader.Name.Equals("EndOfDayPurgeCallbackRequests")) { if (_profile == null) { _profile = new CallbackContactServiceQueueSettingsProfile(); } try { _profile.EndOfDayPurgeCallbackRequests = bool.Parse(reader.ReadString()); } catch { _profile.EndOfDayPurgeCallbackRequests = false; } } break; case System.Xml.XmlNodeType.EndElement: if (reader.Name.Equals("csq")) { if (_cbCSQ != null) { _cbCSQ.Profile = _profile; _TempQueues.Add(_cbCSQ); } else { Trace.TraceWarning("CSQ was not added to list because _cbCSQ is null."); } _profile = null; _cbCSQ = null; } if (reader.Name.Equals("CallbackReentryAlgorithm")) { bCallbackReentryAlgorithmElementBegan = false; } if (reader.Name.Equals("AcceptCallbacksTimeframe")) { bAcceptCallbacksTimeframeElementEnded = true; } if (reader.Name.Equals("CallbackOfferedAlgorithm")) { bCallbackOfferedAlgorithmElementBegan = false; } if (reader.Name.Equals("CallbackProcessingTimeframe")) { bCallbackProcessingTimeframeEnded = true; } break; } //switch (reader.NodeType) } //while (reader.Read()) reader.Close(); reader = null; xmlDoc = null; _Queues = _TempQueues; _TempQueues = null; _profile = null; _cbCSQ = null; return(true); } catch (Exception ex) { Trace.TraceError("Exception:" + ex.Message + Environment.NewLine + "StackTrace:" + ex.StackTrace); xmlDoc = null; return(false); } }
public bool Analyse(ContactServiceQueueInformation Information, CallbackContactServiceQueueSettingsProfile Profile, CallbackRecordManager RecordManager) { Trace.TraceInformation("Enter."); try { if (Information == null) { _Description = "Information is null."; Trace.TraceWarning("Information is null."); return(false); } if (Profile == null) { _Description = "Profile is null."; Trace.TraceWarning("Profile is null."); return(false); } if (RecordManager == null) { _Description = "RecordManager is null."; Trace.TraceWarning("RecordManager is null."); return(false); } bool bResult = true; foreach (CallbackAlgorithmFilter filter in Profile.OfferedAlgorithmFilters) { if (filter.Enabled) { try { Constants.FilterOperations Operation = Constants.FilterOperations.BIGGERTHANOREQUALTO; Operation = (Constants.FilterOperations)Enum.Parse(typeof(Constants.FilterOperations), filter.Operation.ToUpper()); switch (filter.Name) { case "AgentsLoggedIn": switch (Operation) { case Constants.FilterOperations.BIGGERTHANOREQUALTO: if (Information.AgentsLoggedIn >= filter.Value) { bResult = bResult && true; } else { _Description = "CSQ " + Information.Name + " has less than " + filter.Value + " agents logged in."; bResult = bResult && false; } break; case Constants.FilterOperations.SMALLERTHANOREQUALTO: if (Information.AgentsLoggedIn <= filter.Value) { bResult = bResult && true; } else { _Description = "CSQ " + Information.Name + " has more than " + filter.Value + " agents logged in."; bResult = bResult && false; } break; } break; case "CallsWaiting": switch (Operation) { case Constants.FilterOperations.BIGGERTHANOREQUALTO: if (Information.ContactsWaiting >= filter.Value) { bResult = bResult && true; } else { _Description = "CSQ " + Information.Name + " has less than " + filter.Value + " calls waiting."; bResult = bResult && false; } break; case Constants.FilterOperations.SMALLERTHANOREQUALTO: if (Information.ContactsWaiting <= filter.Value) { bResult = bResult && true; } else { _Description = "CSQ " + Information.Name + " has more than " + filter.Value + " calls waiting."; bResult = bResult && false; } break; } break; case "LongestQueueTime": switch (Operation) { case Constants.FilterOperations.BIGGERTHANOREQUALTO: if (Information.LongestWaitingContact >= filter.Value) { bResult = bResult && true; } else { _Description = "CSQ " + Information.Name + " has longest queue time less than " + filter.Value; bResult = bResult && false; } break; case Constants.FilterOperations.SMALLERTHANOREQUALTO: if (Information.LongestWaitingContact <= filter.Value) { bResult = bResult && true; } else { _Description = "CSQ " + Information.Name + " has longest queue time more than " + filter.Value; bResult = bResult && false; } break; } break; case "CallbackRequests": switch (Operation) { case Constants.FilterOperations.BIGGERTHANOREQUALTO: if (RecordManager.NumberOfRecordsForQueue(Information.Name) >= filter.Value) { bResult = bResult && true; } else { _Description = "CSQ " + Information.Name + " has fewer than " + filter.Value + " callback requests."; bResult = bResult && false; } break; case Constants.FilterOperations.SMALLERTHANOREQUALTO: if (RecordManager.NumberOfRecordsForQueue(Information.Name) <= filter.Value) { bResult = bResult && true; } else { _Description = "CSQ " + Information.Name + " has more than " + filter.Value + " callback requests:" + RecordManager.NumberOfRecordsForQueue(Information.Name); bResult = bResult && false; } break; } break; default: break; } } catch (Exception ex) { _Description = "Exception performing algorithm comparisons."; Trace.TraceWarning("Exception: " + ex.Message + Environment.NewLine + "Stacktrace: " + ex.StackTrace); bResult = false; } } } return(bResult); } catch (Exception ex) { _Description = "Exception running callback offer algorithm."; Trace.TraceWarning("Exception: " + ex.Message + Environment.NewLine + "Stacktrace: " + ex.StackTrace); return(false); } }
public CallbackContactServiceQueue() { _CallbackEnabled = false; _Name = String.Empty; _Profile = null; }
void _tmrTick_Tick(object State) { Trace.TraceInformation("Enter."); lock (objLock) { _tmrTick.Change(System.Threading.Timeout.Infinite, System.Threading.Timeout.Infinite); DateTime dtBegin = DateTime.Now; if (_settingsManager == null) { Trace.TraceWarning("_settingsManager is null."); _tmrTick.Change(TICKINTERVAL, TICKINTERVAL); return; } if (_settingsManager.ApplicationSettings == null) { Trace.TraceWarning("_settingsManager.ApplicationSettings is null."); _tmrTick.Change(TICKINTERVAL, TICKINTERVAL); return; } if (_settingsManager.CallbackSettings == null) { Trace.TraceWarning("_settingsManager.CallbackSettings is null."); _tmrTick.Change(TICKINTERVAL, TICKINTERVAL); return; } if (!_settingsManager.UCCXMasterNodeDetected) { Trace.TraceWarning("_settingsManager.UCCXMasterNodeDetected is false; no UCCX Master Node has been detected."); _tmrTick.Change(TICKINTERVAL, TICKINTERVAL); return; } if (_recordManager == null) { Trace.TraceWarning("_recordManager is null."); _tmrTick.Change(TICKINTERVAL, TICKINTERVAL); return; } if (_recordManager.GetRecordCount() == 0) { _tmrTick.Change(TICKINTERVAL, TICKINTERVAL); return; } try { //Task #1: Detect day boundary crossing, check end of day purge and flag records DateTime _CurrentTick = DateTime.Now; bool _DayBoundaryCrossed = false; if (!(_CurrentTick.Year == _LastTick.Year && _CurrentTick.Month == _LastTick.Month && _CurrentTick.Day == _LastTick.Day)) { Trace.TraceInformation("Day bounderay was crossed."); _DayBoundaryCrossed = true; } _LastTick = _CurrentTick; foreach (CallbackRecord record in _recordManager.Records) { String sCSQ = record.TargetCSQ; CallbackContactServiceQueue _queue = null; foreach (CallbackContactServiceQueue queue in _settingsManager.CallbackSettings.Queues) { if (sCSQ == queue.Name) { _queue = queue; break; } }//foreach (CallbackContactServiceQueue queue in _settingsManager.CallbackSettings.Queues) if (_queue != null) { CallbackContactServiceQueueSettingsProfile _Profile = null; if (_queue.Profile == null) { foreach (CallbackContactServiceQueue queue in _settingsManager.CallbackSettings.Queues) { if (queue.Name == "Default") { _Profile = queue.Profile; break; } }//foreach (CallbackContactServiceQueue queue in _settingsManager.CallbackSettings.Queues) } else { _Profile = _queue.Profile; } if (_Profile != null) { if (_DayBoundaryCrossed) { record.CallbackProcessingTimeframeEndCrossed = false; Trace.TraceInformation("CallbackProcessingTimeframeEndCrossed set to false for record " + record.ID); } else { //Trace.TraceInformation("CallbackProcessingTimeframeEndCrossed was not set for record " + record.ID); } DateTime dtCallbackProcessingTimeframeEnd = DateTime.ParseExact(_Profile.CallbackProcessingTimeframeEnd, "HH:mm:ss", System.Globalization.CultureInfo.InvariantCulture); if (!record.CallbackProcessingTimeframeEndCrossed) { //Trace.TraceInformation("CallbackProcessingTimeframeEndCrossed is false for record " + record.ID); if (DateTime.Now.Subtract(dtCallbackProcessingTimeframeEnd).TotalMilliseconds >= 0) { Trace.TraceInformation("Now is after dtCallbackProcessingTimeframeEnd for record " + record.ID); record.CallbackProcessingTimeframeEndCrossed = true; record.ReportOn = true; //Check record age; mark purge if older than maximum number of days if (DateTime.Now.Subtract(record.RequestDate).TotalDays > _settingsManager.ApplicationSettings.MaximumNumberOfDays) { record.Purge = true; record.PurgeDueToAge = true; Trace.TraceInformation("Record " + record.ID + " is " + record.Status + " and was marked for end of day purging due to record age."); } if (record.Status == Constants.RecordStatus.INVALID || record.Status == Constants.RecordStatus.INACTIVE || record.Status == Constants.RecordStatus.EXCEEDEDNUMBEROFATTEMPTS || record.Status == Constants.RecordStatus.COMPLETED) { record.Purge = true; Trace.TraceInformation("Record " + record.ID + " is " + record.Status + " and was marked for end of day purging due to status"); } if (record.Status == Constants.RecordStatus.NEW || record.Status == Constants.RecordStatus.RETRY || record.Status == Constants.RecordStatus.FORCERETRY) { if (_Profile.EndOfDayPurgeCallbackRequests) { record.Purge = true; Trace.TraceInformation("Record " + record.ID + " is " + record.Status + " and was marked for end of day purging due to status"); } else { record.Status = Constants.RecordStatus.PURGED; Trace.TraceInformation("Record " + record.ID + " was marked " + record.Status); } } } else { //Trace.TraceInformation("Now is not after dtCallbackProcessingTimeframeEnd for record " + record.ID); } } else { Trace.TraceInformation("CallbackProcessingTimeframeEndCrossed is true for record " + record.ID); } } //if (_Profile != null) } //if (_queue != null) } //foreach (CallbackRecord record in _recordManager.Records) //Task #2: Remove records where purge is true from _recordManager.Records if (_recordManager.Purge()) { Trace.TraceInformation("_recordManager.Purge() returned true."); } else { Trace.TraceWarning("_recordManager.Purge() returned false."); } //This code is temporary, until a inactive cache is built if (_recordManager.RemoveRecordsInFinalState()) { Trace.TraceInformation("_recordManager.RemoveRecordsInFinalState() returned true."); } else { Trace.TraceWarning("_recordManager.RemoveRecordsInFinalState() returned false."); } //This code is temporary, until a inactive cache is built if (_recordManager.StatusReport()) { Trace.TraceInformation("_recordManager.StatusReport() returned true."); } else { Trace.TraceWarning("_recordManager.StatusReport() returned false."); } if (_recordManager.NumberOfActionableRecords() == 0) { Trace.TraceWarning("_recordManager.NumberOfActionableRecords() is 0; "); _tmrTick.Change(TICKINTERVAL, TICKINTERVAL); return; } if (DateTime.Now.Subtract(_RealtimeDataClient.LastRealtimeDataCollectedAt).TotalMilliseconds > Constants.CONTACT_REALTIMEDATE_REFRESH) { Trace.TraceWarning("Last RealtimeData refresh was at : " + _RealtimeDataClient.LastRealtimeDataCollectedAt); } //Task #3: String sErrorDescription = String.Empty; foreach (CallbackRecord record in _recordManager.Records) { double dInactiveTime = 0; switch (record.Status) { case Constants.RecordStatus.NEW: break; case Constants.RecordStatus.PURGED: break; case Constants.RecordStatus.RETRY: break; case Constants.RecordStatus.INVALID: continue; case Constants.RecordStatus.INACTIVE: continue; case Constants.RecordStatus.COMPLETED: continue; case Constants.RecordStatus.EXCEEDEDNUMBEROFATTEMPTS: continue; case Constants.RecordStatus.PROCESSING: dInactiveTime = DateTime.Now.Subtract(record.StatusLastUpdated).TotalSeconds; if (dInactiveTime >= Constants.STATUSUPDATEINACTIVITY) { sErrorDescription = String.Empty; if (_recordManager.Update(record.ID, String.Empty, String.Empty, Constants.RecordStatus.RETRY, out sErrorDescription)) { Trace.TraceInformation("Record " + record.ID + " went from PROCESSING to " + record.Status + " because it was inactive for " + dInactiveTime.ToString()); } else { Trace.TraceWarning("Record " + record.ID + " did not go to RETRY. Current status:" + record.Status); } } continue; case Constants.RecordStatus.REQUESTED: dInactiveTime = DateTime.Now.Subtract(record.StatusLastUpdated).TotalSeconds; if (dInactiveTime >= Constants.STATUSUPDATEINACTIVITY) { sErrorDescription = String.Empty; if (_recordManager.Update(record.ID, String.Empty, String.Empty, Constants.RecordStatus.RETRY, out sErrorDescription)) { Trace.TraceInformation("Record " + record.ID + " went from REQUESTED to RETRY because it was inactive for " + dInactiveTime.ToString()); } else { Trace.TraceWarning("Record " + record.ID + " did not go to RETRY. Current status:" + record.Status); } } continue; case Constants.RecordStatus.QUEUED: dInactiveTime = DateTime.Now.Subtract(record.StatusLastUpdated).TotalSeconds; if (dInactiveTime >= Constants.STATUSUPDATEINACTIVITY) { sErrorDescription = String.Empty; if (_recordManager.Update(record.ID, String.Empty, String.Empty, Constants.RecordStatus.RETRY, out sErrorDescription)) { Trace.TraceInformation("Record " + record.ID + " went from " + record.Status + " to RETRY because it was inactive for " + dInactiveTime.ToString()); } else { Trace.TraceWarning("Record " + record.ID + " did not go to RETRY. Current status:" + record.Status); } } continue; case Constants.RecordStatus.DIALINGTARGET: sErrorDescription = String.Empty; if (_recordManager.Update(record.ID, String.Empty, String.Empty, Constants.RecordStatus.COMPLETED, out sErrorDescription)) { Trace.TraceInformation("Record " + record.ID + " went from DIALINGTARGET to " + record.Status); } else { Trace.TraceWarning("Record " + record.ID + " did not go to COMPLETED. Current status:" + record.Status); } continue; case Constants.RecordStatus.AGENTACKNOWLEDGED: dInactiveTime = DateTime.Now.Subtract(record.StatusLastUpdated).TotalSeconds; if (dInactiveTime >= Constants.STATUSUPDATEINACTIVITY) { sErrorDescription = String.Empty; if (_recordManager.Update(record.ID, String.Empty, String.Empty, Constants.RecordStatus.RETRY, out sErrorDescription)) { Trace.TraceInformation("Record " + record.ID + " went from AGENTACKNOWLEDGED to " + record.Status + " because it was inactive for " + dInactiveTime.ToString()); } else { Trace.TraceWarning("Record " + record.ID + " did not go to RETRY. Current status:" + record.Status); } } continue; case Constants.RecordStatus.AGENTABANDONED: sErrorDescription = String.Empty; if (_recordManager.Update(record.ID, String.Empty, String.Empty, Constants.RecordStatus.RETRY, out sErrorDescription)) { Trace.TraceInformation("Record " + record.ID + " went from AGENTABANDONED to " + record.Status + " because it was inactive for " + dInactiveTime.ToString()); } else { Trace.TraceWarning("Record " + record.ID + " did not go to RETRY. Current status:" + record.Status); } continue; case Constants.RecordStatus.IVR_FAILURE: sErrorDescription = String.Empty; if (_recordManager.Update(record.ID, String.Empty, String.Empty, Constants.RecordStatus.RETRY, out sErrorDescription)) { Trace.TraceInformation("Record " + record.ID + " went from IVR_FAILURE to " + record.Status); } else { Trace.TraceWarning("Record " + record.ID + " did not go to RETRY. Current status:" + record.Status); } break; }//switch (record.Status) if (record.Status == Constants.RecordStatus.NEW || record.Status == Constants.RecordStatus.RETRY || record.Status == Constants.RecordStatus.PURGED) { //Assert NumberOFAttempts if (record.Status == Constants.RecordStatus.RETRY) { if (record.NumberOfAttempts >= _settingsManager.ApplicationSettings.MaximumNumberOfAttempts) { Trace.TraceInformation("Record " + record.ID + " has reached the maximum number of attempts:" + record.NumberOfAttempts); sErrorDescription = String.Empty; _recordManager.Update(record.ID, String.Empty, String.Empty, Constants.RecordStatus.EXCEEDEDNUMBEROFATTEMPTS, out sErrorDescription); continue; } if (DateTime.Now.Subtract(record.StatusLastUpdated).TotalMinutes <= _settingsManager.ApplicationSettings.MinimumIntervalBetweenRetries) { Trace.TraceInformation("Record " + record.ID + " is in status:" + record.Status + " and has not yet waited " + _settingsManager.ApplicationSettings.MinimumIntervalBetweenRetries + " mins to be attempted again."); continue; } } String sCSQ = record.TargetCSQ; CallbackContactServiceQueue _queue = null; foreach (CallbackContactServiceQueue queue in _settingsManager.CallbackSettings.Queues) { if (sCSQ == queue.Name) { _queue = queue; break; } }//foreach (CallbackContactServiceQueue queue in _settingsManager.CallbackSettings.Queues) if (_queue != null) { Trace.TraceInformation("Record " + record.ID + " Settings for CSQ " + sCSQ + " were found."); CallbackContactServiceQueueSettingsProfile _Profile = null; if (_queue.Profile == null) { Trace.TraceInformation("Record " + record.ID + " Profile for CSQ " + sCSQ + " is null; look for default profile."); foreach (CallbackContactServiceQueue queue in _settingsManager.CallbackSettings.Queues) { if (queue.Name == "Default") { _Profile = queue.Profile; break; } }//foreach (CallbackContactServiceQueue queue in _settingsManager.CallbackSettings.Queues) if (_Profile == null) { Trace.TraceWarning("Record " + record.ID + " Profile for CSQ " + sCSQ + " was not found. Flag record as invalid."); sErrorDescription = String.Empty; _recordManager.Update(record.ID, String.Empty, String.Empty, Constants.RecordStatus.INVALID, out sErrorDescription); continue; } else { Trace.TraceInformation("Record " + record.ID + " Default Profile for CSQ " + sCSQ + " was found."); } } else { Trace.TraceInformation("Record " + record.ID + " Profile for CSQ " + sCSQ + " is not null."); _Profile = _queue.Profile; } //Check profile settings: if (_queue.CallbackEnabled) { if (_Profile == null) { Trace.TraceWarning("Record " + record.ID + " _Profile is null."); } if (_Profile.CallbackProcessingTimeframeBegin == null) { Trace.TraceWarning("Record " + record.ID + " _Profile.CallbackProcessingTimeframeBegin is null."); } DateTime dtCallbackProcessingTimeframeBegin = DateTime.ParseExact(_Profile.CallbackProcessingTimeframeBegin, "HH:mm:ss", System.Globalization.CultureInfo.InvariantCulture); DateTime dtCallbackProcessingTimeframeEnd = DateTime.ParseExact(_Profile.CallbackProcessingTimeframeEnd, "HH:mm:ss", System.Globalization.CultureInfo.InvariantCulture); Trace.TraceInformation("Record " + record.ID + " dtCallbackProcessingTimeframeBegin = " + dtCallbackProcessingTimeframeBegin.ToString() + " Now = " + DateTime.Now.ToString()); if (DateTime.Now.Subtract(dtCallbackProcessingTimeframeBegin).TotalMilliseconds >= 0) { Trace.TraceInformation("Record " + record.ID + " CallbackProcessingTimeframe has opened."); if (dtCallbackProcessingTimeframeEnd.Subtract(DateTime.Now).TotalMilliseconds >= 0) { Trace.TraceInformation("Record " + record.ID + " CallbackProcessingTimeframe has not yet closed."); double dNumberOfIVRPorts = double.Parse(_settingsManager.ApplicationSettings.UCCXNumberOfIVRPorts); double dMaxIVRPortUsagePercent = double.Parse(_settingsManager.ApplicationSettings.UCCXMaxIVRPortUsagePercent); double bMaxIVRPortsAvailable = Math.Floor(dNumberOfIVRPorts * (dMaxIVRPortUsagePercent / 100.0)); int iNumberOfContactsInIVR = _RealtimeDataClient.NumberOfContactsInIVR; if (bMaxIVRPortsAvailable > iNumberOfContactsInIVR) { Trace.TraceInformation("Record id " + record.ID + " Number of contacts in IVR: " + iNumberOfContactsInIVR.ToString() + " IVR Ports available to Callback Server: " + bMaxIVRPortsAvailable.ToString()); if (_settingsManager.ApplicationSettings.BasicInsertionThrottling_Enabled) { Trace.TraceInformation("Record id " + record.ID + " BasicInsertionThrottling: Enabled"); int iCallbacksInIVR = _recordManager.RecordsCurrentlyInIVR; if (iCallbacksInIVR < _settingsManager.ApplicationSettings.BasicInsertionThrottling_MaximumRecordsAtATime) { Trace.TraceInformation("Record id " + record.ID + " Number of Callbacks in IVR: " + iCallbacksInIVR.ToString() + " BasicInsertionThrottling_MaximumRecordsAtATime: " + _settingsManager.ApplicationSettings.BasicInsertionThrottling_MaximumRecordsAtATime); } else //if(iCallbacksInIVR < _settingsManager.ApplicationSettings.BasicInsertionThrottling_MaximumRecordsAtATime) { Trace.TraceWarning("Record " + record.ID + " cannot be reentered: " + " Number of Callbacks in IVR: " + iCallbacksInIVR.ToString() + " BasicInsertionThrottling_MaximumRecordsAtATime: " + _settingsManager.ApplicationSettings.BasicInsertionThrottling_MaximumRecordsAtATime); continue; }//if(iCallbacksInIVR < _settingsManager.ApplicationSettings.BasicInsertionThrottling_MaximumRecordsAtATime) } else { Trace.TraceInformation("Record id " + record.ID + " BasicInsertionThrottling: Disabled"); } if (_RealtimeDataClient.GetContactsQueuedFor(record.TargetCSQ)) { Trace.TraceInformation("Record " + record.ID + " contactRealtimeData.GetContactsQueuedFor() returned true."); if (_RealtimeDataClient.OrderContactsQueuedFor()) { Trace.TraceInformation("Record " + record.ID + " contactRealtimeData.OrderContactsQueuedFor() returned true."); int iResult = _RealtimeDataClient.GetNumberOfContactAheadOf(record.ContactID, record.ID, record.QueueStartTime); if (iResult == -1) { Trace.TraceWarning("_RealtimeDataClient.GetNumberOfContactAheadOf() of recordID " + record.ID + " returned -1. Not sure what to do if false!!!!"); continue; } else if (iResult == -2) { Trace.TraceInformation("_RealtimeDataClient.GetNumberOfContactAheadOf() of recordID " + record.ID + " Not to be reentered yet; scheduled."); continue; } else if (iResult == 0) { Trace.TraceInformation("_RealtimeDataClient.GetNumberOfContactAheadOf() of recordID " + record.ID + " :" + iResult); Trace.TraceInformation("Record id " + record.ID + " with contactID " + record.ContactID + " can be reentered"); System.Threading.Thread thr = new System.Threading.Thread(new System.Threading.ParameterizedThreadStart(_SendReentryRequest)); thr.Start(record.ID); thr = null; break; } } else//if (_RealtimeDataClient.OrderContactsQueuedFor()) { Trace.TraceWarning("Record " + record.ID + " contactRealtimeData.OrderContactsQueuedFor() returned false."); } //if (_RealtimeDataClient.OrderContactsQueuedFor()) } else //if (_RealtimeDataClient.GetContactsQueuedFor(record.TargetCSQ)) { Trace.TraceWarning("Record " + record.ID + " contactRealtimeData.GetContactsQueuedFor() returned false."); } //if (_RealtimeDataClient.GetContactsQueuedFor(record.TargetCSQ)) } else //if (bMaxIVRPortsAvailable > iNumberOfContactsInIVR) { Trace.TraceWarning("Record " + record.ID + " cannot be reentered: " + " Number of contacts in IVR: " + iNumberOfContactsInIVR.ToString() + " IVR Ports available to Callback Server: " + bMaxIVRPortsAvailable.ToString()); continue; }//if (bMaxIVRPortsAvailable > iNumberOfContactsInIVR) //Try reentry based on default algorithm } else//if (dtCallbackProcessingTimeframeEnd.Subtract(DateTime.Now).TotalMilliseconds >= 0) { Trace.TraceInformation("Record " + record.ID + " CallbackProcessingTimeframe has closed."); } //if (dtCallbackProcessingTimeframeEnd.Subtract(DateTime.Now).TotalMilliseconds >= 0) } else //if (DateTime.Now.Subtract(dtCallbackProcessingTimeframeBegin).TotalMilliseconds >= 0) { Trace.TraceInformation("Record " + record.ID + " CallbackProcessingTimeframe has not yet opened."); } //if (DateTime.Now.Subtract(dtCallbackProcessingTimeframeBegin).TotalMilliseconds >= 0) } else //if (_queue.CallbackEnabled) { Trace.TraceWarning("Record " + record.ID + " Callback in not enabled for CSQ " + sCSQ + "; Flag record as invalid."); sErrorDescription = String.Empty; _recordManager.Update(record.ID, String.Empty, String.Empty, Constants.RecordStatus.INVALID, out sErrorDescription); continue; } //if (_queue.CallbackEnabled) } else //if (_queue != null) { Trace.TraceWarning("Record " + record.ID + " Settings for CSQ " + sCSQ + " were not found. Flag record as invalid."); sErrorDescription = String.Empty; _recordManager.Update(record.ID, String.Empty, String.Empty, Constants.RecordStatus.INVALID, out sErrorDescription); continue; } //if (_queue != null) } else //if (record.Status != Constants.RecordStatus.INVALID) { Trace.TraceWarning("Record " + record.ID + " is not NEW or RETRY."); } //if (record.Status != Constants.RecordStatus.INVALID) } //foreach (CallbackRecord record in _recordManager.Records) } catch (Exception ex) { Trace.TraceWarning("Exception: " + ex.Message + Environment.NewLine + "Stacktrace: " + ex.StackTrace); } Trace.TraceInformation("Cycle through " + _recordManager.Records.Count + " records took " + DateTime.Now.Subtract(dtBegin).TotalMilliseconds + " ms."); _tmrTick.Change(TICKINTERVAL, TICKINTERVAL); }//lock (objLock) Trace.TraceInformation("Exit."); }