Skip to content

Instantly share code, notes, and snippets.

@netroy
Last active August 15, 2017 08:15
Show Gist options
  • Save netroy/d4b7195adac3a1a35b4ad988970c96bd to your computer and use it in GitHub Desktop.
Save netroy/d4b7195adac3a1a35b4ad988970c96bd to your computer and use it in GitHub Desktop.
Soundcloud's follower-maze challenge in Javascript
// This code could use comments, tests, & a million other things..
// but since I did not apply at soundcloud, it doesn't matter
const net = require('net')
const split = require('split')
const PriorityQueue = require('priorityqueuejs')
const clients = {}
const followers = {}
const queue = new PriorityQueue((a, b) => b.sequence - a.sequence)
// QUEUE WORKER
const process = event => {
const { type, from, to, payload } = event
switch (type) {
case 'F':
if (to in clients) {
followers[to].add(from)
clients[to].write(payload + '\r\n')
}
break
case 'U':
if (to in followers) {
followers[to].delete(from)
}
break
case 'B':
Object.keys(clients).forEach(id => {
clients[id].write(payload + '\r\n')
})
break
case 'P':
if (to in clients) {
clients[to].write(payload + '\r\n')
}
break
case 'S':
if (from in followers) {
followers[from].forEach(followerId => {
clients[followerId].write(payload + '\r\n')
})
}
break
}
}
let index = 1
const next = () => {
if (!queue.isEmpty()) {
const nextInQueue = queue.peek()
const nextIndex = nextInQueue.sequence
while (nextIndex == index) {
process(queue.deq())
index++
}
setImmediate(next)
}
}
// EVENTS
net.createServer(socket => {
socket.setEncoding('utf8')
socket.pipe(split()).on('data', payload => {
const [sequenceStr, type, from, to] = payload.split('|')
const sequence = parseInt(sequenceStr, 10)
if (!isNaN(sequence)) {
if (queue.isEmpty()) {
setImmediate(next)
}
queue.enq({ sequence, type, from, to, payload })
}
})
}).listen(9090)
// CLIENTS
net.createServer(client => {
client.setEncoding('utf8')
const stream = client.pipe(split())
stream.once('data', id => {
const clientId = id.toString()
clients[clientId] = client
followers[clientId] = new Set()
console.log('registered', clientId)
client.once('close', () => {
console.log('deregistered', clientId)
delete clients[clientId]
delete followers[clientId]
})
})
}).listen(9099)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment