use of org.jivesoftware.xmpp.workgroup.AgentSession 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.AgentSession 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.AgentSession in project Openfire by igniterealtime.
the class ChatMetadataProvider method executeGet.
public void executeGet(IQ packet, Workgroup workgroup) {
IQ reply = IQ.createResultIQ(packet);
try {
AgentSession agentSession = workgroup.getAgentManager().getAgentSession(packet.getFrom());
if (agentSession == null) {
reply = IQ.createResultIQ(packet);
reply.setChildElement(packet.getChildElement().createCopy());
reply.setError(new PacketError(PacketError.Condition.not_authorized));
workgroup.send(reply);
return;
}
} catch (AgentNotFoundException e) {
reply = IQ.createResultIQ(packet);
reply.setChildElement(packet.getChildElement().createCopy());
reply.setError(new PacketError(PacketError.Condition.not_authorized));
workgroup.send(reply);
return;
}
Element chatSessions = reply.setChildElement("chat-metadata", "http://jivesoftware.com/protocol/workgroup");
Element iq = packet.getChildElement();
String sessionID = iq.element("sessionID").getTextTrim();
Connection con = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
Map<String, String> map = new HashMap<String, String>();
try {
con = DbConnectionManager.getConnection();
pstmt = con.prepareStatement(GET_SESSION_METADATA);
pstmt.setString(1, sessionID);
rs = pstmt.executeQuery();
while (rs.next()) {
String name = rs.getString(1);
String value = rs.getString(2);
map.put(name, value);
}
} catch (Exception ex) {
Log.error(ex.getMessage(), ex);
} finally {
DbConnectionManager.closeConnection(rs, pstmt, con);
}
// Add metadata
chatSessions.add(getMetaDataElement(map));
workgroup.send(reply);
}
use of org.jivesoftware.xmpp.workgroup.AgentSession in project Openfire by igniterealtime.
the class ChatNotes method executeSet.
public void executeSet(IQ packet, Workgroup workgroup) {
IQ reply;
Element iq = packet.getChildElement();
try {
// Verify that an agent is requesting this information.
AgentSession agentSession = workgroup.getAgentManager().getAgentSession(packet.getFrom());
if (agentSession != null) {
String sessionID = iq.element("sessionID").getTextTrim();
Element notes = iq.element("notes");
String noteText = notes.getTextTrim();
appendNote(sessionID, noteText);
reply = IQ.createResultIQ(packet);
} else {
reply = IQ.createResultIQ(packet);
reply.setChildElement(packet.getChildElement().createCopy());
reply.setError(new PacketError(PacketError.Condition.item_not_found));
}
} catch (AgentNotFoundException e) {
reply = IQ.createResultIQ(packet);
reply.setChildElement(packet.getChildElement().createCopy());
reply.setError(new PacketError(PacketError.Condition.item_not_found));
}
workgroup.send(reply);
}
use of org.jivesoftware.xmpp.workgroup.AgentSession in project Openfire by igniterealtime.
the class SiteTracker method handleUserHistoryRequest.
private void handleUserHistoryRequest(IQ packet, Workgroup workgroup) {
IQ reply;
Element iq = packet.getChildElement();
try {
AgentSession agentSession = workgroup.getAgentManager().getAgentSession(packet.getFrom());
if (agentSession == null) {
reply = IQ.createResultIQ(packet);
reply.setChildElement(packet.getChildElement().createCopy());
reply.setError(new PacketError(PacketError.Condition.not_authorized));
workgroup.send(reply);
return;
}
} catch (AgentNotFoundException e) {
reply = IQ.createResultIQ(packet);
reply.setChildElement(packet.getChildElement().createCopy());
reply.setError(new PacketError(PacketError.Condition.not_authorized));
workgroup.send(reply);
return;
}
// Define default values
String sessionID = iq.attribute("sessionID").getText();
reply = IQ.createResultIQ(packet);
Element views = reply.setChildElement("site-user-history", "http://jivesoftware.com/protocol/workgroup");
views.addAttribute("sessionID", sessionID);
SiteUser siteUser = siteUsers.get(sessionID);
if (siteUser != null) {
for (PageView view : siteUser.getViews()) {
Element pageView = views.addElement("page-view");
pageView.addElement("title").setText(view.getTitle());
pageView.addElement("url").setText(view.getUrl());
pageView.addElement("time").setText(Long.toString(view.getTimeViewed()));
}
workgroup.send(reply);
}
}
Aggregations