redis-spincycle
Version:
library tha connects to a spincycle server using redis pubsub
329 lines (305 loc) • 11.4 kB
JavaScript
// Generated by CoffeeScript 1.9.1
(function() {
var $q, debug, spinredis, uuid,
bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
uuid = require('node-uuid');
$q = require('node-promise');
debug = process.env['DEBUG'];
spinredis = (function() {
function spinredis(dbUrl) {
this.flattenModel = bind(this.flattenModel, this);
this.listTargets = bind(this.listTargets, this);
this.getModelFor = bind(this.getModelFor, this);
this.emitMessage = bind(this.emitMessage, this);
this._degisterObjectsSubscriber = bind(this._degisterObjectsSubscriber, this);
this.deRegisterObjectsSubscriber = bind(this.deRegisterObjectsSubscriber, this);
this.registerObjectsSubscriber = bind(this.registerObjectsSubscriber, this);
this.registerObjectsSubscriber = bind(this.registerObjectsSubscriber, this);
this.registerListener = bind(this.registerListener, this);
this.setup = bind(this.setup, this);
this.emit = bind(this.emit, this);
var rhost, rport;
this.subscribers = [];
this.objsubscribers = [];
this.objectsSubscribedTo = [];
this.outstandingMessages = [];
this.modelcache = [];
if (debug) {
console.log('redis-spincycle dbUrl = ' + dbUrl);
}
rhost = dbUrl || process.env['REDIS_PORT_6379_TCP_ADDR'] || '127.0.0.1';
rport = process.env['REDIS_PORT_6379_TCP_PORT'] || '6379';
this.sendredis = require('redis').createClient(rport, rhost);
this.listenredis = require('redis').createClient(rport, rhost);
this.listenredis.on('error', function(err) {
return console.log('spinredis listen ERROR: ' + err);
});
this.sendredis.on('error', function(err) {
return console.log('spinredis send ERROR: ' + err);
});
this.sessionId = null;
this.objectss = [];
this.subscribers['OBJECT_UPDATE'] = [
function(obj) {
var k, o, prop, ref, results, v, val;
this.subscribers = objsubscribers[obj.id] || [];
ref = this.subscribers;
results = [];
for (k in ref) {
v = ref[k];
if (!this.objectss[obj.id]) {
this.objectss[obj.id] = obj;
} else {
o = this.objectss[obj.id];
for (prop in obj) {
val = obj[prop];
o[prop] = val;
}
}
results.push(v(obj));
}
return results;
}
];
this.setup();
}
spinredis.prototype.failed = function(msg) {
return console.log('spinclient message failed!! ' + msg);
};
spinredis.prototype.setSessionId = function(id) {
if (id) {
console.log('++++++++++++++++++++++++++++++++++++++ spinclient setting session id to ' + id);
return this.sessionId = id;
}
};
spinredis.prototype.dumpOutstanding = function() {
console.log('-------------------------------- ' + this.outstandingMessages.length + ' outstanding messages ---------------------------------');
this.outstandingMessages.forEach(function(os) {
return console.log(os.messageId + ' -> ' + os.target + ' - ' + os.d);
});
return console.log('-----------------------------------------------------------------------------------------');
};
spinredis.prototype.emit = function(message) {
message.channelID = 'spinchannel_' + this.channelID;
if (debug) {
console.log('redisclient emitting message..');
}
if (debug) {
console.dir(message);
}
return this.sendredis.publish('spinchannel', JSON.stringify(message));
};
spinredis.prototype.setup = function() {
this.channelID = uuid.v4();
this.listenredis.subscribe('spinchannel_' + this.channelID);
return this.listenredis.on('message', (function(_this) {
return function(channel, replystr) {
var detail, i, index, info, message, reply, status;
console.log('on message got ' + replystr);
reply = JSON.parse(replystr);
status = reply.status;
message = reply.payload;
info = reply.info;
console.log('redis-spincycle got reply messageId ' + reply.messageId + ' status ' + status + ', info ' + info + ' data ' + message + ' outstandingMessages = ' + _this.outstandingMessages.length);
_this.dumpOutstanding();
index = -1;
if (reply.messageId) {
i = 0;
while (i < _this.outstandingMessages.length) {
detail = _this.outstandingMessages[i];
if (detail && detail.messageId === reply.messageId) {
if (reply.status === 'FAILURE' || reply.status === 'NOT_ALLOWED') {
console.log('spinclient message FAILURE');
console.dir(reply);
detail.d.reject(reply);
break;
} else {
detail.d.resolve(message);
index = i;
break;
}
}
i++;
}
if (index > -1) {
return _this.outstandingMessages.splice(index, 1);
}
} else {
_this.subscribers = _this.subscribers[info];
if (_this.subscribers) {
return _this.subscribers.forEach(function(listener) {
return listener(message);
});
} else {
console.log('no subscribers for message ' + message);
return console.dir(reply);
}
}
};
})(this));
};
spinredis.prototype.registerListener = function(detail) {
console.log('spinclient::registerListener called for ' + detail.message);
this.subscribers = this.subscribers[detail.message] || [];
this.subscribers.push(detail.callback);
return this.subscribers[detail.message] = this.subscribers;
};
spinredis.prototype.registerObjectsSubscriber = function(detail) {
var d, localsubs, sid;
d = $q.defer();
sid = uuid.v4();
localsubs = this.objectsSubscribedTo[detail.id];
console.log('register@objectsSubscriber localsubs is');
console.dir(localsubs);
if (!localsubs) {
localsubs = [];
console.log('no local subs, so get the original server-side subscription for id ' + detail.id);
this.registerObjectsSubscriber({
id: detail.id,
type: detail.type,
cb: function(updatedobj) {
var k, lsubs, results, v;
console.log('-- register@objectsSubscriber getting obj update callback for ' + detail.id);
lsubs = this.objectsSubscribedTo[detail.id];
results = [];
for (k in lsubs) {
v = lsubs[k];
if (v.cb) {
console.log('--*****--*****-- calling back @objects update to local sid --****--*****-- ' + k);
results.push(v.cb(updatedobj));
} else {
results.push(void 0);
}
}
return results;
}
}).then((function(_this) {
return function(remotesid) {
localsubs['remotesid'] = remotesid;
localsubs[sid] = detail;
console.log('-- adding local callback listener to @objects updates for ' + detail.id + ' local sid = ' + sid + ' remotesid = ' + remotesid);
_this.objectsSubscribedTo[detail.id] = localsubs;
return d.resolve(sid);
};
})(this));
}
return d.promise;
};
spinredis.prototype.registerObjectsSubscriber = function(detail) {
var d;
d = $q.defer();
console.log('message-router registering subscriber for @objects ' + detail.id + ' type ' + detail.type);
this.subscribers = this.objsubscribers[detail.id] || [];
this.emitMessage({
target: 'registerForUpdatesOn',
obj: {
id: detail.id,
type: detail.type
}
}).then((function(_this) {
return function(reply) {
console.log('server subscription id for id ' + detail.id + ' is ' + reply);
_this.subscribers[reply] = detail.cb;
_this.objsubscribers[detail.id] = _this.subscribers;
return d.resolve(reply);
};
})(this), (function(_this) {
return function(reply) {
return _this.failed(reply);
};
})(this));
return d.promise;
};
spinredis.prototype.deRegisterObjectsSubscriber = function(sid, o) {
var count, j, k, len, localsubs, v;
localsubs = this.objectssSubscribedTo[o.id] || [];
if (localsubs[sid]) {
console.log('deregistering local updates for @objects ' + o.id);
delete localsubs[sid];
count = 0;
for (v = j = 0, len = localsubs.length; j < len; v = ++j) {
k = localsubs[v];
count++;
}
if (count === 1) {
return this._deRegisterObjectsSubscriber('remotesid', o);
}
}
};
spinredis.prototype._degisterObjectsSubscriber = function(sid, o) {
this.subscribers = this.objsubscribers[o.id] || [];
if (this.subscribers && this.subscribers[sid]) {
delete this.subscribers[sid];
this.objsubscribers[o.id] = this.subscribers;
return this.emitMessage({
target: 'deRegisterForUpdatesOn',
id: o.id,
type: o.type,
listenerid: sid
}).then(function(reply) {
return console.log('deregistering server updates for @objects ' + o.id);
});
}
};
spinredis.prototype.emitMessage = function(detail) {
var d;
if (debug) {
console.log('emitMessage called');
}
d = $q.defer();
detail.messageId = uuid.v4();
detail.sessionId = detail.sessionId || this.sessionId;
detail.d = d;
this.outstandingMessages.push(detail);
if (debug) {
console.log('saving outstanding reply to messageId ' + detail.messageId + ' and @sessionId ' + detail.sessionId);
}
this.emit(detail);
return d.promise;
};
spinredis.prototype.getModelFor = function(type) {
var d;
d = $q.defer();
if (this.modelcache[type]) {
d.resolve(this.modelcache[type]);
} else {
this.emitMessage({
target: 'getModelFor',
modelname: type
}).then(function(model) {
this.modelcache[type] = model;
return d.resolve(model);
});
}
return d.promise;
};
spinredis.prototype.listTargets = function() {
var d;
d = $q.defer();
this.emitMessage({
target: 'listcommands'
}).then(function(targets) {
return d.resolve(targets);
});
return d.promise;
};
spinredis.prototype.flattenModel = function(model) {
var k, rv, v;
rv = {};
for (k in model) {
v = model[k];
if (angular.isArray(v)) {
rv[k] = v.map(function(e) {
return e.id;
});
} else {
rv[k] = v;
}
}
return rv;
};
return spinredis;
})();
module.exports = spinredis;
}).call(this);
//# sourceMappingURL=spinredis.js.map