* VRFS-2304 - create scoring timeout when doing a network test

This commit is contained in:
Seth Call 2014-10-06 16:44:30 -05:00
parent 2d71a12a79
commit 71f6b7edc6
20 changed files with 255 additions and 58 deletions

View File

@ -117,4 +117,4 @@ end
gem 'pry'
gem 'pry-remote'
gem 'pry-stack_explorer'
gem 'pry-debugger'
#gem 'pry-debugger'

View File

@ -91,6 +91,7 @@ ActiveAdmin.register JamRuby::Connection, :as => 'Connection' do
row :locidispid
row :aasm_state
row :udp_reachable
row :is_network_testing
row :scoring_failures
row :scoring_timeout_occurrences
row :scoring_failures_offset

View File

@ -5,7 +5,7 @@ ActiveAdmin.register_page "Current Scoring Load" do
table_for GetWork.summary do
column "Work", :work_count
column "Who", Proc.new { |connection| "#{connection.first_name} #{connection.last_name} - #{connection.email}" }
column "Errors", Proc.new { |connection| "#{connection.udp_reachable != false ? "" : "No STUN,"} #{connection.in_timeout != 'f' ? "Timeout," : ""} #{connection.in_session != 'f' ? "In-Session," : ""}" }
column "Errors", Proc.new { |connection| "#{connection.udp_reachable != false ? "" : "No STUN,"} #{connection.is_network_testing != false ? "NETWORK TESTING" : ""} #{connection.in_timeout != 'f' ? "Timeout," : ""} #{connection.in_session != 'f' ? "In-Session," : ""}" }
column "Total Timeouts", :scoring_timeout_occurrences
column "Current Scoring Failures", :scoring_failures
column "Offset", :scoring_failures_offset

View File

@ -217,3 +217,4 @@ entabulate_current_network_scores.sql
discard_scores_changed.sql
emails_from_update.sql
add_active_feed.rb
connection_network_testing.sql

View File

@ -0,0 +1,44 @@
-- let the server know if the client is network testing. If so, then also remove them from work
ALTER TABLE connections ADD COLUMN is_network_testing BOOLEAN DEFAULT FALSE NOT NULL;
DROP FUNCTION IF EXISTS get_work (my_client_id VARCHAR(64), mylocidispid BIGINT, myaddr BIGINT, return_rows INT, stale_score INTERVAL);
CREATE FUNCTION get_work (my_client_id VARCHAR(64), mylocidispid BIGINT, myaddr BIGINT, return_rows INT, stale_score INTERVAL) RETURNS TABLE (client_id VARCHAR(64)) VOLATILE AS $$
BEGIN
RETURN QUERY WITH
scorable_locations AS (
SELECT DISTINCT locidispid FROM connections WHERE client_type = 'client' AND connections.client_id != my_client_id AND addr != myaddr AND udp_reachable AND is_network_testing = FALSE AND NOW() > scoring_timeout AND connections.music_session_id IS NULL AND
locidispid NOT IN (SELECT DISTINCT blocidispid FROM most_recent_scores WHERE alocidispid = mylocidispid AND (current_timestamp - score_dt) < stale_score) AND
locidispid/1000000 IN (SELECT locid FROM geoiplocations WHERE geog && st_buffer((SELECT geog FROM geoiplocations WHERE locid = mylocidispid/1000000), 4023360))
)
SELECT tmp.client_id FROM (SELECT connections.client_id, random() AS r, row_number() OVER (PARTITION BY connections.locidispid) AS rownum FROM connections, scorable_locations
WHERE connections.locidispid = scorable_locations.locidispid AND client_type = 'client' AND connections.client_id != my_client_id AND addr != myaddr AND udp_reachable AND NOW() > scoring_timeout AND connections.music_session_id IS NULL ) tmp WHERE rownum <= 1 ORDER BY r LIMIT return_rows;
RETURN;
END;
$$ LANGUAGE plpgsql;
DROP FUNCTION IF EXISTS get_work_summary (stale_score INTERVAL);
CREATE FUNCTION get_work_summary (stale_score INTERVAL) RETURNS TABLE (work_count BIGINT, client_id VARCHAR(64), email VARCHAR, first_name VARCHAR, last_name VARCHAR, user_id VARCHAR(64), udp_reachable BOOLEAN, in_timeout BOOLEAN, in_session BOOLEAN, scoring_failures INT, scoring_failures_offset INT, scoring_timeout_occurrences INT, is_network_testing BOOLEAN) VOLATILE AS $$
BEGIN
RETURN QUERY
SELECT SUM(CASE WHEN tmp.test_client_id IS NULL OR tmp.in_session OR tmp.in_timeout OR tmp.udp_reachable = FALSE OR tmp.is_network_testing = TRUE THEN 0 ELSE 1 END) AS work_count, tmp.client_id AS client_id, users.email, users.first_name, users.last_name, users.id AS user_id, tmp.udp_reachable, tmp.in_timeout, tmp.in_session, tmp.scoring_failures, tmp.scoring_failures_offset, tmp.scoring_timeout_occurrences, tmp.is_network_testing FROM
(SELECT connections.client_type, scorable_locations.client_id AS test_client_id, connections.client_id AS client_id, connections.user_id AS user_id, connections.udp_reachable, connections.scoring_timeout > NOW() as in_timeout, connections.music_session_id IS NOT NULL AS in_session, connections.scoring_failures, connections.scoring_failures_offset, connections.scoring_timeout_occurrences, connections.is_network_testing, scorable_locations.client_id IS NULL AS same_client, row_number() OVER (PARTITION BY connections.locidispid) AS rownum FROM connections LEFT OUTER JOIN scorable_locations(connections.client_id, connections.locidispid, connections.addr, stale_score)
ON connections.locidispid != scorable_locations.locidispid) tmp INNER JOIN users ON tmp.user_id = users.id WHERE tmp.client_type = 'client' GROUP BY tmp.client_id, users.email, users.first_name, users.last_name, users.id, tmp.same_client, tmp.udp_reachable, tmp.in_timeout, tmp.in_session, tmp.scoring_failures, tmp.scoring_failures_offset, tmp.scoring_timeout_occurrences, tmp.is_network_testing ORDER BY work_count DESC;
RETURN;
END;
$$ LANGUAGE plpgsql;
DROP FUNCTION IF EXISTS get_work_summary_no_agg(stale_score INTERVAL);
-- useful for debugging get_work_summary
CREATE FUNCTION get_work_summary_no_agg (stale_score INTERVAL) RETURNS TABLE (client_id VARCHAR(64), test_client_id VARCHAR(64), email VARCHAR, first_name VARCHAR, last_name VARCHAR, user_id VARCHAR(64), udp_reachable BOOLEAN, in_timeout BOOLEAN, scoring_failures INT, scoring_failures_offset INT, scoring_timeout_occurrences INT, is_network_testing BOOLEAN) VOLATILE AS $$
BEGIN
RETURN QUERY
SELECT tmp.client_id AS client_id, tmp.test_client_id, users.email, users.first_name, users.last_name, users.id AS user_id, tmp.udp_reachable, tmp.in_timeout, tmp.scoring_failures, tmp.scoring_failures_offset, tmp.scoring_timeout_occurrences, tmp.is_network_testing FROM
(SELECT scorable_locations.client_id AS test_client_id, connections.client_id AS client_id, connections.user_id AS user_id, connections.udp_reachable, connections.scoring_timeout > NOW() as in_timeout, connections.scoring_failures, connections.scoring_failures_offset, connections.scoring_timeout_occurrences, connections.is_network_testing, scorable_locations.client_id IS NULL AS same_client, row_number() OVER (PARTITION BY connections.locidispid) AS rownum FROM connections LEFT OUTER JOIN scorable_locations(connections.client_id, connections.locidispid, connections.addr, stale_score)
ON connections.locidispid != scorable_locations.locidispid AND connections.client_type = 'client') tmp INNER JOIN users ON tmp.user_id = users.id ORDER BY tmp.client_id;
RETURN;
END;
$$ LANGUAGE plpgsql;

View File

@ -89,7 +89,7 @@ module JamRuby
udp_reachable_value = udp_reachable.nil? ? 'udp_reachable' : udp_reachable
sql =<<SQL
UPDATE connections SET (channel_id, aasm_state, updated_at, music_session_id, joined_session_at, stale_time, expire_time, udp_reachable, gateway) = ('#{channel_id}', '#{Connection::CONNECT_STATE.to_s}', NOW(), #{music_session_id_expression}, #{joined_session_at_expression}, #{connection_stale_time}, #{connection_expire_time}, #{udp_reachable_value}, '#{gateway}')
UPDATE connections SET (channel_id, aasm_state, updated_at, music_session_id, joined_session_at, stale_time, expire_time, udp_reachable, gateway, is_network_testing) = ('#{channel_id}', '#{Connection::CONNECT_STATE.to_s}', NOW(), #{music_session_id_expression}, #{joined_session_at_expression}, #{connection_stale_time}, #{connection_expire_time}, #{udp_reachable_value}, '#{gateway}', FALSE)
WHERE
client_id = '#{conn.client_id}'
RETURNING music_session_id

View File

@ -18,7 +18,7 @@ module JamRuby
has_one :latency_tester, class_name: 'JamRuby::LatencyTester', foreign_key: :client_id, primary_key: :client_id
has_many :tracks, :class_name => "JamRuby::Track", :inverse_of => :connection, :foreign_key => 'connection_id', :dependent => :delete_all
validates :as_musician, :inclusion => {:in => [true, false]}
validates :as_musician, :inclusion => {:in => [true, false, nil]}
validates :client_type, :inclusion => {:in => [TYPE_CLIENT, TYPE_BROWSER, TYPE_LATENCY_TESTER]}
validates_numericality_of :last_jam_audio_latency, greater_than:0, :allow_nil => true
validate :can_join_music_session, :if => :joining_session?

View File

@ -12,6 +12,7 @@ module JamRuby
def self.get_work_list(connection, rows = 25, staleness_hours = 120)
return [] if connection.is_network_testing # short-circuit 0 results if is_network_testing
return [] unless connection.udp_reachable # short-circuit 0 results if udp_reachable
return [] if connection.scoring_timeout > Time.now # short-circuit 0 results if in scoring timeout
return [] if connection.in_session?
@ -25,7 +26,7 @@ module JamRuby
end
def self.summary(staleness_hours = 120)
r = GetWork.select([:work_count, :client_id, :email, :first_name, :last_name, :user_id, :udp_reachable, :in_timeout, :in_session, :scoring_failures, :scoring_failures_offset, :scoring_timeout_occurrences]).find_by_sql("select work_count, client_id, email, first_name, last_name, user_id, udp_reachable, in_timeout, in_session, scoring_failures, scoring_failures_offset, scoring_timeout_occurrences FROM get_work_summary(INTERVAL '#{staleness_hours} hours')" )
r = GetWork.select([:work_count, :client_id, :email, :first_name, :last_name, :user_id, :udp_reachable, :in_timeout, :in_session, :scoring_failures, :scoring_failures_offset, :scoring_timeout_occurrences, :is_network_testing]).find_by_sql("select work_count, client_id, email, first_name, last_name, user_id, udp_reachable, in_timeout, in_session, scoring_failures, scoring_failures_offset, scoring_timeout_occurrences, is_network_testing FROM get_work_summary(INTERVAL '#{staleness_hours} hours')" )
end
end
end

View File

@ -1271,8 +1271,7 @@ module JamRuby
if audio_latency > 2
# updating the connection is best effort
if connection
connection.last_jam_audio_latency = audio_latency
connection.save
Connection.where(:id => connection.id).update_all(:last_jam_audio_latency => audio_latency)
end
self.last_jam_audio_latency = audio_latency

View File

@ -176,6 +176,16 @@ describe GetWork do
GetWork.get_work_list(other_connection2).should == [my_connection.client_id]
end
it "excludes network testing clients" do
my_connection = FactoryGirl.create(:connection, locidispid: austin_geo[:locidispid], addr: 1)
other_connection = FactoryGirl.create(:connection, locidispid: dallas_geo[:locidispid], addr: 2, is_network_testing: true)
other_connection2 = FactoryGirl.create(:connection, locidispid: houston_geoip[:locidispid], addr: 3)
GetWork.get_work_list(my_connection).should == [other_connection2.client_id]
GetWork.get_work_list(other_connection).should == []
GetWork.get_work_list(other_connection2).should == [my_connection.client_id]
end
it "excludes scoring_timeout clients (1)" do
my_connection = FactoryGirl.create(:connection, locidispid: austin_geo[:locidispid], addr: 1)
other_connection = FactoryGirl.create(:connection, locidispid: dallas_geo[:locidispid], addr: 2, scoring_timeout: 1.days.from_now)

View File

@ -54,13 +54,14 @@
}
function beforeShow() {
networkTest.haltScoring();
if(!networkTest.isScoring()) {
networkTest.reset();
}
}
function afterHide() {
networkTest.resumeScoring();
}
function initialize() {

View File

@ -140,6 +140,9 @@
}
function updateScoringIntervals() {
// make sure latency testing is still going on, in case a refresh occurred during network test
context.jamClient.SetLatencyTestBlocked(false)
// set scoring intervals
if(context.jamClient.SetScoreWorkTimingInterval){
var success = context.jamClient.SetScoreWorkTimingInterval(

View File

@ -362,6 +362,18 @@
return 8;
}
function SetLatencyTestBlocked(blocked) {
}
function isLatencyTestBlocked() {
return false;
}
function GetLastLatencyTestTimes() {
return { initiated: 10000, requested: 10000}
}
function GetASIODevices() {
var response =[{"device_id":0,"device_name":"Realtek High Definition Audio","device_type": 0,"interfaces":[{"interface_id":0,"interface_name":"Realtek HDA SPDIF Out","pins":[{"is_input":false,"pin_id":0,"pin_name":"PC Speaker"}]},{"interface_id":1,"interface_name":"Realtek HD Audio rear output","pins":[{"is_input":false,"pin_id":0,"pin_name":"PC Speaker"}]},{"interface_id":2,"interface_name":"Realtek HD Audio Mic input","pins":[{"is_input":true,"pin_id":0,"pin_name":"Recording Control"}]},{"interface_id":3,"interface_name":"Realtek HD Audio Line input","pins":[{"is_input":true,"pin_id":0,"pin_name":"Recording Control"}]},{"interface_id":4,"interface_name":"Realtek HD Digital input","pins":[{"is_input":true,"pin_id":0,"pin_name":"Capture"}]},{"interface_id":5,"interface_name":"Realtek HD Audio Stereo input","pins":[{"is_input":true,"pin_id":0,"pin_name":"Recording Control"}]}],"wavert_supported":false},{"device_id":1,"device_name":"M-Audio FW Audiophile","device_type": 1,"interfaces":[{"interface_id":0,"interface_name":"FW AP Multi","pins":[{"is_input":false,"pin_id":0,"pin_name":"Output"},{"is_input":true,"pin_id":1,"pin_name":"Input"}]},{"interface_id":1,"interface_name":"FW AP 1/2","pins":[{"is_input":false,"pin_id":0,"pin_name":"Output"},{"is_input":true,"pin_id":1,"pin_name":"Input"}]},{"interface_id":2,"interface_name":"FW AP SPDIF","pins":[{"is_input":false,"pin_id":0,"pin_name":"Output"},{"is_input":true,"pin_id":1,"pin_name":"Input"}]},{"interface_id":3,"interface_name":"FW AP 3/4","pins":[{"is_input":false,"pin_id":0,"pin_name":"Output"}]}],"wavert_supported":false},{"device_id":2,"device_name":"Virtual Audio Cable","device_type": 2,"interfaces":[{"interface_id":0,"interface_name":"Virtual Cable 2","pins":[{"is_input":true,"pin_id":0,"pin_name":"Capture"},{"is_input":false,"pin_id":1,"pin_name":"Output"}]},{"interface_id":1,"interface_name":"Virtual Cable 1","pins":[{"is_input":true,"pin_id":0,"pin_name":"Capture"},{"is_input":false,"pin_id":1,"pin_name":"Output"}]}],"wavert_supported":false},{"device_id":3,"device_name":"WebCamDV WDM Audio Capture","device_type": 3,"interfaces":[{"interface_id":0,"interface_name":"WebCamDV Audio","pins":[{"is_input":true,"pin_id":0,"pin_name":"Recording Control"},{"is_input":false,"pin_id":1,"pin_name":"Volume Control"}]}],"wavert_supported":false}];
return response;
@ -823,6 +835,9 @@
this.IsMyNetworkWireless = IsMyNetworkWireless;
this.SetNetworkTestScore = SetNetworkTestScore;
this.GetNetworkTestScore = GetNetworkTestScore;
this.SetLatencyTestBlocked = SetLatencyTestBlocked;
this.isLatencyTestBlocked = isLatencyTestBlocked;
this.GetLastLatencyTestTimes = GetLastLatencyTestTimes;
this.RegisterQuitCallback = RegisterQuitCallback;
this.LeaveSessionAndMinimize = LeaveSessionAndMinimize;
this.GetAutoStart = GetAutoStart;

View File

@ -503,6 +503,19 @@
});
}
function updateNetworkTesting(options) {
var id = getId(options);
return $.ajax({
type: "POST",
dataType: "json",
contentType: 'application/json',
url: "/api/users/" + id + "/is_network_testing",
data: JSON.stringify(options),
processData: false
});
}
function updateAvatar(options) {
var id = getId(options);
@ -1222,6 +1235,7 @@
this.getInstruments = getInstruments;
this.getGenres = getGenres;
this.updateUdpReachable = updateUdpReachable;
this.updateNetworkTesting = updateNetworkTesting;
this.updateAvatar = updateAvatar;
this.deleteAvatar = deleteAvatar;
this.getFilepickerPolicy = getFilepickerPolicy;

View File

@ -167,6 +167,35 @@
return lastNetworkFailure;
}
function haltScoring() {
context.jamClient.SetLatencyTestBlocked(true)
rest.updateNetworkTesting({client_id: app.clientId, is_network_testing: true})
.fail(function(jqXHR) {
if(jqXHR.status == 404) {
// assume connection is missing
app.notifyAlert("Not Connected", "You must be connected to the server to run the network test.")
}
else {
app.notifyServerError(jqXHR, "Unable to tell server that we are beginning the network test")
}
})
}
function resumeScoring() {
context.jamClient.SetLatencyTestBlocked(false)
rest.updateNetworkTesting({client_id: app.clientId, is_network_testing: false})
.fail(function(jqXHR) {
if(jqXHR.status == 404) {
// assume connection is missing
// do nothing in this case
}
else {
app.notifyServerError(jqXHR, "Unable to tell server that we are ending the network test")
}
})
}
function storeLastNetworkFailure(reason, data) {
if (!trackedPass) {
lastNetworkFailure = {reason: reason, data: data};
@ -471,63 +500,125 @@
}
}
function pauseForRecentScoresTime() {
var lastScoreTimes = context.jamClient.GetLastLatencyTestTimes()
console.log(lastScoreTimes)
return 0;
var noPause = 0;
var longAgo = 1000000;
var initiated = lastScoreTimes.initiatied;
var requested = lastScoreTimes.requested;
if(initiated === null || initiated === undefined) {
logger.warn("lastScoreTimes.initiated is not set");
initiated = longAgo;
}
if(requested === null || requested === undefined) {
logger.warn("lastScoreTimes.requested is not set");
requested = longAgo;
}
if(initiated == 0) {
logger.debug("lastScoreTimes.initiated is zero");
initiated = longAgo;
}
if(requested == 0) {
logger.debug("lastScoreTimes.requested is zero");
requested = longAgo;
}
if(initiated < 0) {
logger.debug("lastScoreTimes.initiated is less than zero");
initiated = longAgo;
}
if(requested < 0) {
logger.debug("lastScoreTimes.requested is less than zero");
requested = longAgo;
}
var mostRecentValue = initiated < requested ? initiated : requested;
if(mostRecentValue > gon.globalftue_network_test_min_wait_since_last_score * 1000) {
return noPause; // our last score was past our min wait; so no delay necessary
}
else {
// pause for the remainder of the min wait threshold
var remainder = gon.globalftue_network_test_min_wait_since_last_score * 1000 - mostRecentValue;
if(remainder > 1500) {
// we need to update the UI because this is a long time for a mystery pause
$startNetworkTestBtn.text('SHORT QUIET PERIOD...')
}
return remainder;
}
}
function prepareNetworkTest() {
if (scoring) return false;
logger.info("starting network test");
resetTestState();
scoring = true;
$self.triggerHandler(NETWORK_TEST_START);
renderStartTest();
rest.getLatencyTester()
.done(function (response) {
// ensure there are no tests ongoing
serverClientId = response.client_id;
testSummary.serverClientId = serverClientId;
setTimeout(function() {
logger.info("beginning network test against client_id: " + serverClientId);
logger.info("starting network test");
resetTestState();
scoring = true;
$self.triggerHandler(NETWORK_TEST_START);
renderStartTest();
rest.getLatencyTester()
.done(function (response) {
// ensure there are no tests ongoing
primePump()
.done(function () {
postPumpRun();
})
.fail(function () {
logger.debug("unable to determine user's network type. primePump failed.")
context.JK.Banner.showAlert({
title: 'Unable to Determine Network Type',
buttons: [
{name: 'CANCEL', click: function () {
cancelTest();
}},
{name: 'RUN NETWORK TEST ANYWAY', click: function () {
attemptTestPass();
;
}}
],
html: "<p>We are unable to determine if your computer is connected to your network using WiFi.</p>" +
"<p>We strongly advise against running the JamKazam application on a WiFi connection. " +
"We recommend using a wired Ethernet connection from your computer to your router. " +
"A WiFi connection is likely to cause significant issues in both latency and audio quality.</p>"})
});
})
.fail(function (jqXHR) {
if (jqXHR.status == 404) {
// means there are no network testers available.
// we have to skip this part of the UI
testSummary.final = {reason: 'no_servers'}
}
else {
if (context.JK.isNetworkError(arguments)) {
testSummary.final = {reason: 'no_network'}
serverClientId = response.client_id;
testSummary.serverClientId = serverClientId;
logger.info("beginning network test against client_id: " + serverClientId);
primePump()
.done(function () {
postPumpRun();
})
.fail(function () {
logger.debug("unable to determine user's network type. primePump failed.")
context.JK.Banner.showAlert({
title: 'Unable to Determine Network Type',
buttons: [
{name: 'CANCEL', click: function () {
cancelTest();
}},
{name: 'RUN NETWORK TEST ANYWAY', click: function () {
attemptTestPass();
;
}}
],
html: "<p>We are unable to determine if your computer is connected to your network using WiFi.</p>" +
"<p>We strongly advise against running the JamKazam application on a WiFi connection. " +
"We recommend using a wired Ethernet connection from your computer to your router. " +
"A WiFi connection is likely to cause significant issues in both latency and audio quality.</p>"})
});
})
.fail(function (jqXHR) {
if (jqXHR.status == 404) {
// means there are no network testers available.
// we have to skip this part of the UI
testSummary.final = {reason: 'no_servers'}
}
else {
testSummary.final = {reason: 'rest_api_error'}
if (context.JK.isNetworkError(arguments)) {
testSummary.final = {reason: 'no_network'}
}
else {
testSummary.final = {reason: 'rest_api_error'}
}
}
}
testFinished();
})
testFinished();
})
}, pauseForRecentScoresTime())
return false;
}
@ -844,6 +935,8 @@
this.reset = reset;
this.cancel = cancel;
this.getLastNetworkFailure = getLastNetworkFailure;
this.haltScoring = haltScoring;
this.resumeScoring = resumeScoring;
this.NETWORK_TEST_START = NETWORK_TEST_START;
this.NETWORK_TEST_DONE = NETWORK_TEST_DONE;

View File

@ -53,11 +53,13 @@
}
function beforeShow() {
networkTest.haltScoring();
networkTest.cancel();
updateButtons();
}
function beforeHide() {
networkTest.resumeScoring();
networkTest.cancel();
}

View File

@ -669,8 +669,17 @@ class ApiUsersController < ApiController
def udp_reachable
Connection.transaction do
@connection = Connection.find_by_client_id!(params[:client_id])
@connection.udp_reachable = params[:udp_reachable]
@connection.save
# deliberately don't updated_at on connection! only heartbeats do that
Connection.where(:id => @connection.id).update_all(:udp_reachable => params[:udp_reachable])
respond_with_model(@connection)
end
end
def is_network_testing
Connection.transaction do
@connection = Connection.find_by_client_id!(params[:client_id])
# deliberately don't updated_at on connection! only heartbeats do that
Connection.where(:id => @connection.id).update_all(:is_network_testing => params[:is_network_testing])
respond_with_model(@connection)
end
end

View File

@ -248,6 +248,8 @@ if defined?(Bundler)
config.ftue_network_test_packet_size = 60
# number of times that the backend retries before giving up
config.ftue_network_test_backend_retries = 10
# amount of time that we want passed until we run the next network test
config.ftue_network_test_min_wait_since_last_score = 5
# the maximum amount of allowable latency
config.ftue_maximum_gear_latency = 20

View File

@ -4,4 +4,5 @@ Gon.global.ftue_network_test_backend_retries = Rails.application.config.ftue_net
Gon.global.twitter_public_account = Rails.application.config.twitter_public_account
Gon.global.scoring_get_work_interval = Rails.application.config.scoring_get_work_interval
Gon.global.scoring_get_work_backoff_interval = Rails.application.config.scoring_get_work_backoff_interval
Gon.global.ftue_network_test_min_wait_since_last_score = Rails.application.config.ftue_network_test_min_wait_since_last_score
Gon.global.env = Rails.env

View File

@ -297,6 +297,7 @@ SampleApp::Application.routes.draw do
# udp reachable (can stun?)
match '/users/:id/udp_reachable' => 'api_users#udp_reachable', :via => :post
match '/users/:id/is_network_testing' => 'api_users#is_network_testing', :via => :post
# social
match '/users/:id/share/session/:provider' => 'api_users#share_session', :via => :get