add support for being able to return more than one event in a single long poll request, since the client will poll no more often than every half-second. this could have caused a rather large backlog of events to deliver if chat was active.

This commit is contained in:
Andy Janata 2012-01-06 16:43:40 -08:00
parent 8a45078d77
commit eba02a35bd
4 changed files with 63 additions and 26 deletions

View File

@ -30,23 +30,26 @@ cah.longpoll.complete = function() {
}
};
cah.longpoll.done = function(data) {
cah.log.debug("long poll done", data);
cah.longpoll.done = function(data_list) {
cah.log.debug("long poll done", data_list);
if (data['error']) {
// TODO cancel any timers or whatever we may have, and disable interface
// this probably should be done in the appropriate error code handler because we may not
// want to always be that extreme.
if (cah.longpoll.ErrorCodeHandlers[data.error_code]) {
cah.longpoll.ErrorCodeHandlers[data.error_code](data);
for ( var index in data_list) {
var data = data_list[index];
if (data['error']) {
// TODO cancel any timers or whatever we may have, and disable interface
// this probably should be done in the appropriate error code handler because we may not
// want to always be that extreme.
if (cah.longpoll.ErrorCodeHandlers[data.error_code]) {
cah.longpoll.ErrorCodeHandlers[data.error_code](data);
} else {
cah.log.error(data.error_message);
}
} else {
cah.log.error(data.error_message);
}
} else {
if (cah.longpoll.EventHandlers[data.event]) {
cah.longpoll.EventHandlers[data.event](data);
} else {
cah.log.error("Unhandled event " + data.event);
if (cah.longpoll.EventHandlers[data.event]) {
cah.longpoll.EventHandlers[data.event](data);
} else {
cah.log.error("Unhandled event " + data.event);
}
}
}
@ -56,7 +59,6 @@ cah.longpoll.done = function(data) {
cah.longpoll.error = function(jqXHR, textStatus, errorThrown) {
// TODO deal with this somehow
debugger;
cah.log.debug(textStatus);
cah.longpoll.Backoff *= 2;
cah.log

View File

@ -2,6 +2,7 @@ package net.socialgamer.cah;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;
import java.util.Map;
import javax.servlet.ServletException;
@ -108,7 +109,23 @@ public abstract class CahServlet extends HttpServlet {
* Key-value data to return as the response.
*/
protected void returnData(final PrintWriter writer, final Map<String, Object> data) {
writer.println(JSONValue.toJSONString(data));
returnObject(writer, data);
}
/**
* Return multiple response data to the client.
*
* @param writer
* Writer for the response.
* @param data_list
* List of key-value data to return as the response.
*/
protected void returnArray(final PrintWriter writer, final List<Map<String, Object>> data_list) {
returnObject(writer, data_list);
}
private void returnObject(final PrintWriter writer, final Object object) {
writer.println(JSONValue.toJSONString(object));
}
protected Injector getInjector() {

View File

@ -2,7 +2,10 @@ package net.socialgamer.cah;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.ServletException;
@ -35,12 +38,10 @@ public class LongPollServlet extends CahServlet {
private static final double TIMEOUT_RANDOMNESS = 20 * 1000 * 1000;
/**
* @see HttpServlet#HttpServlet()
* The maximum number of messages which will be returned to a client during a single poll
* operation.
*/
public LongPollServlet() {
super();
// TODO Auto-generated constructor stub
}
private static final int MAX_MESSAGES_PER_POLL = 5;
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
@ -67,10 +68,14 @@ public class LongPollServlet extends CahServlet {
}
}
if (user.hasQueuedMessages()) {
final QueuedMessage qm = user.getNextQueuedMessage();
final Collection<QueuedMessage> msgs = user.getNextQueuedMessages(MAX_MESSAGES_PER_POLL);
// just in case...
if (qm != null) {
returnData(out, qm.getData());
if (msgs.size() > 0) {
final List<Map<String, Object>> data = new ArrayList<Map<String, Object>>(msgs.size());
for (final QueuedMessage qm : msgs) {
data.add(qm.getData());
}
returnArray(out, data);
return;
}
}
@ -78,6 +83,8 @@ public class LongPollServlet extends CahServlet {
final Map<String, Object> data = new HashMap<String, Object>();
data.put("event", "noop");
data.put("timestamp", System.currentTimeMillis());
returnData(out, data);
final List<Map<String, Object>> data_list = new ArrayList<Map<String, Object>>(1);
data_list.add(data);
returnArray(out, data_list);
}
}

View File

@ -1,5 +1,7 @@
package net.socialgamer.cah.data;
import java.util.ArrayList;
import java.util.Collection;
import java.util.concurrent.PriorityBlockingQueue;
@ -61,6 +63,15 @@ public class User {
}
}
public Collection<QueuedMessage> getNextQueuedMessages(final int maxElements) {
final ArrayList<QueuedMessage> c = new ArrayList<QueuedMessage>(maxElements);
synchronized (queuedMessageSynchronization) {
queuedMessages.drainTo(c, maxElements);
}
c.trimToSize();
return c;
}
public String getNickname() {
return nickname;
}