<commit_before>var cadence = require('cadence')
var Cliffhanger = require('cliffhanger')
var Dispatcher = require('inlet/dispatcher')
var url = require('url')
var assert = require('assert')

function Conduit (id) {
    this._cliffhanger = new Cliffhanger()
    this._listeners = {}
    this._instanceId = id
    var dispatcher = new Dispatcher(this)
    dispatcher.dispatch('GET /', 'index')
    dispatcher.dispatch('POST /bootstrap', 'bootstrap')
    dispatcher.dispatch('POST /join', 'join')
    dispatcher.dispatch('POST /kibitz', 'kibitz')
    dispatcher.dispatch('POST /health', 'health')
    dispatcher.dispatch('GET /colleagues', 'colleagues')
    this.dispatcher = dispatcher
// TODO Should be able to time out explicitly on socket close.
    setInterval(function () {
        this._cliffhanger.expire(Date.now() - 5000)
    }.bind(this), 1000).unref()
}

Conduit.prototype.index = cadence(function () {
    return 'Compassion Conduit API\n'
})

Conduit.prototype.connection = function (ws) {
    var query = url.parse(ws.upgradeReq.url, true).query
    if (query.islandName && query.colleagueId) {
        var listeners = this._listeners, cliffhanger = this._cliffhanger

        var key = '(' + query.islandName + ')' + query.colleagueId

        var listener = listeners[key]
        if (listener != null) {
            listener.close.call(null)
        }
        listener = listeners[key] = { query: query, close: close, ws: ws }

        ws.on('message', message)
        ws.on('close', close)

        function message (event) {
            var message = JSON.parse(event)
            cliffhanger.resolve(message.cookie, [ null, message.body ])
        }

        function close () {
            delete listeners[key]
            ws.removeListener('close', close)
            ws.removeListener('message', message)
            ws.close()
            ws.terminate()
        }
    }
}

Conduit.prototype._send = cadence(function (async, type, request) {
    var body = request.body
    assert(body.islandName && body.colleagueId)
    var key = '(' + body.islandName + ')' + body.colleagueId
    var listener = this._listeners[key]
    if (listener != null) {
        var cookie = this._cliffhanger.invoke(async())
        listener.ws.send(JSON.stringify({ type: type, cookie: cookie, body: body }))
        return
    }
    request.raise(404)
})

; [ 'bootstrap', 'join', 'kibitz', 'health' ].forEach(function (name) {
    Conduit.prototype[name] = cadence(function (async, request) {
        this._send(name, request, async())
    })
})

Conduit.prototype.colleagues = cadence(function (async) {
    var inquire = []
    for (var key in this._listeners) {
        inquire.push(this._listeners[key].query)
    }
    return {
        instanceId: this._instanceId,
        colleagues: inquire
    }
})

module.exports = Conduit<commit_msg>Add out of band channel.<commit_after>var cadence = require('cadence')
var Cliffhanger = require('cliffhanger')
var Dispatcher = require('inlet/dispatcher')
var url = require('url')
var assert = require('assert')

function Conduit (id) {
    this._cliffhanger = new Cliffhanger()
    this._listeners = {}
    this._instanceId = id
    var dispatcher = new Dispatcher(this)
    dispatcher.dispatch('GET /', 'index')
    dispatcher.dispatch('POST /bootstrap', 'bootstrap')
    dispatcher.dispatch('POST /join', 'join')
    dispatcher.dispatch('POST /kibitz', 'kibitz')
    dispatcher.dispatch('POST /oob', 'oob')
    dispatcher.dispatch('POST /health', 'health')
    dispatcher.dispatch('GET /colleagues', 'colleagues')
    this.dispatcher = dispatcher
// TODO Should be able to time out explicitly on socket close.
    setInterval(function () {
        this._cliffhanger.expire(Date.now() - 5000)
    }.bind(this), 1000).unref()
}

Conduit.prototype.index = cadence(function () {
    return 'Compassion Conduit API\n'
})

Conduit.prototype.connection = function (ws) {
    var query = url.parse(ws.upgradeReq.url, true).query
    if (query.islandName && query.colleagueId) {
        var listeners = this._listeners, cliffhanger = this._cliffhanger

        var key = '(' + query.islandName + ')' + query.colleagueId

        var listener = listeners[key]
        if (listener != null) {
            listener.close.call(null)
        }
        listener = listeners[key] = { query: query, close: close, ws: ws }

        ws.on('message', message)
        ws.on('close', close)

        function message (event) {
            var message = JSON.parse(event)
            cliffhanger.resolve(message.cookie, [ null, message.body ])
        }

        function close () {
            delete listeners[key]
            ws.removeListener('close', close)
            ws.removeListener('message', message)
            ws.close()
            ws.terminate()
        }
    }
}

Conduit.prototype._send = cadence(function (async, type, request) {
    var body = request.body
    console.log(body)
    assert(body.islandName && body.colleagueId)
    var key = '(' + body.islandName + ')' + body.colleagueId
    var listener = this._listeners[key]
    if (listener != null) {
        var cookie = this._cliffhanger.invoke(async())
        listener.ws.send(JSON.stringify({ type: type, cookie: cookie, body: body }))
        return
    }
    request.raise(404)
})

; [ 'oob', 'bootstrap', 'join', 'kibitz', 'health' ].forEach(function (name) {
    Conduit.prototype[name] = cadence(function (async, request) {
        this._send(name, request, async())
    })
})

Conduit.prototype.colleagues = cadence(function (async) {
    var inquire = []
    for (var key in this._listeners) {
        inquire.push(this._listeners[key].query)
    }
    return {
        instanceId: this._instanceId,
        colleagues: inquire
    }
})

module.exports = Conduit
{'fraction_non_alphanumeric': 0.13806228373702423, 'fraction_numerical': 0.0038062283737024223, 'mean_word_length': 2.8234126984126986, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5078564', 'n_tokens_mistral': 1837, 'n_tokens_neox': 1766, 'n_words': 386}