Skip to content
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

BOT-296/Server Modules #313

Merged
merged 81 commits into from
Aug 23, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
81 commits
Select commit Hold shift + click to select a range
f640db5
Globally create socket.
Jul 8, 2017
91e9877
Test routing logic for supported and unsupported clients.
Jul 8, 2017
8429ad8
Add test for disconnection.
Jul 8, 2017
cae02eb
Collapse requires into a single var.
Jul 8, 2017
36bdc1f
Add bot locator into server and test.
Jul 8, 2017
56c039d
Add debug logging to logging client.
Jul 8, 2017
3f68123
Add debug logging to logging client.
Jul 8, 2017
3ccdb93
Merge branch 'BOT-296/socket_io_client' of github.com:novoda/spikes i…
Jul 8, 2017
8350798
Fix error.
Jul 8, 2017
47b8ff5
Extract routing logic to collaborator.
Jul 9, 2017
2fdc4db
Create a server each time for tests using Creator, rather than invali…
Jul 9, 2017
10bc3c3
Move dependencies out of create method.
Jul 9, 2017
b4be0fa
Extract get operations from server create.
Jul 9, 2017
7cb6bee
Hide dependencies in constructor.
Jul 9, 2017
dc75c12
Pass true or false to staticBotLocator to determine returning a usefu…
Jul 9, 2017
243e82e
Add test router.
Jul 9, 2017
cb3ae5e
Fix production server failure. Allow server to create router and botL…
Jul 9, 2017
d7fac41
Inline router.
Jul 9, 2017
a654d35
Have each client join a given room.
Jul 9, 2017
d4b978e
Drop unnecessary test client.
Jul 9, 2017
84fe62f
Add test for room joining.
Jul 9, 2017
62bdb6a
Add disconnector collaborator to encapsulate room disconnectiong logic.
Jul 10, 2017
c897a19
Use disconnector in serverCreator.
Jul 10, 2017
6d0370a
Add sinon mock library.
Jul 12, 2017
84dd8a5
Merge branch 'tpbot-feature-branch' into BOT-296/socket_io_client
Jul 17, 2017
695d1b8
Add observer to notify when a disconnect event occurs for testing pur…
Jul 19, 2017
e729920
Use stubbing library over test disconnect and test router.
Jul 19, 2017
0054999
Drop rooms from Router, they are only used in BotLocator."
Jul 19, 2017
19aa9de
Fix errors in serverCreator.
Jul 19, 2017
238d468
Introduce overides for ServerCreator dependencies.
Jul 19, 2017
a75f27d
Inline BotLocator, it isn't used anywhere else.
Jul 19, 2017
86e27f1
Export botLocator so that requires can specify the rooms.
Jul 19, 2017
d4582c3
Create Router so that requires can supply the BotLocator.
Jul 19, 2017
526ccf0
Constructor Disconnector and Observer so that requires can specify ad…
Jul 19, 2017
63e6dfa
Return this for each with function in Builder.
Jul 19, 2017
ae0c5b5
Use correct pattern for require with params.
Jul 19, 2017
0548eee
Pass query alone to router, not the full object.
Jul 20, 2017
fe3a863
Begin adding tests for routing logic.
Jul 20, 2017
35f0602
Remove unnecessary before block from router test.
Jul 25, 2017
00a8892
Add test for no available bots.
Jul 25, 2017
ae3ab18
Remove TEST block from Router, we now use mocks for all tests.
Jul 25, 2017
2860885
Add test for Bot query.
Jul 25, 2017
e20ed9d
Rename socketTest to serverCreatorTest to match sut.
Jul 29, 2017
41b6112
Make BotLocatorTest match ServerCreator test naming.
Jul 29, 2017
1fc6014
Test that client if disconnecting in Disconnector.
Jul 29, 2017
71f233d
Introduce socket movement code.
Jul 31, 2017
1eab3ef
Extract a mover object.
Jul 31, 2017
a596a7a
Add tests for mover.
Aug 2, 2017
179afd5
Add mover to serverCreator.
Aug 2, 2017
e15e71b
Pass through socket id to mover.
Aug 2, 2017
945f397
Remove legacy server code.
Aug 3, 2017
f0d737d
Remove unnecessary logging from ApiTest.
Aug 3, 2017
3856276
Use expect test assertions on BotLocatorTests.
Aug 3, 2017
87988e4
Use expect assertions for disconnector tests.
Aug 3, 2017
db62967
Use expect assertions for mover tests.
Aug 3, 2017
3ec8936
Use expect assertions for router tests.
Aug 3, 2017
c67e763
Use expect assertions for serverCreator tests.
Aug 3, 2017
4194d78
Use newer js notation.
Aug 3, 2017
4b8224a
Use newer js notation for disconnector.
Aug 3, 2017
0553635
Use newer js notation for mover.
Aug 3, 2017
a064488
Use newer js notation for router.
Aug 3, 2017
e7fe833
Use newer js notation for server creator.
Aug 3, 2017
2c6c36b
Rename testServer to server.
Aug 3, 2017
ce0f2f6
Use semicolons where appropriate.
Aug 3, 2017
d5a867b
Use single quotes.
Aug 3, 2017
246880c
Use single quotes to improve test data readability.
Aug 3, 2017
f481cba
Improve test naming.
Aug 3, 2017
f5c48b9
Don't new up in module.exports.
Aug 21, 2017
43f8be6
Remove unnecessary check for null. It occurs on Object.keys now.
Aug 21, 2017
684516d
Auto-format all the things.
Aug 21, 2017
f24914a
Create functions for botLocator.
Aug 23, 2017
56b8b9d
Extract explanatory functions for botLocator.
Aug 23, 2017
9e01129
Rename rooms to highlight that these are location based.
Aug 23, 2017
08a0535
Extract explanatory method for empty bot room.
Aug 23, 2017
239ac6f
Don't rely on return statements in disconnectorTests.
Aug 23, 2017
10b4d56
Add additional bots to disconnector tests to cover edge cases.
Aug 23, 2017
01b9155
Use functions like map and filter to improve readability in disconnec…
Aug 23, 2017
0356ae8
Remove unused debug log.
Aug 23, 2017
df10104
Extract explanatory functions from disconnector.
Aug 23, 2017
f541733
Extract explanatory functions from mover.
Aug 23, 2017
e982951
Use let and const over var.
Aug 23, 2017
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 32 additions & 18 deletions TelepresenceBot/server-unit/core/botLocator.js
Original file line number Diff line number Diff line change
@@ -1,25 +1,39 @@
function BotLocator(rooms) {
this.rooms = rooms;
}
module.exports = function (locationRooms) {

BotLocator.prototype.locateFirstAvailableBotIn = function(room) {
var botsInRoom = this.rooms[room];

if(!botsInRoom) {
return;
const roomsThatMatch = function (toMatch) {
return function (room) {
return toMatch == room;
};
}

for (socketId in botsInRoom.sockets) {
var socketsInBotRoom = this.rooms[socketId];
const roomsThatContainProperty = function (property) {
return function (roomName) {
return locationRooms[roomName].hasOwnProperty(property);
};
}

if(botNotConnectedToHuman(socketsInBotRoom)) {
return socketId;
}
const roomsThatAreNotAlreadyConnectedToOtherSockets = function () {
return function (roomName) {
return locationRooms[roomName].length == 1;
};
}
}

function botNotConnectedToHuman(socketsInBotRoom) {
return socketsInBotRoom.length === 1;
}
const asEmptyBotRoom = function () {
return function (locationRoom) {
return Object.keys(locationRooms[locationRoom].sockets)
.filter(roomsThatContainProperty('length'))
.filter(roomsThatAreNotAlreadyConnectedToOtherSockets())
.pop();
};
}

module.exports = BotLocator;
return {
locateFirstAvailableBotIn: function (locationRoom) {
return Object.keys(locationRooms)
.filter(roomsThatMatch(locationRoom))
.filter(roomsThatContainProperty('sockets'))
.map(asEmptyBotRoom())
.pop();
}
};
};
16 changes: 7 additions & 9 deletions TelepresenceBot/server-unit/core/clientType.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
ClientType = {
BOT : "bot",
HUMAN : "human",
TEST : "test",
from : function(rawClientType) {
for(var key in this) {
if(ClientType[key] == rawClientType) {
module.exports = ClientType = {
BOT: 'bot',
HUMAN: 'human',
TEST: 'test',
from: function (rawClientType) {
for (let key in this) {
if (ClientType[key] == rawClientType) {
return ClientType[key];
}
}
return undefined;
}
}

module.exports = ClientType;
53 changes: 53 additions & 0 deletions TelepresenceBot/server-unit/core/disconnector.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
module.exports = function Disconnector(rooms, connectedClients) {

const roomsThatMatch = function (toMatch) {
return function (room) {
return toMatch == room;
};
}

const roomsThatContainProperty = function (property) {
return function (roomName) {
return rooms[roomName].hasOwnProperty(property);
};
}

const thosePresentIn = function (objectToSearch) {
return function (key) {
return objectToSearch[key]
};
}

const asConnectedClient = function () {
return function (key) {
return connectedClients[key];
};
}

const connectedClientsThatContainProperty = function (property) {
return function (connectedClient) {
return connectedClient.hasOwnProperty(property);
}
}

const disconnectClient = function () {
return function (connectedClient) {
connectedClient.disconnect();
}
}

return {
disconnectRoom: function (roomName) {
Object.keys(rooms)
.filter(roomsThatMatch(roomName))
.filter(roomsThatContainProperty('sockets'))
.map(function (roomKey) {
return Object.keys(rooms[roomKey].sockets)
.filter(thosePresentIn(connectedClients))
.map(asConnectedClient())
.filter(connectedClientsThatContainProperty('disconnect'))
.every(disconnectClient());
});
}
};
}
18 changes: 0 additions & 18 deletions TelepresenceBot/server-unit/core/loggingClient.js

This file was deleted.

17 changes: 17 additions & 0 deletions TelepresenceBot/server-unit/core/mover.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
module.exports = function Mover(clientsAndRooms, emitter) {

const emitToRoom = function (direction) {
return function (room) {
emitter.to(room).emit('direction', direction);
}
}

return {
moveIn: function (clientId, direction) {
const rooms = clientsAndRooms[clientId];

Object.keys(rooms || {})
.every(emitToRoom(direction));
}
};
}
7 changes: 7 additions & 0 deletions TelepresenceBot/server-unit/core/observer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
module.exports = function Observer() {
return {
notify: function (eventName, eventData) {
return true;
}
};
}
13 changes: 10 additions & 3 deletions TelepresenceBot/server-unit/core/public/js/connect.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,24 @@
var intervalId;
const intervalId;

const socketOptions ={
transports: ['websocket'],
'force new connection': true,
query: 'clientType=human&room=London'
};

const socket = io(socketOptions);

$(document).ready(function(){

$("input").mousedown(function(){
console.log("mouseDown");
var message = $(this).val();
const message = $(this).val();
intervalId = setInterval(function() {
sendMessage(message);
}, 100);
});

function sendMessage(message) {
var socket = io();
socket.emit('chat message', message);
$('#messages').append($('<li>').text(message));
}
Expand Down
28 changes: 28 additions & 0 deletions TelepresenceBot/server-unit/core/router.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
const ClientType = require('./clientType.js')

module.exports = function Router(botLocator) {
return {
route: function (query, next) {
const roomName = query.room;
const rawClientType = query.clientType;
const clientType = ClientType.from(rawClientType);

switch (clientType) {
case ClientType.BOT:
return next();
case ClientType.HUMAN:
const availableBot = botLocator.locateFirstAvailableBotIn(roomName);

if (availableBot) {
query.room = availableBot;
return next();
} else {
return next(new Error('No bots available'));
}

default:
return next(new Error('Unrecognised clientType: ' + rawClientType));
}
}
};
}
102 changes: 3 additions & 99 deletions TelepresenceBot/server-unit/core/server.js
Original file line number Diff line number Diff line change
@@ -1,100 +1,4 @@
var io = require('socket.io').listen(5000);
var ClientType = require("./clientType.js");
var LoggingClient = require("./loggingClient.js");
var BotLocator = require("./botLocator.js");
const ServerCreator = require('./serverCreator');

var testClient = new LoggingClient();
var botLocator = new BotLocator(io.sockets.adapter.rooms);

io.use(function(client, next){

var roomName = client.handshake.query.room;
var rawClientType = client.handshake.query.clientType;
var clientType = ClientType.from(rawClientType);

switch(clientType) {
case ClientType.TEST:
case ClientType.BOT:
return next();
case ClientType.HUMAN:
var human = client;
var availableBot = botLocator.locateFirstAvailableBotIn(roomName);

if(availableBot) {
human.handshake.query.room = availableBot;
return next();
} else {
return next(new Error('No bots available'));
}
default:
return next(new Error('Unrecognised clientType: ' + rawClientType));

}

});

io.sockets.on('connection', function (client) {

var roomName = client.handshake.query.room;
var rawClientType = client.handshake.query.clientType;
var clientType = ClientType.from(rawClientType);

switch(clientType) {
case ClientType.HUMAN:
client.join(roomName);
testClient.emit('connected_human', asRoomsWithSocketIds());
break;
case ClientType.BOT:
client.join(roomName);
testClient.emit('connected_bot', asRoomsWithSocketIds());
break;
case ClientType.TEST:
console.log('switching test client');
testClient = new LoggingClient(client);
testClient.emit('connected', asRoomsWithSocketIds());
break;
default:
throw 'Unexpected rawClientType: ' + clientType;
}

client.on('disconnect', function() {
disconnectRoom(client.id);
testClient.emit('disconnected_human', asRoomsWithSocketIds());
testClient.emit('disconnected_bot', asRoomsWithSocketIds());
});

client.on('move_in', function(direction) {
var rooms = Object.keys(io.sockets.adapter.sids[client.id]);
for(var i = 0; i < rooms.length; i++) {
io.to(rooms[i]).emit('direction', direction);
testClient.emit('direction', direction);
}
});
});

function disconnectRoom(name) {
var room = io.sockets.adapter.rooms[name];

if(!room) {
return;
}

var clients = io.sockets.adapter.rooms[name].sockets;

for(var client in clients) {
var connectedClient = io.sockets.connected[client];
connectedClient.disconnect();
}
}

function asRoomsWithSocketIds() {
var roomNames = Object.keys(io.sockets.adapter.rooms);
var roomsWithSockets = {};

for(var i = 0; i < roomNames.length; i++) {
var room = io.sockets.adapter.rooms[roomNames[i]];
roomsWithSockets[roomNames[i]] = Object.keys(room.sockets);
}

return roomsWithSockets;
}
const serverCreator = new ServerCreator();
serverCreator.create();
Loading