I had a general question about programming in Twilio which I posted to stackoverflow, but since I'm actually using SFDC as my development platform, I'm also going to ask here in case there are Salesforce-specific solutions.
The problem
I'm receiving text messages from Twilio and saving them as custom objects in my Salesforce database. If someone sends me a message that is longer than 160 characters long, it gets chopped up into chunks and sent as multiple messages; in my app, I want to recombine them and save them as a single new record.
When Twilio sends me the incoming messages (as a POST to a Site), there's no way for me to inspect the request and determine whether it's a new message or an addition to a previous one. Instead, I'm doing this in my Apex:
Message__c msg = tryToGetMessageFromThisSenderInLastMinute();
if (msg != null) {
// Append to previous
msg.Body__c += newMessage;
} else {
// Save a new message
msg = new Message__c(Body__c = newMessage);
}
upsert msg;
The problem is that sometimes the second message arrives before the first one has finished saving. As a result, two records will be created instead of just one. When there are three (or more) message segments, it gets even crazier:
// First message arrives:
record1 == "This is the first message."
// Second message arrives, first isn't saved yet.
record1 == "This is the first message."
record2 == "This is the second message."
// Third message arrives, first has now been saved.
record1 == "This is the first message. This is the third message."
record2 == "This is the second message."
Are there Salesforce-specific solutions?
Some ideas:
Control flow w/ static properties: Unfortunately, each message comes in as a separate request, so static variables don't retain their values.
Go Async or Pause before (re-)checking for an existing record: This would be tricky to do well, but is irrelevant on SFDC since there's no way to 'sleep' within a synchronous flow. Going async (@future) could be even worse b/c I can't guarantee when the records will be processed. It doesn't solve the problem, just delays it.
Other Ideas? Looking for good tricks here - I'm out of my own ideas!