From 64fe29698cac776dee42fed5995b22cea9ade928 Mon Sep 17 00:00:00 2001 From: Joseph Schorr Date: Thu, 3 Jul 2014 17:55:53 -0400 Subject: [PATCH] Add a PingService and make sure we use the average of at least three pings --- static/js/app.js | 135 +++++++++++++++++++++++++++++++++-------------- 1 file changed, 94 insertions(+), 41 deletions(-) diff --git a/static/js/app.js b/static/js/app.js index 49a8bec7d..eb45c5b45 100644 --- a/static/js/app.js +++ b/static/js/app.js @@ -416,6 +416,93 @@ quayApp = angular.module('quay', quayDependencies, function($provide, cfpLoading }]); + $provide.factory('PingService', [function() { + var pingService = {}; + var pingCache = {}; + + var reportPingResult = function($scope, url, ping, callback) { + // Lookup the cached ping data, if any. + var cached = pingCache[url]; + if (!cached) { + cached = pingCache[url] = { + 'pings': [] + }; + } + + // If an error occurred, report it and done. + if (ping < 0) { + cached['pings'] = [-1]; + $scope.$apply(function() { + callback(-1, false, -1); + }); + return; + } + + // Otherwise, add the current ping and determine the average. + cached['pings'].push(ping); + + var sum = 0; + for (var i = 0; i < cached['pings'].length; ++i) { + sum += cached['pings'][i]; + } + + // Report the average ping. + $scope.$apply(function() { + callback(Math.floor(sum / cached['pings'].length), true, cached['pings'].length); + }); + + // Schedule another check if we've done less than three. + if (cached['pings'].length < 3) { + setTimeout(function() { + pingUrlInternal($scope, url, callback); + }, 1000); + } + }; + + var pingUrlInternal = function($scope, url, callback) { + var path = url + '?cb=' + (Math.random() * 100); + var start = new Date(); + var xhr = new XMLHttpRequest(); + xhr.onerror = function() { + reportPingResult(url, -1, callback); + }; + + xhr.onreadystatechange = function () { + if (xhr.readyState === xhr.HEADERS_RECEIVED) { + if (xhr.status != 200) { + reportPingResult($scope, url, -1, callback); + return; + } + + var ping = (new Date() - start); + reportPingResult($scope, url, ping, callback); + } + }; + + xhr.open("GET", path); + xhr.send(null); + }; + + pingService.pingUrl = function($scope, url, callback) { + if (pingCache[url]) { + cached = pingCache[url]; + $scope.$apply(function() { + callback(cached.result, cached.success); + }); + return; + } + + // Note: We do each in a callback after 1s to prevent it running when other code + // runs (which can skew the results). + setTimeout(function() { + pingUrlInternal($scope, url, callback); + }, 1000); + }; + + return pingService; + }]); + + $provide.factory('TriggerDescriptionBuilder', ['UtilService', '$sanitize', function(UtilService, $sanitize) { var builderService = {}; @@ -4628,7 +4715,7 @@ quayApp.directive('locationView', function () { scope: { 'location': '=location' }, - controller: function($rootScope, $scope, $element, $http) { + controller: function($rootScope, $scope, $element, $http, PingService) { var LOCATIONS = { 'local_us': { 'country': 'US', 'data': 'quay-registry.s3.amazonaws.com', 'title': 'United States' }, 'local_eu': { 'country': 'EU', 'data': 'quay-registry-eu.s3-eu-west-1.amazonaws.com', 'title': 'Europe' }, @@ -4671,46 +4758,12 @@ quayApp.directive('locationView', function () { }; $scope.getLocationPing = function(location) { - if (!$rootScope.__CACHED_LOCATION_PINGS) { - $rootScope.__CACHED_LOCATION_PINGS = {}; - } - - if ($rootScope.__CACHED_LOCATION_PINGS[location]) { - $scope.locationPing = $rootScope.__CACHED_LOCATION_PINGS[location]; - return; - } - - var conductPing = function() { - var path = 'http://' + LOCATIONS[location]['data'] + '/okay.txt?cb=' + (Math.random() * 100); - var start = new Date(); - var xhr = new XMLHttpRequest(); - xhr.onerror = function() { - $scope.$apply(function() { - $scope.locationPing = -1; - }); - }; - xhr.onreadystatechange = function () { - if (xhr.readyState === xhr.HEADERS_RECEIVED) { - if (xhr.status != 200) { - $scope.$apply(function() { - $scope.locationPing = -1; - }); - return; - } - - var ping = (new Date() - start); - $scope.$apply(function() { - $rootScope.__CACHED_LOCATION_PINGS[location] = $scope.locationPing = ping; - }); - } - }; - - xhr.open("GET", path); - xhr.send(null); - return; - }; - - setTimeout(conductPing, 1000); + var url = 'http://' + LOCATIONS[location]['data'] + '/okay.txt'; + PingService.pingUrl($scope, url, function(ping, success, count) { + if (count == 3 || !success) { + $scope.locationPing = success ? ping : -1; + } + }); }; $scope.$watch('location', function(location) {