I'm using django development server on windows 8.1 64 bit. I'm also using Tastypie. The mysql version is: 5.5 (x86).
The problem I'm facing is that various queries randomly hangs. I'm using AJAX at the client, but it also happens when I'm using the django admin. I saw that all similar questions relates to chrome issue. But it happens also on Firefox. My database is mysql. Lately I installed SSD drive so all my development code and database is on that SSD (not that I think this should make any difference)
Here is an example of few queries as seen in the Firebug. in this case the 4th hangs (randomly, sometimes it is a different one)
GET id=1">http://127.0.0.1:8000/api/v1/financialmodel/?user_id=1 200 OK 1.33s jquery....min.js GET id=1">http://127.0.0.1:8000/api/v1/strategy/?user_id=1 200 OK 1.35s jquery....min.js (line 6) GET id=1">http://127.0.0.1:8000/api/v1/currency/?user_id=1 200 OK 1.4s jquery....min.js (line 6) the next query get stuck (but this is random sometime it is another query) GET id=1">http://127.0.0.1:8000/api/v1/account/?user_id=1 jquery....min.js (line 6) GET id=1">http://127.0.0.1:8000/api/v1/bankbranch/?user_id=1 200 OK 2.62s
I tried running the server with:
runserver with --nothread (or without)
did not change anything.
I tried installing //github.com/ashchristopher/django-concurrent-server thinking this might help, but same thing still random hangs on various queries.
If I pause the server using the debugger in the APTANA IDE, I find that the server is at:
SocketServer.py line 155
def _eintr_retry(func, *args):
"""restart a system call interrupted by EINTR"""
while True:
try:
return func(*args)
except (OSError, select.error) as e:
if e.args[0] != errno.EINTR:
raise
Any ideas? Thanks a lot!
Here is the line in the Ajax code from jquery-2.0.3
// Do send the request
// This may raise an exception which is actually
// handled in jQuery.ajax (so no try/catch here)
xhr.send( options.hasContent &&
options.data || null );
},
abort: function() {
if ( callback ) {
callback();
}
}
};
}
});
Here is a function that loads a ui tree:
function loadAccountsTree() {
$.getJSON("/api/v1/account/?user__id=" + userid, function(json) {
// Extracting the required JSON structure from the entire response
var tree = json.objects[0];
$("#accounts-tree").jstree({
"sort" : function() {
},
"json_data" : {
"data" : tree
},
"types" : {
"max_children" : 1,
"types" : {
// Account type
"default" : {
"valid_children" : "none"
},
"folder" : {
"valid_children" : ["default", "folder"]
}
}
},
"hotkeys" : {
"return" : function() {
var hovered = $('#accounts-tree .jstree-hovered');
if (hovered.length) {
$("#accounts-tree").jstree("deselect_all");
$("#accounts-tree").jstree("select_node", hovered);
}
}
},
"ui" : {
select_multiple_modifier : false
},
"contextmenu" : {
// Select node when right-clicking
"select_node" : true,
items : {// Could be a function that should return an object like this one
"ccp" : false,
"create" : {
"separator_before" : false,
"separator_after" : true,
"label" : "Create",
"action" : false,
"submenu" : {
"create_file" : {
"seperator_before" : false,
"seperator_after" : false,
"label" : "Account",
action : function(obj) {
this.create(obj, "last", {
"attr" : {
"rel" : "default"
}
});
}
},
"create_folder" : {
"seperator_before" : false,
"seperator_after" : false,
"label" : "Folder",
action : function(obj) {
this.create(obj, "last", {
"attr" : {
"rel" : "folder"
}
});
}
} // End of "create_folder" contextmenu function
}
}
}
},
"plugins" : ["themes", "json_data", "ui", "hotkeys", "crrm", "dnd", "contextmenu", "types"]
}).bind("before.jstree", function(e, data) {
if (data.func === "remove") {
var nodes = data.inst._get_node(null, true);
for (var i = 0; i < nodes.length; i++) {
var node = nodes[i];
var nodeName = $(node).find('> a').text().substring(1);
if ($(node).find('> ul').length) {
alert('You need to delete all folders and accounts inside ' + nodeName + ' before deleting it.');
e.stopImmediatePropagation();
return false;
} else if (!confirm("Are you sure you want to delete " + nodeName + " ?")) {
e.stopImmediatePropagation();
return false;
}
}
}
}).bind("loaded.jstree", function(event, data) {
// Selecting top account
data.inst.select_node('> ul > li:first');
// Loading all assets for top account
loadAccountAssets($("#accounts-tree > ul:first > li:first").attr("id"));
loadCommissions($("#accounts-tree > ul:first > li:first").attr("id"));
}).bind("create.jstree", function(e, data) {
var newNode = data.rslt.obj;
var verified = true;
$(newNode).siblings().each(function(idx, listItem) {
var siblingNode = $(listItem);
if (newNode.attr("rel") !== siblingNode.attr("rel")) {
verified = false;
return false;
}
});
var isFolder;
if (data.rslt.obj.attr("rel") == 'default') {
isFolder = 'false';
} else {
isFolder = 'true';
}
if (verified) {
$.ajax({
type : 'POST',
// make sure you respect the same origin policy with this url:
// http://en.wikipedia.org/wiki/Same_origin_policy
url : '/api/v1/account/',
data : JSON.stringify({
'folder' : isFolder,
'user' : '/api/v1/user/' + userid + '/',
'parent' : '/api/v1/account/' + data.rslt.parent.attr("id") + '/',
'name' : data.rslt.name,
'type' : data.rslt.obj.attr("rel")
}),
contentType : "application/json",
dataType : 'json',
processData : false,
success : function(r) {
data.rslt.obj.attr("id", r.id);
},
error : function(xhr, textStatus, error) {
loadAccountsTree();
logErrors(xhr, textStatus, error);
}
});
} else {
alert("Folders can contain either folders or accounts, not both at a time.");
$(newNode).prev().addClass("jstree-last");
$(newNode).remove();
}
}).bind("rename.jstree", function(e, data) {
$.ajax({
type : 'PATCH',
url : '/api/v1/account/' + data.rslt.obj.attr("id") + '/',
data : JSON.stringify({
"name" : data.rslt.new_name
}),
dataType : 'json',
contentType : 'application/json',
error : function(xhr, textStatus, error) {
loadAccountsTree();
logErrors(xhr, textStatus, error);
}
});
}).bind("remove.jstree", function(e, data) {
$.ajax({
type : 'DELETE',
url : '/api/v1/account/' + data.rslt.obj.attr("id") + '/'
});
}).bind("select_node.jstree", function(event, data) {
var currentNode = data.rslt.obj;
var ui_currency = ($('#usd').hasClass('active')) ? 'usd' : 'ils';
var isFolder = currentNode.attr("rel") === "folder";
if (isFolder) {
$("#account-form").slideUp();
} else {
// The account is not a folder. Show account details and load its commissions.
$("#account-form").slideDown();
$("#account-name").attr("value", $(currentNode).text().substring(2));
var bankId = $(currentNode).closest("li").data("bank_id");
var accountBank = (bankId) ? bankId : "None";
$("#bank").val(accountBank);
$("#account-type").val($(currentNode).closest("li").data("account_type"));
reloadAccountCommissions(currentNode.attr("id"));
}
reloadAccountAssets(isFolder, currentNode.attr("id"), ui_currency);
var parents = currentNode.parents("li");
var parentsList = currentNode.children("a").text().substring(1);
parents.each(function(index) {
parentsList = $(this).children("a").text().substring(1) + ' > ' + parentsList;
});
$("#account-title").text(currentNode.find("> a").text().substring(1) + " details");
$("#account-breadcrumbs > p").text("Accounts: " + parentsList);
}).bind("move_node.jstree", function(e, data) {
data.rslt.o.each(function(i) {
var valid = true;
var currentNode = $(this);
$(currentNode).siblings().each(function(idx, listItem) {
var siblingNode = $(listItem);
if (currentNode.attr("rel") !== siblingNode.attr("rel")) {
valid = false;
return false;
}
});
if (valid) {
$.ajax({
type : 'PATCH',
url : '/api/v1/account/' + currentNode.attr("id") + '/',
data : JSON.stringify({
"parent" : '/api/v1/account/' + data.rslt.np.attr("id") + '/'
}),
dataType : 'json',
contentType : 'application/json',
error : function(xhr, textStatus, error) {
loadAccountsTree();
logErrors(xhr, textStatus, error);
}
});
} else {
$(data.rslt.op).append(currentNode);
$(currentNode).addClass("jstree-last");
alert("The parent folder can not contain folders and accounts at the same time.");
}
});
});
});
}
Here is the function that loads all the assets for the selected account into a grid (this grid sometimes stays "Loading...", when I check the server log 200 was sent back, but in the Firebug one of the queries never ends
function loadAccountAssets(accountid) {
$("#pager-account-assets").empty();
var ui_currency = ($('#usd').hasClass('active')) ? 'usd' : 'ils';
$("#jqgrid-account-assets").empty().jqGrid({
url : '/api/v1/assetgrid/?user__id=' + userid + '&account__id__in=' + accountid + '&ui_currency_code=' + ui_currency,
datatype : 'json',
ajaxGridOptions : {
contentType : "application/json"
},
jsonReader : {
repeatitems : false,
id : "id"
},
colNames : ['Account', 'Place', 'Subtype', 'Issuer', 'Price linkage', 'Interest type', 'Return net', 'Return gross', 'Maturity term', 'Maturity date', 'Symbol', 'Update', 'Update hint', 'Value', 'Currency', 'Units', 'Price', 'Description', 'FinancialModel'],
// 'Issuer', 'Price linkage', 'Interest type', 'Return net', 'Return gross', 'Maturity term', 'Maturity date', 'Financialmodel',
colModel : [{
name : 'Account',
edittype : 'select',
editoptions : {
dataUrl : '/api/v1/account/?user__id=' + userid + '&folder=false',
buildSelect : function(data) {
var response = $.parseJSON(data);
var s = '<select>';
$.each(response.objects, function(index, account) {
s += '<option value="' + account.resource_uri + '">' + account.data + '</option>';
});
return s + "</select>";
}
},
stype : 'select'
}, buildHiddenColumn('Place', 'place', true, false, 'resource_uri', 'name'), buildHiddenColumn('Subtype', 'subtype', true, false, 'resource_uri', 'name'), buildHiddenColumn('Issuer', 'issuer', true, false, 'resource_uri', 'name'), {
name : 'price_linkage',
hidden : true,
editable : true,
edittype : 'select',
editoptions : {
value : 'F:Foreign Currency;M:Madad;I:ILS'
},
stype : 'select',
editrules : {
edithidden : true
}
}, {
name : 'Interest',
hidden : true,
editable : true,
edittype : 'select',
editoptions : {
value : 'F:Fix;C:Changing;O:Other'
},
stype : 'select',
editrules : {
edithidden : true
}
}, {
name : 'Return Net',
editable : true,
editrules : {
edithidden : true
},
hidden : true,
editoptions : {
dataInit : function(element) {
$(element).attr("readonly", true);
}
}
}, {
name : 'Return Gross',
editable : true,
editrules : {
edithidden : true
},
hidden : true,
editoptions : {
dataInit : function(element) {
$(element).attr("readonly", "readonly");
}
}
}, {
name : 'Maturity',
hidden : true,
editable : true,
edittype : 'select',
editoptions : {
value : 'S:Short;M:Medium;L:Long'
},
stype : 'select',
editrules : {
edithidden : true
}
}, {
name : 'MaturityDate',
hidden : true,
editable : true,
formatter : "date",
editoptions : {
dataInit : function(el) {
setTimeout(function() {
$(el).datepicker({
dateFormat : "yy-mm-dd"
});
}, 200);
}
},
formoptions : {
rowpos : 1,
colpos : 2
},
formatoptions : {
newformat : "Y-m-d"
},
editrules : {
edithidden : true
}
}, symbolColumn, {
name : 'Update',
edittype : 'select',
editoptions : {
value : 'A:Automatic;M:Manual'
},
formoptions : {
rowpos : 2,
colpos : 2
},
stype : 'select',
}, {
name : 'UpdHint',
formoptions : {
rowpos : 3,
colpos : 2
}
}, {
name : 'Value',
width : 70,
editable : false
}, currencyColumn, {
name : 'Units',
width : 70,
formoptions : {
rowpos : 4,
colpos : 2
},
editoptions : {
dataInit : function(elem) {
setTimeout(function() {
// It must be an integer
$(elem).numeric(false, function() {
alert("Integers only");
this.value = "";
this.focus();
});
}, 100);
}
}
}, {
name : 'Price',
width : 70,
formoptions : {
rowpos : 5,
colpos : 2
},
editoptions : {
dataInit : function(elem) {
setTimeout(function() {
$(elem).numeric();
}, 100);
}
}
}, {
name : 'Description',
formoptions : {
rowpos : 6,
colpos : 2
},
width : 200
}, {
name : 'FinancialModel',
edittype : 'select',
formoptions : {
rowpos : 7,
colpos : 2
},
editoptions : {
dataUrl : '/api/v1/financialmodel/?user__id=' + userid,
buildSelect : function(data) {
var response = $.parseJSON(data);
var s = '<select><option value="">None</option>';
$.each(response.objects, function(index, financialmodel) {
s += '<option value="' + financialmodel.resource_uri + '">' + financialmodel.data + '</option>';
});
return s + "</select>";
}
},
stype : 'select'
}],
cmTemplate : {
editable : true,
width : 100
},
ondblClickRow : function() {
var rowid = $("#jqgrid-account-assets").getGridParam('selrow');
$('#jqgrid-account-assets').jqGrid('editRow', rowid, {
keys : true,
dataType : 'json',
url : '/api/v1/assetgrid/' + encodeURIComponent(rowid) + '/',
mtype : 'PATCH'
});
},
serializeRowData : function(data) {
return serializeAssetData(data);
},
ajaxRowOptions : {
contentType : "application/json"
},
width : 835,
shrinkToFit : false,
gridview : true,
height : "auto",
autoencode : true,
loadonce : true,
rowNum : 10,
rowList : [10, 20, 30],
pager : "#pager-account-assets",
viewrecords : true,
}).jqGrid("navGrid", "#pager-account-assets", {
search : false,
refresh : false
},
// edit options
{
closeAfterEdit : true,
mtype : "PUT",
serializeEditData : function(data) {
return serializeAssetData(data);
},
onclickSubmit : function(params, postdata) {
params.url = '/api/v1/assetgrid/' + encodeURIComponent(postdata[this.id + "_id"]) + '/';
},
ajaxEditOptions : {
contentType : "application/json",
dataType : "json"
},
afterSubmit : function(response, postdata) {
$('#jqgrid-account-assets').setGridParam({
datatype : 'json'
}).trigger('reloadGrid');
return [true, '', false];
},
beforeShowForm : function(form) {
centerDialog($("#editmodjqgrid-account-assets"));
}
},
// add options
{
closeAfterAdd : true,
mtype : "POST",
serializeEditData : function(data) {
return serializeAssetData(data);
},
onclickSubmit : function(params, postdata) {
params.url = '/api/v1/assetgrid/';
},
afterSubmit : function(response, postdata) {
$('#jqgrid-account-assets').setGridParam({
datatype : 'json'
}).trigger('reloadGrid');
return [true, ''];
},
ajaxEditOptions : {
contentType : "application/json",
dataType : "json"
},
beforeShowForm : function(form) {
centerDialog($("#editmodjqgrid-account-assets"));
}
},
// delete options
{
// Delete parameters
mtype : "DELETE",
serializeDelData : function() {
return "";
},
onclickSubmit : function(params, postdata) {
params.url = '/api/v1/assetgrid/' + encodeURIComponent(postdata) + '/';
},
beforeShowForm : function(form) {
centerDialog($("#delmodjqgrid-account-assets"));
},
afterSubmit : function(response, postdata) {
$('#jqgrid-account-assets').setGridParam({
datatype : 'json'
}).trigger('reloadGrid');
return [true, ''];
}
});
}