Per-RPC retry support, used when subscribe() can't find an active instance.

This commit is contained in:
Ian Gulliver
2014-05-23 15:32:31 -07:00
parent ba82bf3dee
commit 1e91f5babb
2 changed files with 18 additions and 8 deletions

9
api.py
View File

@@ -27,10 +27,6 @@ from cosmopolite.lib import utils
import config import config
class InvalidInstanceID(Exception):
pass
def CreateChannel(google_user, client, instance_id, args): def CreateChannel(google_user, client, instance_id, args):
models.Instance.FindOrCreate(instance_id) models.Instance.FindOrCreate(instance_id)
@@ -84,7 +80,10 @@ def SendMessage(google_user, client, instance_id, args):
def Subscribe(google_user, client, instance_id, args): def Subscribe(google_user, client, instance_id, args):
instance = models.Instance.FromID(instance_id) instance = models.Instance.FromID(instance_id)
if not instance or not instance.active: if not instance or not instance.active:
raise InvalidInstanceID # Probably a race with the channel opening
return {
'result': 'retry',
}
subject = models.Subject.FindOrCreate(args['subject']) subject = models.Subject.FindOrCreate(args['subject'])
messages = args.get('messages', 0) messages = args.get('messages', 0)

View File

@@ -469,7 +469,7 @@ Cosmopolite.prototype.sendRPCs_ = function(commands, delay) {
var xhr = new XMLHttpRequest(); var xhr = new XMLHttpRequest();
xhr.responseType = 'json'; xhr.responseType = 'json';
var retryAfterDelay = function() { var retryAfterDelay = function(newCommands) {
var intDelay = var intDelay =
xhr.getResponseHeader('Retry-After') || xhr.getResponseHeader('Retry-After') ||
Math.min(32, Math.max(2, delay || 2)); Math.min(32, Math.max(2, delay || 2));
@@ -477,14 +477,14 @@ Cosmopolite.prototype.sendRPCs_ = function(commands, delay) {
this.loggingPrefix_(), this.loggingPrefix_(),
'RPC failed; will retry in ' + intDelay + ' seconds'); 'RPC failed; will retry in ' + intDelay + ' seconds');
var retry = function() { var retry = function() {
this.sendRPCs_(commands, Math.pow(intDelay, 2)); this.sendRPCs_(newCommands, Math.pow(intDelay, 2));
}.bind(this); }.bind(this);
window.setTimeout(retry, intDelay * 1000); window.setTimeout(retry, intDelay * 1000);
}.bind(this); }.bind(this);
xhr.addEventListener('load', function(e) { xhr.addEventListener('load', function(e) {
if (xhr.status != 200) { if (xhr.status != 200) {
retryAfterDelay(); retryAfterDelay(commands);
return; return;
} }
var data = xhr.response; var data = xhr.response;
@@ -517,11 +517,22 @@ Cosmopolite.prototype.sendRPCs_ = function(commands, delay) {
// data. // data.
data['events'].forEach(this.onServerEvent_, this); data['events'].forEach(this.onServerEvent_, this);
var retryCommands = [];
for (var i = 0; i < data['responses'].length; i++) { for (var i = 0; i < data['responses'].length; i++) {
var response = data['responses'][i];
if (response['result'] == 'retry') {
retryCommands.push(commands[i]);
continue;
}
if (commands[i]['onSuccess']) { if (commands[i]['onSuccess']) {
commands[i]['onSuccess'].bind(this)(data['responses'][i]); commands[i]['onSuccess'].bind(this)(data['responses'][i]);
} }
} }
if (retryCommands.length) {
retryAfterDelay(retryCommands);
}
}.bind(this)); }.bind(this));
xhr.addEventListener('error', retryAfterDelay); xhr.addEventListener('error', retryAfterDelay);