Fix for out-of-order message/receipt arrival

In a multi device world, it's possible to receive a receipt for a sync
message before the sync message actually arrives. In this case we need
to keep the receipt around and the process it when the message shows up.
This commit is contained in:
lilia 2015-05-18 13:48:48 -07:00
parent c4fa2cb935
commit 65a6068003
2 changed files with 42 additions and 8 deletions

View file

@ -102,6 +102,9 @@
});
}
// lazy hack
window.receipts = new Backbone.Collection();
function onDeliveryReceipt(pushMessage) {
var timestamp = pushMessage.timestamp.toNumber();
var messages = new Whisper.MessageCollection();
@ -123,6 +126,11 @@
// successfully delivered to?
}
}
// if we get here, we didn't find a matching message.
// keep the receipt in memory in case it shows up later
// as a sync message.
receipts.add({ timestamp: timestamp, source: pushMessage.source });
return;
});
}).fail(function() {
console.log('got delivery receipt for unknown message', pushMessage.source, timestamp);

View file

@ -130,13 +130,6 @@
var source = message.get('source');
var timestamp = message.get('sent_at');
return textsecure.processDecrypted(pushMessageContent, source).then(function(pushMessageContent) {
var type = 'incoming';
if (pushMessageContent.sync) {
type = 'outgoing';
timestamp = pushMessageContent.sync.timestamp.toNumber();
}
var now = new Date().getTime();
var conversationId = source;
if (pushMessageContent.sync) {
conversationId = pushMessageContent.sync.destination;
@ -144,8 +137,41 @@
conversationId = pushMessageContent.group.id;
}
var conversation = new Whisper.Conversation({id: conversationId});
var attributes = {};
conversation.fetch().always(function() {
var type = 'incoming';
if (pushMessageContent.sync) {
type = 'outgoing';
timestamp = pushMessageContent.sync.timestamp.toNumber();
// lazy hack - check for receipts that arrived early.
if (pushMessageContent.sync.destination) {
var receipt = window.receipts.findWhere({
timestamp: timestamp,
source: pushMessageContent.sync.destination
});
if (receipt) {
window.receipts.remove(receipt);
message.set({
delivered: (message.get('delivered') || 0) + 1
});
}
} else if (pushMessageContent.group.id) { // group sync
var members = conversation.get('members');
var receipts = window.receipts.where({ timestamp: timestamp });
for (var i in receipts) {
if (members.indexOf(receipts[i].get('source')) > -1) {
window.receipts.remove(receipts[i]);
message.set({
delivered: (message.get('delivered') || 0) + 1
});
}
}
} else {
throw new Error('Received sync message with no destination and no group id');
}
}
var now = new Date().getTime();
var attributes = {};
if (pushMessageContent.group) {
var group_update = {};
attributes = {