Api: make longTask (merge to email) more robust

Should continue in the face of network error
This commit is contained in:
nathan 2023-08-02 14:08:17 -06:00
parent 31d93a6ee3
commit b92d45c44a

View File

@ -1293,7 +1293,7 @@ export class Et2Dialog extends Et2Widget(SlotMixin(SlDialog))
// Cancel run // Cancel run
cancel = true; cancel = true;
jQuery("button[button_id=" + Et2Dialog.CANCEL_BUTTON + "]", dialog.div.parent()).button("disable"); jQuery("button[button_id=" + Et2Dialog.CANCEL_BUTTON + "]", dialog.div.parent()).button("disable");
update.call(_list.length, ''); updateUi.call(_list.length, '');
} }
} }
]; ];
@ -1331,13 +1331,12 @@ export class Et2Dialog extends Et2Widget(SlotMixin(SlDialog))
failed: 0, failed: 0,
widget: null widget: null
}; };
let success = [];
let retryDialog = null;
// Updates progressbar & log, calls next step // Updates progressbar & log, returns next index
let update = function(response) let updateUi = function(response, index = 0)
{ {
// context is index
let index = this || 0;
progressbar.set_value(100 * (index / _list.length)); progressbar.set_value(100 * (index / _list.length));
progressbar.set_label(index + ' / ' + _list.length); progressbar.set_label(index + ' / ' + _list.length);
@ -1354,6 +1353,7 @@ export class Et2Dialog extends Et2Widget(SlotMixin(SlDialog))
// Ask to retry / ignore / abort // Ask to retry / ignore / abort
let retry = new Et2Dialog(dialog.egw()); let retry = new Et2Dialog(dialog.egw());
let retry_index = null;
retry.transformAttributes({ retry.transformAttributes({
callback: function(button) callback: function(button)
{ {
@ -1361,16 +1361,14 @@ export class Et2Dialog extends Et2Widget(SlotMixin(SlDialog))
{ {
case 'dialog[cancel]': case 'dialog[cancel]':
cancel = true; cancel = true;
return update.call(index, ''); break;
case 'dialog[skip]': case 'dialog[skip]':
// Continue with next index
totals.skipped++; totals.skipped++;
return update.call(index, ''); break
default: default:
// Try again with previous index // Try again with previous index
return update.call(index - 1, ''); retry_index = index - 1;
} }
}, },
message: response.data, message: response.data,
title: '', title: '',
@ -1384,10 +1382,18 @@ export class Et2Dialog extends Et2Widget(SlotMixin(SlDialog))
}); });
dialog.egw().window.document.body.appendChild(<LitElement><unknown>retry); dialog.egw().window.document.body.appendChild(<LitElement><unknown>retry);
// Early exit // Early exit
return; retryDialog = retry.getComplete().then(() =>
{
retryDialog = null;
if(retry_index !== null)
{
sendRequest(retry_index)
}
});
default: default:
if(response && typeof response === "string") if(response && typeof response === "string")
{ {
success.push(_list[index - 1]);
totals.success++; totals.success++;
let div = document.createElement("DIV"); let div = document.createElement("DIV");
div.className = "message"; div.className = "message";
@ -1415,36 +1421,63 @@ export class Et2Dialog extends Et2Widget(SlotMixin(SlDialog))
// Fire next step // Fire next step
if(!cancel && index < _list.length) if(!cancel && index < _list.length)
{ {
var parameters = _list[index]; return Promise.resolve(index);
if(typeof parameters != 'object') }
}
/** Send off the request for one item */
let sendRequest = function(index)
{
let request = null;
let parameters = _list[index];
if(typeof parameters != 'object')
{
parameters = [parameters];
}
// Set up timeout for 30 seconds
const timeout_id = window.setTimeout(() =>
{
// Abort request, we'll either skip it or try again
if(request && request.abort)
{ {
parameters = [parameters]; request.abort();
} }
updateUi({type: 'error', data: dialog.egw().lang("failed") + " " + parameters.join(" ")}, index + 1)
}, 30000);
// Async request, we'll take the next step in the callback // Async request, we'll take the next step in the callback
// We can't pass index = 0, it looks like false and causes issues // We can't pass index = 0, it looks like false and causes issues
dialog.egw().json(_menuaction, parameters, update, index + 1, true, index + 1).sendRequest(); try
}
else
{ {
// All done request = dialog.egw().json(_menuaction, parameters).sendRequest()
if(!cancel) .then(async(response) =>
{ {
progressbar.set_value(100); if(response && response.response)
} {
clearTimeout(timeout_id);
// Disable cancel (it's too late), enable OK for(let value of response.response)
dialog.querySelector('et2-button[button_id="' + Et2Dialog.CANCEL_BUTTON + '"]').setAttribute("disabled", "") {
dialog.querySelector('et2-button[button_id="' + Et2Dialog.OK_BUTTON + '"]').removeAttribute("disabled") await updateUi(value.type == "data" ? value.data : value, index + 1);
if(!cancel && typeof _callback == "function") }
{ }
_callback.call(dialog, true, response); })
} .catch(async(response) =>
{
clearTimeout(timeout_id);
updateUi({type: 'error', data: response.message ?? response}, index + 1);
});
} }
catch(e)
{
clearTimeout(timeout_id);
request.abort();
updateUi({type: 'error', data: dialog.egw().lang("No response from server: your data is probably NOT saved")}, index + 1);
}
return request;
}; };
// Wait for dialog, then start the process // Wait for dialog, then start the process
dialog.getUpdateComplete().then(function() dialog.getUpdateComplete().then(async function()
{ {
// Get access to template widgets // Get access to template widgets
log = dialog.template.widgetContainer.getDOMWidgetById('log').getDOMNode(); log = dialog.template.widgetContainer.getDOMWidgetById('log').getDOMNode();
@ -1452,13 +1485,29 @@ export class Et2Dialog extends Et2Widget(SlotMixin(SlDialog))
progressbar.set_label('0 / ' + _list.length); progressbar.set_label('0 / ' + _list.length);
totals.widget = dialog.template.widgetContainer.getWidgetById('totals'); totals.widget = dialog.template.widgetContainer.getWidgetById('totals');
// Start for(let index = 0; index < _list.length && !cancel; index++)
window.setTimeout(function()
{ {
update.call(0, ''); await sendRequest(index);
}, 0); if(retryDialog)
}); {
await retryDialog;
}
}
// All done
if(!cancel)
{
progressbar.set_value(100);
}
// Disable cancel (it's too late), enable OK
dialog.querySelector('et2-button[button_id="' + Et2Dialog.CANCEL_BUTTON + '"]').setAttribute("disabled", "")
dialog.querySelector('et2-button[button_id="' + Et2Dialog.OK_BUTTON + '"]').removeAttribute("disabled")
if(!cancel && typeof _callback == "function")
{
_callback.call(dialog, true, success);
}
});
return dialog; return dialog;
} }
} }