redis-spincycle
Version:
library tha connects to a spincycle server using redis pubsub
220 lines (188 loc) • 7.78 kB
text/coffeescript
uuid = require('node-uuid')
$q = require('node-promise')
debug = process.env['DEBUG']
class spinredis
constructor: (dbUrl) ->
= []
= []
= []
= []
= []
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'
= require('redis').createClient(rport, rhost)
= require('redis').createClient(rport, rhost)
.on 'error', (err) ->
console.log 'spinredis listen ERROR: '+err
.on 'error', (err) ->
console.log 'spinredis send ERROR: '+err
= null
= []
['OBJECT_UPDATE'] = [ (obj) ->
#console.log 'spinclient +++++++++ obj update message router got obj'
#console.dir(obj);
= objsubscribers[obj.id] or []
for k,v of
#console.log 'updating subscriber to @objects updates on id '+k
if not [obj.id]
[obj.id] = obj
else
o = [obj.id]
for prop, val of obj
o[prop] = val
v obj
]
failed: (msg)->
console.log 'spinclient message failed!! '+msg
setSessionId: (id) ->
if(id)
console.log '++++++++++++++++++++++++++++++++++++++ spinclient setting session id to '+id
= id
dumpOutstanding: ()->
console.log '-------------------------------- '+.length+' outstanding messages ---------------------------------'
.forEach (os)->
console.log os.messageId+' -> '+os.target+' - '+os.d
console.log '-----------------------------------------------------------------------------------------'
emit: (message) =>
message.channelID = 'spinchannel_'+
if debug then console.log 'redisclient emitting message..'
if debug then console.dir message
.publish('spinchannel', JSON.stringify(message))
setup: () =>
= uuid.v4()
.subscribe('spinchannel_'+)
.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 = '+.length
#console.dir reply
index = -1
if reply.messageId
i = 0
while i < .length
detail = [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'
.splice index, 1
else
= [info]
if
.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
= [detail.message] or []
.push detail.callback
[detail.message] =
registerObjectsSubscriber: (detail) =>
d = $q.defer()
sid = uuid.v4()
localsubs = [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
.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
[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
= [detail.id] or []
.then(
(reply)=>
console.log 'server subscription id for id '+detail.id+' is '+reply
[reply] = detail.cb
[detail.id] =
d.resolve(reply)
,(reply)=>
)
return d.promise
deRegisterObjectsSubscriber: (sid, o) =>
localsubs = [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
_degisterObjectsSubscriber: (sid, o) =>
= [o.id] or []
if and [sid]
delete [sid]
[o.id] =
.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
detail.d = d
.push detail
if debug then console.log 'saving outstanding reply to messageId '+detail.messageId+' and @sessionId '+detail.sessionId
detail
return d.promise
# ------------------------------------------------------------------------------------------------------------------
getModelFor: (type) =>
d = $q.defer()
if [type]
d.resolve([type])
else
.then((model)->
[type] = model
d.resolve(model))
return d.promise
listTargets: () =>
d = $q.defer()
.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