Added ability to ensure that every push is delivered to Apple

If you send many push notifications (10k) and 10th will have invalid token,
there is chance that 2k push notifications will be broken before broken pipe exception.
This commit adds checking for every push message and fix bug with close event listener.
This commit is contained in:
Ian Babrou 2011-09-25 18:07:56 +04:00
Родитель 516aba71dd
Коммит 47519f5f5c
1 изменённых файлов: 59 добавлений и 18 удалений

Просмотреть файл

@ -31,6 +31,7 @@ var Connection = function (optionArgs) {
, enhanced: true /* enable enhanced format */
, errorCallback: undefined /* Callback when error occurs */
, cacheLength: 5 /* Number of notifications to cache for error purposes */
, writeTimeout: 10 /* Timeout to wait for empty buffer */
};
if (optionArgs) {
@ -50,15 +51,28 @@ var Connection = function (optionArgs) {
callback = function() {
if(!self.socket.authorized) {
throw self.socket.authorizationError
}
while(offlineCache.length) {
self.socket.write(offlineCache.shift());
}
self.scheduleOfflineCacheChecking();
});
self.socket.on('data', function(data) { handleTransmissionError(data); });
self.socket.on('error', function(data) {self.socket.removeAllListeners(); self.socket = undefined; });
self.socket.once('end', function () { });
self.socket.once('close', function () { self.socket.removeAllListeners(); self.socket = undefined; });
self.socket.on('data', function(data) {
handleTransmissionError(data);
});
self.socket.on('error', function(data) {
self.socket.removeAllListeners();
self.socket = undefined;
});
self.socket.once('close', function () {
if (!self.socket) {
return;
}
self.socket.removeAllListeners();
self.socket = undefined;
});
}
var connect = invoke_after(function() { startSocket(); });
@ -79,6 +93,42 @@ var Connection = function (optionArgs) {
hasKey = true;
}));
this.writeNotificationToSocket = function(data) {
if (self.socket === undefined || self.socket.readyState != 'open') {
if ((self.socket === undefined || self.socket.readyState == 'closed') && readyToConnect()) {
startSocket();
}
offlineCache.push(data);
} else {
if (self.socket.socket.bufferSize > 0) {
offlineCache.push(data);
self.scheduleOfflineCacheChecking();
} else {
self.socket.write(data);
}
}
};
this.recheckOfflineCache = function() {
console.log("RECHECK");
if (offlineCache.length) {
self.writeNotificationToSocket(offlineCache.pop());
}
self.offlineCacheScheduler = undefined;
if (offlineCache.length) {
self.scheduleOfflineCacheChecking();
}
};
this.scheduleOfflineCacheChecking = function() {
if (!self.offlineCacheScheduler) {
self.offlineCacheScheduler = setTimeout(self.recheckOfflineCache.bind(self), options.writeTimeout);
}
};
this.sendNotification = function (note) {
var token = note.device.token;
var message = JSON.stringify(note);
@ -119,17 +169,8 @@ var Connection = function (optionArgs) {
pos += token.copy(data, pos, 0);
pos += int2buf(messageLength, data, pos, 2);
pos += data.write(message, pos);
// If error occurs then slice array and resend all stored notes.
if(self.socket === undefined || self.socket.readyState != 'open') {
if((self.socket === undefined || self.socket.readyState == 'closed') && readyToConnect()) {
startSocket();
}
offlineCache.push(data);
}
else {
self.socket.write(data);
}
this.writeNotificationToSocket(data);
}
var tidyCachedNotes = function() {