use of org.jivesoftware.xmpp.workgroup.Workgroup in project Openfire by igniterealtime.
the class RoundRobinDispatcher method getBestNextAgent.
/**
* <p>Locate the next 'best' agent to receive an offer.</p>
* <p>Routing is based on show-status, max-chats, and who has
* already rejected the offer.
* show status is ranked from most available to least:
* chat, default (no show status), away,
* and xa. A show status of dnd indicates no offers should be routed to an agent.
* The general algorithm is:</p>
* <ul>
* <li>Mark the current position.</li>
* <li>Start iterating around the circular queue until all agents
* have been considered. For each agent:
* <ul>
* <li>Skip if session is null. Should only occur if no agents are in the list.</li>
* <li>Skip if session show state is DND. Never route to agents that are dnd.</li>
* <li>Skip if session current-chats is equal to or higher than max-chats.</li>
* <li>Replace current best if:
* <ul>
* <li>No current best. Any agent is better than none.</li>
* <li>If session hasn't rejected offer but current best has.</li>
* <li>If both session and current best have not rejected the
* offer and session show-status is higher.</li>
* <li>If both session and current best have rejected offer and
* session show-status is higher.</li>
* </ul></li>
* </ul></li>
* </li>
*
* @param initialAgent the initial agent requested by the user.
* @param ignoreAgent agent that should not be considered as available.
* @param offer the offer about to be sent to the best available agent.
* @return the best agent.
*/
private AgentSession getBestNextAgent(String initialAgent, String ignoreAgent, Offer offer) {
AgentSession bestSession;
// Look for specified agent in agent list
if (initialAgent != null) {
final AgentSessionList agentSessionList = queue.getAgentSessionList();
for (AgentSession agentSession : agentSessionList.getAgentSessions()) {
String sessionAgent = agentSession.getAgent().getAgentJID().toBareJID();
boolean match = sessionAgent.startsWith(initialAgent.toLowerCase());
Workgroup workgroup = offer.getRequest().getWorkgroup();
if (agentSession.isAvailableToChat() && agentSession.getCurrentChats(workgroup) < agentSession.getMaxChats(workgroup) && match) {
bestSession = agentSession;
// Log debug trace
Log.debug("RR - Initial agent: " + bestSession.getJID() + " will receive offer for request: " + offer.getRequest());
return bestSession;
}
}
}
// Let's iterate through each agent and check availability
final AgentSessionList agentSessionList = queue.getAgentSessionList();
final List<AgentSession> possibleSessions = new ArrayList<AgentSession>();
for (AgentSession agentSession : agentSessionList.getAgentSessions()) {
String sessionAgent = agentSession.getAgent().getAgentJID().toBareJID();
boolean ignore = ignoreAgent != null && sessionAgent.startsWith(ignoreAgent.toLowerCase());
if (!ignore && validateAgent(agentSession, offer)) {
possibleSessions.add(agentSession);
}
}
// Select the best agent from the list of possible agents
if (possibleSessions.size() > 0) {
AgentSession s = agentSelector.bestAgentFrom(possibleSessions, offer);
// Log debug trace
Log.debug("RR - Agent SELECTED: " + s.getJID() + " for receiving offer for request: " + offer.getRequest());
return s;
}
return null;
}
use of org.jivesoftware.xmpp.workgroup.Workgroup in project Openfire by igniterealtime.
the class RoundRobinDispatcher method dispatch.
/**
* Dispatch the given request to one or more agents in the agent pool.<p>
*
* If this method returns, it is assumed that the request was properly
* dispatched.The only exception is if an agent is not in the pool for routing
* within the agent timeout period, the dispatch will throw an AgentNotFoundException
* so the request can be re-routed.
*
* @param offer the offer to send to the best agent available.
*/
public void dispatch(Offer offer) {
// The time when the request should timeout
long timeoutTime = System.currentTimeMillis() + info.getRequestTimeout();
final Request request = offer.getRequest();
boolean canBeInQueue = request instanceof UserRequest;
Map<String, List<String>> map = request.getMetaData();
String initialAgent = map.get("agent") == null || map.get("agent").isEmpty() ? null : map.get("agent").get(0);
String ignoreAgent = map.get("ignore") == null || map.get("ignore").isEmpty() ? null : map.get("ignore").get(0);
// Log debug trace
Log.debug("RR - Dispatching request: " + request + " in queue: " + queue.getAddress());
// to overflow the current request
if (!agentList.isEmpty()) {
for (long timeRemaining = timeoutTime - System.currentTimeMillis(); !offer.isAccepted() && timeRemaining > 0 && !offer.isCancelled(); timeRemaining = timeoutTime - System.currentTimeMillis()) {
try {
AgentSession session = getBestNextAgent(initialAgent, ignoreAgent, offer);
if (session == null && agentList.isEmpty()) {
// Stop looking for an agent since there are no more agent available
break;
} else if (session == null || offer.isRejector(session)) {
initialAgent = null;
Thread.sleep(1000);
} else {
// Recheck for changed maxchat setting
Workgroup workgroup = request.getWorkgroup();
if (session.getCurrentChats(workgroup) < session.getMaxChats(workgroup)) {
// Set the timeout of the offer based on the remaining time of the
// initial request and the default offer timeout
timeRemaining = timeoutTime - System.currentTimeMillis();
offer.setTimeout(timeRemaining < info.getOfferTimeout() ? timeRemaining : info.getOfferTimeout());
// Make the offer and wait for a resolution to the offer
if (!request.sendOffer(session, queue)) {
// Log debug trace
Log.debug("RR - Offer for request: " + offer.getRequest() + " FAILED TO BE SENT to agent: " + session.getJID());
continue;
}
// Log debug trace
Log.debug("RR - Offer for request: " + offer.getRequest() + " SENT to agent: " + session.getJID());
offer.waitForResolution();
// and reset the offer
if (offer.isAccepted()) {
// Get the first agent that accepted the offer
AgentSession selectedAgent = offer.getAcceptedSessions().get(0);
// Log debug trace
Log.debug("RR - Agent: " + selectedAgent.getJID() + " ACCEPTED request: " + request);
// Create the room and send the invitations
offer.invite(selectedAgent);
// has finished
for (AgentSession agent : offer.getAcceptedSessions()) {
agent.removeOffer(offer);
}
if (canBeInQueue) {
// Remove the user from the queue since his request has
// been accepted
queue.removeRequest((UserRequest) request);
}
}
} else {
// Log debug trace
Log.debug("RR - Selected agent: " + session.getJID() + " has reached max number of chats");
}
}
} catch (Exception e) {
Log.error(e.getMessage(), e);
}
}
}
if (!offer.isAccepted() && !offer.isCancelled()) {
// Calculate the maximum time limit for an unattended request before cancelling it
long limit = request.getCreationTime().getTime() + (info.getRequestTimeout() * (getOverflowTimes() + 1));
if (limit - System.currentTimeMillis() <= 0 || !canBeInQueue) {
// Log debug trace
Log.debug("RR - Cancelling request that maxed out overflow limit or cannot be queued: " + request);
// Cancel the request if it has overflowed 'n' times
request.cancel(Request.CancelType.AGENT_NOT_FOUND);
} else {
// Overflow if request timed out and was not dispatched and max number of overflows
// has not been reached yet
overflow(offer);
// If there is no other queue to overflow then cancel the request
if (!offer.isAccepted() && !offer.isCancelled()) {
// Log debug trace
Log.debug("RR - Cancelling request that didn't overflow: " + request);
request.cancel(Request.CancelType.AGENT_NOT_FOUND);
}
}
}
}
use of org.jivesoftware.xmpp.workgroup.Workgroup in project Openfire by igniterealtime.
the class ChatHistoryUtils method getTotalWaitTimeForWorkgroup.
/**
* Returns the number of canceled requests.
*
* @param workgroupName the workgroup to search
* @param startDate the time to begin the search from.
* @param endDate the time to end the search.
* @return the total number of requests
*/
public static long getTotalWaitTimeForWorkgroup(String workgroupName, Date startDate, Date endDate) {
Workgroup workgroup = null;
try {
workgroup = WorkgroupManager.getInstance().getWorkgroup(new JID(workgroupName));
} catch (Exception ex) {
Log.error(ex.getMessage(), ex);
}
if (workgroup == null) {
return 0;
}
int waitTime = 0;
Connection con = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
con = DbConnectionManager.getConnection();
pstmt = con.prepareStatement(WORKGROUP_WAIT_TIME);
pstmt.setLong(1, workgroup.getID());
// Set the state the ignored requests.
pstmt.setInt(2, 1);
pstmt.setString(2, StringUtils.dateToMillis(startDate));
pstmt.setString(3, StringUtils.dateToMillis(endDate));
rs = pstmt.executeQuery();
rs.next();
waitTime = rs.getInt(1);
} catch (Exception ex) {
Log.error(ex.getMessage(), ex);
} finally {
DbConnectionManager.closeConnection(rs, pstmt, con);
}
return waitTime;
}
use of org.jivesoftware.xmpp.workgroup.Workgroup in project Openfire by igniterealtime.
the class ChatHistoryUtils method getNumberOfChatsAccepted.
/**
* Returns the number of chat requests that were accepted.
*
* @param workgroupName the name of the workgroup where the request(s) were made.
* @param startDate the start date.
* @param endDate the end date.
* @return the number of chats requests accepted by the workgroup.
*/
public static int getNumberOfChatsAccepted(String workgroupName, Date startDate, Date endDate) {
Workgroup workgroup = null;
try {
workgroup = WorkgroupManager.getInstance().getWorkgroup(new JID(workgroupName));
} catch (Exception ex) {
Log.error(ex.getMessage(), ex);
}
if (workgroup == null) {
return 0;
}
int count = 0;
Connection con = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
con = DbConnectionManager.getConnection();
pstmt = con.prepareStatement(ACCEPTED_CHATS_COUNT);
pstmt.setLong(1, workgroup.getID());
pstmt.setString(2, StringUtils.dateToMillis(startDate));
pstmt.setString(3, StringUtils.dateToMillis(endDate));
rs = pstmt.executeQuery();
if (rs.next()) {
count = rs.getInt(1);
}
} catch (Exception ex) {
Log.error(ex.getMessage(), ex);
} finally {
DbConnectionManager.closeConnection(rs, pstmt, con);
}
return count;
}
use of org.jivesoftware.xmpp.workgroup.Workgroup in project Openfire by igniterealtime.
the class ChatHistoryUtils method getNumberOfRequestsForWorkgroup.
/**
* Returns the number of request made to a workgroup between
* specified dates.
*
* @param workgroupName the workgroup to search
* @param startDate the time to begin the search from.
* @param endDate the time to end the search.
* @return the total number of requests
*/
public static int getNumberOfRequestsForWorkgroup(String workgroupName, Date startDate, Date endDate) {
Workgroup workgroup = getWorkgroup(workgroupName);
if (workgroup == null) {
return 0;
}
int count = 0;
Connection con = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
con = DbConnectionManager.getConnection();
pstmt = con.prepareStatement(WORKGROUP_REQUEST_COUNT);
pstmt.setLong(1, workgroup.getID());
pstmt.setString(2, StringUtils.dateToMillis(startDate));
pstmt.setString(3, StringUtils.dateToMillis(endDate));
rs = pstmt.executeQuery();
if (rs.next()) {
count = rs.getInt(1);
}
} catch (Exception ex) {
Log.error(ex.getMessage(), ex);
} finally {
DbConnectionManager.closeConnection(rs, pstmt, con);
}
return count;
}
Aggregations