Skip to content

Commit

Permalink
tests pass; update web chatting to return all pending messages
Browse files Browse the repository at this point in the history
  • Loading branch information
evantahler committed Jan 12, 2013
1 parent d7f1ba9 commit 0e4bd67
Show file tree
Hide file tree
Showing 10 changed files with 67 additions and 129 deletions.
9 changes: 6 additions & 3 deletions actions/chat.js
Expand Up @@ -23,7 +23,7 @@ action.outputExample = {
/////////////////////////////////////////////////////////////////////
// functional
action.run = function(api, connection, next){
if(connection.type == "web"){
if(connection.type == "web" && api.configData.commonWeb.httpClientMessageTTL != null){
if (connection.params.method == "roomView"){
api.chatRoom.socketRoomStatus(connection.room, function(err, roomStatus){
connection.response.roomStatus = roomStatus;
Expand All @@ -46,14 +46,17 @@ action.run = function(api, connection, next){
}
next(connection, true);
}else if(connection.params.method == "messages"){
api.webServer.getWebChatMessage(connection, function(err, message){
connection.response.message = message;
api.webServer.getWebChatMessage(connection, function(err, messages){
connection.response.messages = messages;
next(connection, true);
});
}else{
connection.error = new Error(connection.params.method + " is not a known chat method");
next(connection, true);
}
}else if(connection.type == "web" && api.configData.commonWeb.httpClientMessageTTL == null){
connection.error = new Error("chatting via web clients is not enabled");
next(connection, true);
}else{
connection.error = new Error("this action is only for web clients; use your proticol's native methods");
next(connection, true);
Expand Down
1 change: 1 addition & 0 deletions initializers/chatRooms.js
Expand Up @@ -22,6 +22,7 @@ var chatRooms = function(api, next){
var payload = {
message: message,
connection: {
id: connection.id,
room: connection.room,
roomMatchKey: connection.roomMatchKey,
roomMatchValue: connection.roomMatchValue,
Expand Down
7 changes: 6 additions & 1 deletion initializers/connections.js
Expand Up @@ -5,6 +5,7 @@ var connections = function(api, next){
api.connections = {}

// {type: type, remotePort: remotePort, remoteIP: remoteIP, rawConnection: rawConnection}
// id is optional
api.connection = function(data){
this.setup(data)
this.joinRoomOnConnect();
Expand All @@ -13,7 +14,11 @@ var connections = function(api, next){

api.connection.prototype.setup = function(data){
var self = this;
self.id = self.generateID();
if(data.id != null){
self.id = data.id;
}else{
self.id = self.generateID();
}
self.connectedAt = new Date().getTime();
['type', 'remotePort', 'remoteIP', 'rawConnection'].forEach(function(req){
if(data[req] == null){ throw new Error(req + ' is required to create a new connection object'); }
Expand Down
10 changes: 7 additions & 3 deletions initializers/socketServer.js
Expand Up @@ -88,7 +88,7 @@ var socketServer = function(api, next){

connection.rawConnection.on("error", function(e){
api.log("socket error: " + e, "red");
connection.end();
connection.rawConnection.end();
});

};
Expand Down Expand Up @@ -161,7 +161,8 @@ var socketServer = function(api, next){
}else if(words[0] == "detailsView"){
var details = {};
details.params = connection.params;
details.public = connection.public;
details.id = connection.id;
details.connectedAt = connection.connectedAt;
details.room = connection.room;
details.totalActions = connection.totalActions;
details.pendingActions = connection.pendingActions;
Expand Down Expand Up @@ -297,6 +298,9 @@ var socketServer = function(api, next){
api.socketServer.gracefulShutdown = function(next, alreadyShutdown){
if(alreadyShutdown == null){alreadyShutdown = false;}
if(alreadyShutdown == false){
for(var i in api.connections){
if(api.connections[i].type == 'socket'){ api.chatRoom.roomRemoveMember(api.connections[i]) }
}
api.socketServer.server.close();
alreadyShutdown = true;
}
Expand All @@ -305,7 +309,7 @@ var socketServer = function(api, next){
var connection = api.connections[i];
if(connection.type == "socket"){
if (connection.responsesWaitingCount == 0){
connection.end(JSON.stringify({status: "Bye!", context: "response", reason: 'server shutdown'}) + "\r\n");
connection.rawConnection.end(JSON.stringify({status: "Bye!", context: "response", reason: 'server shutdown'}) + "\r\n");
}else{
pendingConnections++;
// hard shutdown in 5 seconds
Expand Down
39 changes: 22 additions & 17 deletions initializers/webServer.js
Expand Up @@ -35,6 +35,11 @@ var webServer = function(api, next){

api.webServer._teardown = function(api, next){
api.webServer.stopTimers(api);
if(api.configData.commonWeb.httpClientMessageTTL != null){
for(var i in api.connections){
if(api.connections[i].type == 'web'){ api.chatRoom.roomRemoveMember(api.connections[i]) }
}
}
if(api.configData.webSockets.enable != true){
api.webServer.server.close();
}
Expand All @@ -55,15 +60,14 @@ var webServer = function(api, next){
});
}

api.webServer.decorateConnection = function(connection, fingerprint, cookieHash){
api.webServer.decorateConnection = function(connection, cookieHash){
var responseHeaders = [];
for(var i in cookieHash){
responseHeaders.push([i, cookieHash[i]]);
}
responseHeaders.push(['Content-Type', "application/json"]);
responseHeaders.push(['X-Powered-By', api.configData.general.serverName]);

connection.fingerprint = fingerprint;
connection.responseHeaders = responseHeaders;
connection.method = connection.rawConnection.req.method;
connection.cookies = api.utils.parseCookies(connection.rawConnection.req);
Expand All @@ -74,14 +78,15 @@ var webServer = function(api, next){
browser_fingerprint.fingerprint(req, api.configData.commonWeb.fingerprintOptions, function(fingerprint, elementHash, cookieHash){
var connection = new api.connection({
type: 'web',
id: fingerprint,
remotePort: req.connection.remotePort,
remoteIP: req.connection.remoteAddress,
rawConnection: {
req: req,
res: res,
},
});
api.webServer.decorateConnection(connection, fingerprint, cookieHash);
api.webServer.decorateConnection(connection, cookieHash);
api.stats.increment("webServer:numberOfWebRequests");

if(connection.cookies[api.webServer.roomCookieKey] != null){
Expand Down Expand Up @@ -159,7 +164,7 @@ var webServer = function(api, next){
}

if(connection.requestMode == 'public'){
fillParamsFromWebRequest(connection, connection.parsedURL.query);
api.webServer.fillParamsFromWebRequest(connection, connection.parsedURL.query);
process.nextTick(function(){ api.sendFile(connection, api.webServer.respondToWebClient); })
}
});
Expand Down Expand Up @@ -324,23 +329,23 @@ var webServer = function(api, next){
api.webServer.getWebChatMessage = function(connection, next){
if(api.redis.enable === true){
var rediskey = 'actionHero:webMessages:' + connection.id;
api.redis.client.lpop(rediskey, function(err, message){
if(message != null){
var parsedMessage = JSON.parse(message);
if(parsedMessage == []){ parsedMessage = null; }
next(null, parsedMessage);
}else{
next(null, null);
}
var messages = [];
api.redis.client.lrange(rediskey, 0, -1, function(err, redisMessages){
api.redis.client.del(rediskey, function(){
for(var i in redisMessages){
messages.push(JSON.parse(redisMessages[i]));
}
next(null, messages);
});
});
}else{
var store = api.webServer.webChatMessages[connection.id];
if(store == null){
next(null, null);
}else{
var message = store.splice(0,1);
next(null, message);
var messages = [];
for(var i in store){
messages.push(store[i]);
}
delete api.webServer.webChatMessages[connection.id];
next(null, messages);
}
}

Expand Down
6 changes: 5 additions & 1 deletion initializers/webSocketServer.js
Expand Up @@ -68,6 +68,9 @@ var webSocketServer = function(api, next){
}

api.webSockets._teardown = function(api, next){
for(var i in api.connections){
if(api.connections[i].type == 'webSocket'){ api.chatRoom.roomRemoveMember(api.connections[i]) }
}
api.webSockets.disconnectAll(function(){
api.webServer.server.close();
next();
Expand Down Expand Up @@ -159,7 +162,8 @@ var webSocketServer = function(api, next){
if(data == null){ data = {}; }
var details = {};
details.params = connection.params;
details.public = connection.public;
details.id = connection.id;
details.connectedAt = connection.connectedAt;
details.room = connection.room;
details.totalActions = connection.totalActions;
details.pendingActions = connection.pendingActions;
Expand Down
35 changes: 12 additions & 23 deletions test/action_chat.js
Expand Up @@ -16,18 +16,6 @@ describe('Action: chat', function(){
done();
});

clientID = null;

describe('basics', function(){
it('I can my chat details', function(done){
specHelper.apiTest.get('/chat/?method=detailsView', 0, {}, function(response){
console.log(response.body)
clientID = response.body.details.id
done();
});
});
});

describe('should be off', function(){
it('messages should not be saved when httpClientMessageTTL is null', function(done){
apiObj.chatRoom.socketRoomBroadcast(apiObj, {room: 'defaultRoom'}, "TEST");
Expand All @@ -42,9 +30,14 @@ describe('Action: chat', function(){

describe('should be on', function(){

var clientID = null;

before(function(done){
apiObj.configData.commonWeb.httpClientMessageTTL = 10000;
done();
specHelper.apiTest.get('/chat/?method=detailsView', 0, {}, function(response){
clientID = response.body.details.id
done();
});
});

it('I can my room details', function(done){
Expand Down Expand Up @@ -83,26 +76,22 @@ describe('Action: chat', function(){
apiObj.chatRoom.socketRoomBroadcast({room: 'defaultRoom'}, "TEST");
setTimeout(function(){
specHelper.apiTest.get('/chat/?method=messages', 0, {}, function(response){
response.body.message.message.should.equal("TEST");
response.body.messages[0].message.should.equal("TEST");
done();
});
}, 50);
});

it('I should get queued messages from other clients', function(done){
it('I can get many messagse and the order is maintained', function(done){
apiObj.chatRoom.socketRoomBroadcast({room: 'defaultRoom'}, "TEST: A");
apiObj.chatRoom.socketRoomBroadcast({room: 'defaultRoom'}, "TEST: B");
apiObj.chatRoom.socketRoomBroadcast({room: 'defaultRoom'}, "TEST: C");
setTimeout(function(){
specHelper.apiTest.get('/chat/?method=messages', 0, {}, function(response){
response.body.message.message.should.equal("TEST: A");
specHelper.apiTest.get('/chat/?method=messages', 0, {}, function(response){
response.body.message.message.should.equal("TEST: B");
specHelper.apiTest.get('/chat/?method=messages', 0, {}, function(response){
response.body.message.message.should.equal("TEST: C");
done();
});
});
response.body.messages[0].message.should.equal("TEST: A");
response.body.messages[1].message.should.equal("TEST: B");
response.body.messages[2].message.should.equal("TEST: C");
done();
});
}, 50);
});
Expand Down
74 changes: 0 additions & 74 deletions test/action_file.js

This file was deleted.

0 comments on commit 0e4bd67

Please sign in to comment.