Exponential ajax calls when refreshing multiple rows in horizon tables.
Affects | Status | Importance | Assigned to | Milestone | |
---|---|---|---|---|---|
OpenStack Dashboard (Horizon) |
New
|
Undecided
|
Unassigned |
Bug Description
Exponential ajax calls when refreshing multiple rows in horizon tables. When you launch multiple instances, each instance status refresh makes an ajax call to any status_unknown instance, when the number is big (>50) it kill the client CPU.
horizon/
Original:
horizon.datatables = {
update: function () {
var $rows_to_update = $('tr.status_
if ($rows_
var interval = $rows_to_
$table = $rows_to_
// Do not update this row if the action column is expanded
if ($rows_
// Wait and try to update again in next interval instead
// Remove interval decay, since this will not hit server
return;
}
// Trigger the update handlers.
$
var $row = $(this),
$table = $row.closest(
url: $row.attr(
error: function (jqXHR, textStatus, errorThrown) {
switch (jqXHR.status) {
// A 404 indicates the object is gone, and should be removed from the table
case 404:
// Update the footer count and reset to default empty row if needed
var $footer, row_count, footer_text, colspan, template, params, $empty_row;
// existing count minus one for the row we're removing
} else {
}
// Reset tablesorter's data cache.
// Enable launch action if quota is not exceeded
}
},
success: function (data, textStatus, jqXHR) {
var $new_row = $(data);
if ($new_row.
var spinner_elm = $new_row.
var imagePath = $new_row.
}
// Only replace row if the html content has changed
// Preserve the checkbox if it's already clicked
}
// Reset tablesorter's data cache.
// Reset decay constant.
// Check that quicksearch is enabled for this table
// Reset quicksearch's data cache.
if ($table.attr('id') in horizon.
}
}
},
complete: function (jqXHR, textStatus) {
// Revalidate the button check for the updated table
// Set interval decay to this table, and increase if it already exist
} else {
}
// Poll until there are no rows in an "unknown" state on the page.
// Limit the interval to 30 secs
}
});
});
}
},
_______
Our fix:
horizon.datatables = {
update: function (row_id) {
var $rows_to_update = undefined;
//Filter by row_id to prevent exponential ajax calls
if(
$
}
else {
$
}
if ($rows_
var interval = $rows_to_
$table = $rows_to_
// Do not update this row if the action column is expanded
if ($rows_
// Wait and try to update again in next interval instead
return;
}
// Set interval decay to this table, and increase if it already exist
if(
} else {
}
$
// Poll until there are no rows in an "unknown" state on the page.
next_poll = interval * decay_constant;
// Limit the interval to 30 secs
if(next_poll > 30 * 1000) { next_poll = 30 * 1000; }
// Trigger the update handlers.
$
var $row = $(this),
$table = $row.closest(
url: $row.attr(
error: function (jqXHR, textStatus, errorThrown) {
switch (jqXHR.status) {
// A 404 indicates the object is gone, and should be removed from the table
case 404:
// Update the footer count and reset to default empty row if needed
var $footer, row_count, footer_text, colspan, template, params, $empty_row;
// existing count minus one for the row we're removing
} else {
}
// Reset tablesorter's data cache.
// Enable launch action if quota is not exceeded
}
},
success: function (data, textStatus, jqXHR) {
var $new_row = $(data);
if ($new_row.
var spinner_elm = $new_row.
var imagePath = $new_row.
}
// Only replace row if the html content has changed
// Preserve the checkbox if it's already clicked
}
// Reset tablesorter's data cache.
// Check that quicksearch is enabled for this table
// Reset quicksearch's data cache.
if ($table.attr('id') in horizon.
}
}
},
complete: function (jqXHR, textStatus) {
// Revalidate the button check for the updated table
}
});
});
}
},