-
Notifications
You must be signed in to change notification settings - Fork 2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Building a Real-Time Activity Stream on Cloud Foundry with Node.js, Redis and MongoDB--Part II #1
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,37 +1,136 @@ | ||
module.exports = function Server(expressInstance, sessionStore) { | ||
var parseCookie = require('connect').utils.parseCookie; | ||
var io = require('socket.io').listen(expressInstance); | ||
var asmsServer = expressInstance.asmsDB; | ||
var thisApp = expressInstance.thisApp; | ||
var thisInstance = expressInstance.thisInstance; | ||
|
||
io.configure(function () { | ||
io.set('log level', 0); | ||
}); | ||
|
||
io.set('authorization', function(handshakeData, ack) { | ||
var cookies = parseCookie(handshakeData.headers.cookie); | ||
sessionStore.get(cookies['connect.sid'], function(err, sessionData) { | ||
sessionStore.get(cookies[expressInstance.cookieName], function(err, sessionData) { | ||
handshakeData.session = sessionData || {}; | ||
handshakeData.sid = cookies['connect.sid']|| null; | ||
handshakeData.sid = cookies[expressInstance.cookieName]|| null; | ||
ack(err, err ? false : true); | ||
}); | ||
}); | ||
|
||
io.sockets.on('connection', function(client) { | ||
var user = client.handshake.session.user ? client.handshake.session.user.name : 'UID: '+(client.handshake.session.uid || 'has no UID'); | ||
|
||
var desiredStream = "firehose"; | ||
|
||
if (client.handshake.session && client.handshake.session.desiredStream) { | ||
desiredStream = client.handshake.session.desiredStream; | ||
} | ||
|
||
// Join user specific channel, this is good so content is send across user tabs. | ||
client.join(client.handshake.sid); | ||
|
||
client.send('welcome: '+user); | ||
|
||
client.on('message', function(msg) { | ||
// Send back the message to the users room. | ||
io.sockets.in(client.handshake.sid).send('socket.io relay message "'+msg+'" from: '+ user +' @ '+new Date().toString().match(/[0-9]+:[0-9]+:[0-9]+/)); | ||
var avatarUrl = (client.handshake.session.auth && client.handshake.session.user && client.handshake.session.user.image) ? client.handshake.session.user.image : '/img/codercat-sm.jpg'; | ||
var currentUser = {displayName: user, image: {url: avatarUrl}}; | ||
|
||
|
||
console.log("Subscribing " + user); | ||
|
||
asmsServer.subscribe(desiredStream, function(channel, json) { | ||
client.send(json); | ||
}); | ||
|
||
var cf_provider; | ||
var provider = new asmsServer.ActivityObject({'displayName': 'The Internet', icon: {url: ''}}); | ||
if (client.handshake.session.auth) { | ||
if (client.handshake.session.auth.github) { | ||
provider.displayName = 'GitHub'; | ||
provider.icon.url = 'http://github.com/favicon.ico'; | ||
} else if (client.handshake.session.auth.facebook) { | ||
provider.displayName = 'Facebook'; | ||
provider.icon = {url: 'http://facebook.com/favicon.ico'}; | ||
} else if (client.handshake.session.auth.twitter) { | ||
provider.displayName = 'Twitter'; | ||
provider.icon = {url: 'http://twitter.com/favicon.ico'}; | ||
} | ||
} | ||
provider.save(function(err) { | ||
if (err == null) { | ||
var cf_provider = new asmsServer.ActivityObject({'displayName': 'Cloud Foundry', icon:{url: 'http://www.cloudfoundry.com/images/favicon.ico'}}); | ||
cf_provider.save(function(err) { | ||
if (err == null) { | ||
if (client.handshake.session && client.handshake.session.auth && client.handshake.session.user) { | ||
var act = new asmsServer.Activity({ | ||
id: 1, | ||
actor: currentUser, | ||
verb: 'connect', | ||
object: thisInstance, | ||
target: thisApp, | ||
title: "connected to", | ||
provider: provider, | ||
generator: cf_provider | ||
}); | ||
asmsServer.publish(desiredStream, act); | ||
} else { | ||
console.log("We don't have a user name so don't raise an activity"); | ||
console.dir(client.handshake.session.user); | ||
} | ||
|
||
} else { | ||
console.log("Got error publishing welcome message") | ||
} | ||
}); | ||
} | ||
}); | ||
|
||
|
||
|
||
client.on('message', function(message) { | ||
var actHash = { | ||
actor: currentUser, | ||
verb: 'post', | ||
object: {objectType: "note", content: message, displayName: ""}, | ||
target: thisApp, | ||
provider: provider, | ||
generator: cf_provider | ||
} | ||
|
||
if (actHash.verb == "post") { | ||
actHash.title = "posted a " + actHash.object.objectType; | ||
|
||
} | ||
|
||
var act = new asmsServer.Activity(actHash); | ||
// Send back the message to the users room. | ||
asmsServer.publish(desiredStream, act); | ||
}); | ||
|
||
client.on('disconnect', function() { console.log('disconnect'); }); | ||
client.on('disconnect', function() { | ||
console.log('********* disconnect'); | ||
asmsServer.unsubscribe(desiredStream); | ||
console.log("unsubscribed from firehose"); | ||
|
||
if (client.handshake.session.user && client.handshake.session.user.name) { | ||
asmsServer.publish(desiredStream, new asmsServer.Activity({ | ||
actor: currentUser, | ||
verb: 'disconnect', | ||
object: thisInstance, | ||
target: thisApp, | ||
title: "disconnected from", | ||
provider: provider, | ||
generator: cf_provider | ||
})); | ||
|
||
|
||
} else { | ||
console.log("User disconnected"); | ||
console.dir(client.handshake); | ||
} | ||
}); | ||
}); | ||
|
||
io.sockets.on('error', function(){ console.log(arguments); }); | ||
|
||
return io; | ||
}; | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,6 +6,9 @@ | |
"engines" : ["node"], | ||
"repository" : { "type":"git", "url":"http://github.com/mape/node-express-boilerplate" }, | ||
"dependencies" : { | ||
"activity-streams-mongoose": ">=0.0.11", | ||
"mongoose": "", | ||
"underscore": "", | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Run |
||
"cloudfoundry": ">=0.1.0", | ||
"connect" : ">=1.6.0", | ||
"connect-assetmanager" : ">=0.0.21", | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -23,24 +23,43 @@ | |
$$('#connected').addClass('on').find('strong').text('Online'); | ||
}); | ||
|
||
var image = $.trim($('#image').val()); | ||
var service = $.trim($('#service').val()); | ||
socketIoClient.on('message', function(msg) { | ||
var $li = $('<li>').text(msg).append($('<img class="avatar">').attr('src', image)); | ||
if (service) { | ||
$li.append($('<img class="service">').attr('src', service)); | ||
} | ||
$$('#bubble ul').prepend($li); | ||
$$('#bubble').scrollTop(98).stop().animate({ | ||
'scrollTop': '0' | ||
}, 500); | ||
setTimeout(function() { | ||
$li.remove(); | ||
}, 5000); | ||
|
||
setTimeout(function() { | ||
socketIoClient.send('pong'); | ||
}, 1000); | ||
socketIoClient.on('message', function(json) { | ||
var doc = JSON.parse(json); | ||
if (doc) { | ||
var msg = doc.actor.displayName + " " + doc.title + " " + doc.object.displayName; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Now we have a full activity so we can use its properties to build a more meaningful message On Part 3 we will see how to use |
||
if (doc.target) { | ||
msg+= " in " + doc.target.displayName; | ||
} | ||
if (doc.generator) { | ||
msg+= " via " + doc.generator.displayName; | ||
} | ||
|
||
if (doc.object && doc.object.content) { | ||
msg+= ": " + doc.object.content; | ||
} | ||
|
||
var $li = $('<li>').text(msg).append($('<img class="avatar">').attr('src', doc.actor.image.url)); | ||
if (doc.provider && doc.provider.icon && doc.provider.icon.url) { | ||
$li.append($('<img class="service">').attr('src', doc.provider.icon.url)); | ||
} | ||
$$('#stream ul').prepend($li); | ||
$$('#bubble').scrollTop(98).stop().animate({ | ||
'scrollTop': '0' | ||
}, 5000); | ||
setTimeout(function() { | ||
$li.remove(); | ||
}, 5000); | ||
|
||
if (doc.verb == "connect") { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Doing something semi interesting with the different activities |
||
setTimeout(function() { | ||
socketIoClient.send('Ok great news !'); | ||
}, 1000); | ||
} else { | ||
setTimeout(function() { | ||
socketIoClient.send('I am still here'); | ||
}, 10000); | ||
} | ||
} | ||
}); | ||
|
||
socketIoClient.on('disconnect', function() { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Avoid memory leaks by unsubscribing from Redis