From c18a28b1be72ddef4768cd24cb0939d4dd797ada Mon Sep 17 00:00:00 2001 From: Jesse Young Date: Tue, 29 Nov 2011 18:04:35 -0800 Subject: [PATCH] enable long polling - increase socket timeout, start only one PollerTask at a time, and add 5 sec poll interval; prevent sending duplicate outgoing SMS if server does not receive send_status request --- res/values/arrays.xml | 2 ++ src/org/envaya/sms/App.java | 40 ++++++++++++++++++----- src/org/envaya/sms/Outbox.java | 42 +++++++++++++++++++++++-- src/org/envaya/sms/task/PollerTask.java | 6 ++++ 4 files changed, 80 insertions(+), 10 deletions(-) diff --git a/res/values/arrays.xml b/res/values/arrays.xml index 70398b5..16e82fa 100755 --- a/res/values/arrays.xml +++ b/res/values/arrays.xml @@ -2,6 +2,7 @@ + 5 sec 15 sec 30 sec 1 minute @@ -14,6 +15,7 @@ + 5 15 30 60 diff --git a/src/org/envaya/sms/App.java b/src/org/envaya/sms/App.java index 27f9305..100601a 100755 --- a/src/org/envaya/sms/App.java +++ b/src/org/envaya/sms/App.java @@ -99,6 +99,7 @@ public final class App extends Application { public static final int LOG_TIMESTAMP_INTERVAL = 60000; // ms public static final int HTTP_CONNECTION_TIMEOUT = 10000; // ms + public static final int HTTP_SOCKET_TIMEOUT = 60000; // ms // Each QueuedMessage is identified within our internal Map by its Uri. // Currently QueuedMessage instances are only available within EnvayaSMS, @@ -353,14 +354,37 @@ public final class App extends Application { extras); } - public void checkOutgoingMessages() + private boolean pollActive = false; + private boolean requestedPoll = false; + + public synchronized void markPollComplete() { - String serverUrl = getServerUrl(); - if (serverUrl.length() > 0) { - log("Checking for outgoing messages"); - new PollerTask(this).execute(); - } else { - log("Can't check outgoing messages; server URL not set"); + pollActive = false; + + if (requestedPoll) + { + requestedPoll = false; + checkOutgoingMessages(); + } + } + + public synchronized void checkOutgoingMessages() + { + if (!pollActive) + { + String serverUrl = getServerUrl(); + if (serverUrl.length() > 0) { + log("Checking for outgoing messages"); + pollActive = true; + new PollerTask(this).execute(); + } else { + log("Can't check outgoing messages; server URL not set"); + } + } + else + { + debug("Waiting for server response..."); + requestedPoll = true; } } @@ -696,7 +720,7 @@ public final class App extends Application { { HttpParams httpParams = new BasicHttpParams(); HttpConnectionParams.setConnectionTimeout(httpParams, HTTP_CONNECTION_TIMEOUT); - HttpConnectionParams.setSoTimeout(httpParams, HTTP_CONNECTION_TIMEOUT); + HttpConnectionParams.setSoTimeout(httpParams, HTTP_SOCKET_TIMEOUT); HttpProtocolParams.setContentCharset(httpParams, "UTF-8"); return httpParams; } diff --git a/src/org/envaya/sms/Outbox.java b/src/org/envaya/sms/Outbox.java index 2ec53f2..eb9929f 100755 --- a/src/org/envaya/sms/Outbox.java +++ b/src/org/envaya/sms/Outbox.java @@ -11,17 +11,27 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Comparator; import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedList; import java.util.Map; import java.util.PriorityQueue; +import java.util.Queue; +import java.util.Set; import org.apache.http.message.BasicNameValuePair; import org.envaya.sms.receiver.DequeueOutgoingMessageReceiver; import org.envaya.sms.task.HttpTask; public class Outbox { private Map outgoingMessages = new HashMap(); - + private App app; + // keep track of some recent message URIs to avoid sending duplicate messages + // (e.g. if send_status HTTP request fails for some reason) + public static final int MAX_RECENT_URIS = 100; + private Set recentSentMessageUris = new HashSet(); + private Queue recentSentMessageUriOrder = new LinkedList(); + // number of outgoing messages that are currently being sent and waiting for // messageSent or messageFailed to be called private int numSendingOutgoingMessages = 0; @@ -108,7 +118,11 @@ public class Outbox { notifyMessageStatus(sms, App.STATUS_SENT, ""); - outgoingMessages.remove(sms.getUri()); + Uri uri = sms.getUri(); + + outgoingMessages.remove(uri); + + addRecentSentMessage(sms); notifyChanged(); @@ -116,6 +130,23 @@ public class Outbox { maybeDequeueMessage(); } + private synchronized void addRecentSentMessage(OutgoingMessage sms) + { + if (sms.getServerId() != null) + { + Uri uri = sms.getUri(); + + recentSentMessageUris.add(uri); + recentSentMessageUriOrder.add(uri); + + if (recentSentMessageUriOrder.size() > MAX_RECENT_URIS) + { + Uri oldUri = recentSentMessageUriOrder.remove(); + recentSentMessageUris.remove(oldUri); + } + } + } + public synchronized void messageFailed(OutgoingMessage sms, String error) { if (sms.scheduleRetry()) @@ -166,6 +197,13 @@ public class Outbox { app.debug("Duplicate outgoing " + sms.getLogName() + ", skipping"); return; } + + if (recentSentMessageUris.contains(uri)) + { + app.debug("Outgoing " + sms.getLogName() + " already sent, re-notifying server"); + notifyMessageStatus(sms, App.STATUS_SENT, ""); + return; + } outgoingMessages.put(uri, sms); enqueueMessage(sms); diff --git a/src/org/envaya/sms/task/PollerTask.java b/src/org/envaya/sms/task/PollerTask.java index 82f8644..6f20923 100755 --- a/src/org/envaya/sms/task/PollerTask.java +++ b/src/org/envaya/sms/task/PollerTask.java @@ -12,6 +12,12 @@ public class PollerTask extends HttpTask { super(app, new BasicNameValuePair("action", App.ACTION_OUTGOING)); } + @Override + protected void onPostExecute(HttpResponse response) { + super.onPostExecute(response); + app.markPollComplete(); + } + @Override protected void handleResponse(HttpResponse response) throws Exception { for (OutgoingMessage reply : parseResponseXML(response)) {