5
0
mirror of https://github.com/cwinfo/envayasms.git synced 2024-11-09 10:20:25 +00:00

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

This commit is contained in:
Jesse Young 2011-11-29 18:04:35 -08:00
parent 22f8c26da1
commit c18a28b1be
4 changed files with 80 additions and 10 deletions

View File

@ -2,6 +2,7 @@
<resources> <resources>
<string-array name="check_intervals"> <string-array name="check_intervals">
<item>5 sec</item>
<item>15 sec</item> <item>15 sec</item>
<item>30 sec</item> <item>30 sec</item>
<item>1 minute</item> <item>1 minute</item>
@ -14,6 +15,7 @@
</string-array> </string-array>
<string-array name="check_intervals_values"> <string-array name="check_intervals_values">
<item>5</item>
<item>15</item> <item>15</item>
<item>30</item> <item>30</item>
<item>60</item> <item>60</item>

View File

@ -99,6 +99,7 @@ public final class App extends Application {
public static final int LOG_TIMESTAMP_INTERVAL = 60000; // ms public static final int LOG_TIMESTAMP_INTERVAL = 60000; // ms
public static final int HTTP_CONNECTION_TIMEOUT = 10000; // 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. // Each QueuedMessage is identified within our internal Map by its Uri.
// Currently QueuedMessage instances are only available within EnvayaSMS, // Currently QueuedMessage instances are only available within EnvayaSMS,
@ -353,14 +354,37 @@ public final class App extends Application {
extras); extras);
} }
public void checkOutgoingMessages() private boolean pollActive = false;
private boolean requestedPoll = false;
public synchronized void markPollComplete()
{ {
String serverUrl = getServerUrl(); pollActive = false;
if (serverUrl.length() > 0) {
log("Checking for outgoing messages"); if (requestedPoll)
new PollerTask(this).execute(); {
} else { requestedPoll = false;
log("Can't check outgoing messages; server URL not set"); 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(); HttpParams httpParams = new BasicHttpParams();
HttpConnectionParams.setConnectionTimeout(httpParams, HTTP_CONNECTION_TIMEOUT); HttpConnectionParams.setConnectionTimeout(httpParams, HTTP_CONNECTION_TIMEOUT);
HttpConnectionParams.setSoTimeout(httpParams, HTTP_CONNECTION_TIMEOUT); HttpConnectionParams.setSoTimeout(httpParams, HTTP_SOCKET_TIMEOUT);
HttpProtocolParams.setContentCharset(httpParams, "UTF-8"); HttpProtocolParams.setContentCharset(httpParams, "UTF-8");
return httpParams; return httpParams;
} }

View File

@ -11,8 +11,12 @@ import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Comparator; import java.util.Comparator;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Map; import java.util.Map;
import java.util.PriorityQueue; import java.util.PriorityQueue;
import java.util.Queue;
import java.util.Set;
import org.apache.http.message.BasicNameValuePair; import org.apache.http.message.BasicNameValuePair;
import org.envaya.sms.receiver.DequeueOutgoingMessageReceiver; import org.envaya.sms.receiver.DequeueOutgoingMessageReceiver;
import org.envaya.sms.task.HttpTask; import org.envaya.sms.task.HttpTask;
@ -22,6 +26,12 @@ public class Outbox {
private App app; 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<Uri> recentSentMessageUris = new HashSet<Uri>();
private Queue<Uri> recentSentMessageUriOrder = new LinkedList<Uri>();
// number of outgoing messages that are currently being sent and waiting for // number of outgoing messages that are currently being sent and waiting for
// messageSent or messageFailed to be called // messageSent or messageFailed to be called
private int numSendingOutgoingMessages = 0; private int numSendingOutgoingMessages = 0;
@ -108,7 +118,11 @@ public class Outbox {
notifyMessageStatus(sms, App.STATUS_SENT, ""); notifyMessageStatus(sms, App.STATUS_SENT, "");
outgoingMessages.remove(sms.getUri()); Uri uri = sms.getUri();
outgoingMessages.remove(uri);
addRecentSentMessage(sms);
notifyChanged(); notifyChanged();
@ -116,6 +130,23 @@ public class Outbox {
maybeDequeueMessage(); 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) public synchronized void messageFailed(OutgoingMessage sms, String error)
{ {
if (sms.scheduleRetry()) if (sms.scheduleRetry())
@ -167,6 +198,13 @@ public class Outbox {
return; 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); outgoingMessages.put(uri, sms);
enqueueMessage(sms); enqueueMessage(sms);
} }

View File

@ -12,6 +12,12 @@ public class PollerTask extends HttpTask {
super(app, new BasicNameValuePair("action", App.ACTION_OUTGOING)); super(app, new BasicNameValuePair("action", App.ACTION_OUTGOING));
} }
@Override
protected void onPostExecute(HttpResponse response) {
super.onPostExecute(response);
app.markPollComplete();
}
@Override @Override
protected void handleResponse(HttpResponse response) throws Exception { protected void handleResponse(HttpResponse response) throws Exception {
for (OutgoingMessage reply : parseResponseXML(response)) { for (OutgoingMessage reply : parseResponseXML(response)) {