From 0798d922a65e83a11086fbc03c2f9f5c9ab539cc Mon Sep 17 00:00:00 2001 From: Gabriel Hurley Date: Mon, 26 Mar 2012 23:26:10 -0700 Subject: [PATCH] Adds configurable ajax connection queueing. Fixes bug 965910. Change-Id: I84807f6ca0d9769d25b942c151c1a83501648a0a --- horizon/context_processors.py | 3 +- horizon/static/horizon/js/horizon.js | 52 ++++++++++++++++++- .../templates/horizon/client_side/conf.html | 5 +- openstack_dashboard/settings.py | 1 + 4 files changed, 58 insertions(+), 3 deletions(-) diff --git a/horizon/context_processors.py b/horizon/context_processors.py index 8b094e5e2..0ac7e7ce8 100644 --- a/horizon/context_processors.py +++ b/horizon/context_processors.py @@ -51,7 +51,8 @@ def horizon(request): for each template/template fragment which takes context that is used to render the complete output. """ - context = {"True": True, + context = {"HORIZON_CONFIG": getattr(settings, "HORIZON_CONFIG", {}), + "True": True, "False": False} # Auth/Keystone context diff --git a/horizon/static/horizon/js/horizon.js b/horizon/static/horizon/js/horizon.js index 5cce48305..ad64d0c7c 100644 --- a/horizon/static/horizon/js/horizon.js +++ b/horizon/static/horizon/js/horizon.js @@ -101,7 +101,8 @@ var Horizon = function() { $rows_to_update.each(function(index, row) { var $row = $(this), $table = $row.closest('table'); - $.ajax($row.attr('data-update-url'), { + horizon.ajax.queue({ + url: $row.attr('data-update-url'), error: function (jqXHR, textStatus, errorThrown) { switch (jqXHR.status) { // A 404 indicates the object is gone, and should be removed from the table @@ -276,6 +277,55 @@ var Horizon = function() { return $(template.render(params)).prependTo("#main_content .messages"); }; + /* Queued ajax handling for Horizon. + * + * Note: The number of concurrent AJAX connections hanlded in the queue + * can be configured by setting an "ajax_queue_limit" key in + * settings.HORIZON_CONFIG to the desired number (or None to disable queue + * limiting). + */ + horizon.ajax = { + // This will be our jQuery queue container. + _queue: [], + _active: [], + // Function to add a new call to the queue. + queue: function(opts) { + var complete = opts.complete, + active = horizon.ajax._active; + + opts.complete = function () { + var index = $.inArray(request, active); + if (index > -1) { + active.splice(index, 1); + } + horizon.ajax.next(); + if (complete) { + complete.apply(this, arguments); + } + }; + + function request() { + return $.ajax(opts); + } + + // Queue the request + horizon.ajax._queue.push(request); + + // Start up the queue handler in case it's stopped. + horizon.ajax.next(); + }, + next: function () { + var queue = horizon.ajax._queue, + limit = horizon.conf.ajax.queue_limit, + request; + if (queue.length && (!limit || horizon.ajax._active.length < limit)) { + request = queue.pop(); + horizon.ajax._active.push(request); + return request(); + } + } + }; + return horizon; }; diff --git a/horizon/templates/horizon/client_side/conf.html b/horizon/templates/horizon/client_side/conf.html index f88a6bc0d..fb531bf8c 100644 --- a/horizon/templates/horizon/client_side/conf.html +++ b/horizon/templates/horizon/client_side/conf.html @@ -4,6 +4,9 @@ */ horizon.conf = { debug: {{ debug|yesno:"true,false" }}, - static_url: "{{ STATIC_URL }}" + static_url: "{{ STATIC_URL }}", + ajax: { + queue_limit: {{ HORIZON_CONFIG.ajax_queue_limit|default:"null" }} + } } diff --git a/openstack_dashboard/settings.py b/openstack_dashboard/settings.py index db9922c7d..5153759ff 100644 --- a/openstack_dashboard/settings.py +++ b/openstack_dashboard/settings.py @@ -52,6 +52,7 @@ HORIZON_CONFIG = { 'dashboards': ('nova', 'syspanel', 'settings',), 'default_dashboard': 'nova', 'user_home': 'openstack_dashboard.views.user_home', + 'ajax_queue_limit': 10 } MIDDLEWARE_CLASSES = (