UNPKG

redis-spincycle

Version:

library tha connects to a spincycle server using redis pubsub

220 lines (188 loc) 7.78 kB
uuid = require('node-uuid') $q = require('node-promise') debug = process.env['DEBUG'] class spinredis constructor: (dbUrl) -> @subscribers = [] @objsubscribers = [] @objectsSubscribedTo = [] @outstandingMessages = [] @modelcache = [] if debug then console.log 'redis-spincycle dbUrl = '+dbUrl rhost = dbUrl or process.env['REDIS_PORT_6379_TCP_ADDR'] or '127.0.0.1' rport = process.env['REDIS_PORT_6379_TCP_PORT'] or '6379' @sendredis = require('redis').createClient(rport, rhost) @listenredis = require('redis').createClient(rport, rhost) @listenredis.on 'error', (err) -> console.log 'spinredis listen ERROR: '+err @sendredis.on 'error', (err) -> console.log 'spinredis send ERROR: '+err @sessionId = null @objectss = [] @subscribers['OBJECT_UPDATE'] = [ (obj) -> #console.log 'spinclient +++++++++ obj update message router got obj' #console.dir(obj); @subscribers = objsubscribers[obj.id] or [] for k,v of @subscribers #console.log 'updating subscriber to @objects updates on id '+k if not @objectss[obj.id] @objectss[obj.id] = obj else o = @objectss[obj.id] for prop, val of obj o[prop] = val v obj ] @setup() failed: (msg)-> console.log 'spinclient message failed!! '+msg setSessionId: (id) -> if(id) console.log '++++++++++++++++++++++++++++++++++++++ spinclient setting session id to '+id @sessionId = id dumpOutstanding: ()-> console.log '-------------------------------- '+@outstandingMessages.length+' outstanding messages ---------------------------------' @outstandingMessages.forEach (os)-> console.log os.messageId+' -> '+os.target+' - '+os.d console.log '-----------------------------------------------------------------------------------------' emit: (message) => message.channelID = 'spinchannel_'+@channelID if debug then console.log 'redisclient emitting message..' if debug then console.dir message @sendredis.publish('spinchannel', JSON.stringify(message)) setup: () => @channelID = uuid.v4() @listenredis.subscribe('spinchannel_'+@channelID) @listenredis.on 'message', (channel, replystr) => 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 = '+@outstandingMessages.length @dumpOutstanding() #console.dir reply index = -1 if reply.messageId i = 0 while i < @outstandingMessages.length detail = @outstandingMessages[i] if detail and detail.messageId == reply.messageId if reply.status == 'FAILURE' or reply.status == 'NOT_ALLOWED' console.log 'spinclient message FAILURE' console.dir reply detail.d.reject reply break else #console.log 'delivering message '+message+' reply to '+detail.target+' to '+reply.messageId detail.d.resolve(message) index = i break i++ if index > -1 #console.log 'removing outstanding reply' @outstandingMessages.splice index, 1 else @subscribers = @subscribers[info] if @subscribers @subscribers.forEach (listener) -> #console.log("sending reply to listener"); listener message else console.log 'no subscribers for message ' + message console.dir reply registerListener: (detail) => console.log 'spinclient::registerListener called for '+detail.message @subscribers = @subscribers[detail.message] or [] @subscribers.push detail.callback @subscribers[detail.message] = @subscribers registerObjectsSubscriber: (detail) => d = $q.defer() sid = uuid.v4() localsubs = @objectsSubscribedTo[detail.id] console.log 'register@objectsSubscriber localsubs is' console.dir localsubs if not localsubs localsubs = [] console.log 'no local subs, so get the original server-side subscription for id '+detail.id # actually set up subscription, once for each @objects @registerObjectsSubscriber({id: detail.id, type: detail.type, cb: (updatedobj) -> console.log '-- register@objectsSubscriber getting obj update callback for '+detail.id lsubs = @objectsSubscribedTo[detail.id] #console.dir(lsubs) for k,v of lsubs if (v.cb) console.log '--*****--*****-- calling back @objects update to local sid --****--*****-- '+k v.cb updatedobj }).then (remotesid) => localsubs['remotesid'] = remotesid localsubs[sid] = detail console.log '-- adding local callback listener to @objects updates for '+detail.id+' local sid = '+sid+' remotesid = '+remotesid @objectsSubscribedTo[detail.id] = localsubs d.resolve(sid) return d.promise registerObjectsSubscriber: (detail) => d = $q.defer() console.log 'message-router registering subscriber for @objects ' + detail.id + ' type ' + detail.type @subscribers = @objsubscribers[detail.id] or [] @emitMessage({target: 'registerForUpdatesOn', obj: {id: detail.id, type: detail.type} }).then( (reply)=> console.log 'server subscription id for id '+detail.id+' is '+reply @subscribers[reply] = detail.cb @objsubscribers[detail.id] = @subscribers d.resolve(reply) ,(reply)=> @failed(reply) ) return d.promise deRegisterObjectsSubscriber: (sid, o) => localsubs = @objectssSubscribedTo[o.id] or [] if localsubs[sid] console.log 'deregistering local updates for @objects '+o.id delete localsubs[sid] count = 0 for k,v in localsubs count++ if count == 1 # only remotesid property left @_deRegisterObjectsSubscriber('remotesid', o) _degisterObjectsSubscriber: (sid, o) => @subscribers = @objsubscribers[o.id] or [] if @subscribers and @subscribers[sid] delete @subscribers[sid] @objsubscribers[o.id] = @subscribers @emitMessage({target: 'deRegisterForUpdatesOn', id:o.id, type: o.type, listenerid: sid } ).then (reply)-> console.log 'deregistering server updates for @objects '+o.id emitMessage : (detail) => if debug then console.log 'emitMessage called' #console.dir detail d = $q.defer() detail.messageId = uuid.v4() detail.sessionId = detail.sessionId or @sessionId detail.d = d @outstandingMessages.push detail if debug then console.log 'saving outstanding reply to messageId '+detail.messageId+' and @sessionId '+detail.sessionId @emit detail return d.promise # ------------------------------------------------------------------------------------------------------------------ getModelFor: (type) => d = $q.defer() if @modelcache[type] d.resolve(@modelcache[type]) else @emitMessage({target:'getModelFor', modelname: type}).then((model)-> @modelcache[type] = model d.resolve(model)) return d.promise listTargets: () => d = $q.defer() @emitMessage({target:'listcommands'}).then((targets)-> d.resolve(targets)) return d.promise flattenModel: (model) => rv = {} for k,v of model if angular.isArray(v) rv[k] = v.map (e) -> e.id else rv[k] = v return rv module.exports = spinredis