randomize the timeout in the long poll servlet so all clients don't hammer it at the same time

This commit is contained in:
Andy Janata 2011-12-22 18:43:13 -08:00
parent 5aacc0ac32
commit cb4d4413c2
1 changed files with 17 additions and 4 deletions

View File

@ -23,7 +23,16 @@ import net.socialgamer.cah.data.User;
public class LongPollServlet extends CahServlet { public class LongPollServlet extends CahServlet {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
private static final long TIMEOUT = 60 * 1000; /**
* Minimum amount of time before timing out and returning a no-op, in nanoseconds.
*/
private static final long TIMEOUT_BASE = 60 * 1000 * 1000;
/**
* Randomness factor added to minimum timeout duration, in nanoseconds. The maximum timeout delay
* will be TIMEOUT_BASE + TIMEOUT_RANDOMNESS.
*/
private static final double TIMEOUT_RANDOMNESS = 20 * 1000 * 1000;
/** /**
* @see HttpServlet#HttpServlet() * @see HttpServlet#HttpServlet()
@ -42,12 +51,16 @@ public class LongPollServlet extends CahServlet {
IOException { IOException {
final PrintWriter out = response.getWriter(); final PrintWriter out = response.getWriter();
final long start = System.currentTimeMillis(); final long start = System.nanoTime();
// Pick a random timeout point between TIMEOUT_BASE and TIMEOUT_BASE + TIMEOUT_RANDOMNESS
// nanoseconds from now.
final long end = start + TIMEOUT_BASE + (long) (Math.random() * TIMEOUT_RANDOMNESS);
final User user = (User) hSession.getAttribute("user"); final User user = (User) hSession.getAttribute("user");
assert (user != null);
// TODO we might have to synchronize on the user object? // TODO we might have to synchronize on the user object?
while (!(user.hasQueuedMessages()) && start + TIMEOUT > System.currentTimeMillis()) { while (!(user.hasQueuedMessages()) && System.nanoTime() < end) {
try { try {
user.waitForNewMessageNotification(start + TIMEOUT - System.currentTimeMillis()); user.waitForNewMessageNotification((end - System.nanoTime()) / 1000);
} catch (final InterruptedException ie) { } catch (final InterruptedException ie) {
// I don't think we care? // I don't think we care?
} }