jam-cloud/web/app/assets/javascripts/sessionLatency.js

141 lines
4.8 KiB
JavaScript

(function(context, $) {
"use strict";
context.JK = context.JK || {};
context.JK.SessionLatency = function(jamClient) {
var logger = context.JK.logger;
var sessionPingsOut = {};
var clientsToSessions = {};
var sessionLatency = {};
var subscribers = {};
function getSortScore(sessionId) {
return sessionLatency[sessionId].sortScore;
}
function ensureSessionLatencyEntry(sessionId) {
if (!(sessionId in sessionLatency)) {
sessionLatency[sessionId] = {
clientLatencies: {},
averageLatency: 0
};
}
}
function setInitialSortScore(session) {
var i,
p,
score = 0,
participant = null;
// user has invitations for this session
if ("invitations" in session) {
score += 2;
}
for (i=0, p=session.participants.length; i<p; i++) {
participant = session.participants[i];
// this session participant is a friend
if (participant !== undefined && participant.user !== undefined && participant.user.is_friend) {
score += 1;
break;
}
}
ensureSessionLatencyEntry(session.id);
sessionLatency[session.id].sortScore = score;
}
function sessionPings(session) {
setInitialSortScore(session);
$.each(session.participants, function(index, participant) {
var clientID = participant.client_id;
clientsToSessions[clientID] = session.id;
if (!(session.id in sessionPingsOut)) {
sessionPingsOut[session.id] = 0;
}
sessionPingsOut[session.id]++;
var jsFunction = "JK.Callbacks.clientPingResponse";
var timeoutFunction = "JK.Callbacks.clientPingTimeout";
jamClient.TestLatency(clientID, jsFunction, timeoutFunction);
});
}
function clientPingResponse(response) {
logger.debug("clientPingResponse");
logger.debug(response);
var sessionId = clientsToSessions[response.clientID];
sessionPingsOut[sessionId]--;
updateSessionLatency(sessionId, response);
for (var k in subscribers) {
if (typeof(subscribers[k]) === 'function') {
subscribers[k](sessionId);
}
}
}
function clientPingTimeout(clientId) {
logger.warn("TIMEOUT during client ping:" + clientId);
logger.warn("calling clientPingResponse directly with 1,000 MS latency");
var response = { clientID: clientId, latency: 1000 };
clientPingResponse(response);
}
function updateSessionLatency(sessionId, latencyResponse) {
ensureSessionLatencyEntry(sessionId);
var sl = sessionLatency[sessionId];
sl.clientLatencies[latencyResponse.clientID] = latencyResponse.latency;
sl.averageLatency = latencyAverage(sl.clientLatencies);
sl.sortScore = updateSortScore(sessionId, sl.averageLatency);
}
function updateSortScore(sessionId, averageLatency) {
var newScore = sessionLatency[sessionId].sortScore;
if (!(newScore)) {
newScore = 0;
}
if (!averageLatency) {
return newScore;
}
var base = Math.floor(newScore);
newScore = base + (1/averageLatency);
return newScore;
}
function latencyAverage(clientLatencies) {
var total = 0;
var count = 0;
$.each(clientLatencies, function(index, latency) {
total += latency;
count++;
});
return total/count;
}
function sessionInfo(sessionId) {
return sessionLatency[sessionId];
}
function subscribe(subscriberKey, cb) {
subscribers[subscriberKey] = cb;
}
this.sessionPings = sessionPings;
this.sessionInfo = sessionInfo;
this.getSortScore = getSortScore;
this.subscribe = subscribe;
this.clientPingResponse = clientPingResponse;
this.clientPingTimeout = clientPingTimeout;
// Register clientPingResponse on this instance as a static function
// so that the JavascriptBridge native code can invoke it with a string.
context.JK.Callbacks.makeStatic("clientPingResponse", this.clientPingResponse, this);
context.JK.Callbacks.makeStatic("clientPingTimeout", this.clientPingTimeout, this);
return this;
};
})(window, jQuery);