Skip to content

Commit

Permalink
feat(frontend): show celery task status while users wait for the results
Browse files Browse the repository at this point in the history
  • Loading branch information
mcauer authored and matthiasschaub committed Oct 18, 2023
1 parent 108d927 commit e7c32dc
Show file tree
Hide file tree
Showing 5 changed files with 52 additions and 34 deletions.
4 changes: 4 additions & 0 deletions client-src/base/results.css
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,7 @@
height: 3rem;
font-size: 2rem;
}

.task-status {
font-size: small;
}
54 changes: 40 additions & 14 deletions client-src/shared/poll/poll.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,26 @@
import { PollUntilValid } from "./pollUntilValid.js";
import { setDownloadLink, setIsBusy, setDisabled } from "../domHelpers.js";
import {
setDownloadLink,
setIsBusy,
setDisabled,
setTaskStatus,
} from "../domHelpers.js";

/**
* This function polls repeatedly data from a URL as long as it receives
* HTTP 202 Accepted Codes.
* It will stop if it get a 200 OK or any Code outside the range of 200-299.
* Depending on Success(200), Pending(202), or any failure (!200-299 or NetworkError) it
* It will stop if it gets a 200 OK or any Code outside the range of 200-299.
* Depending on Success(200), Pending(202), or any failure (!200-299) it
* will display different messages to the user.
* On NetworkError it will continue polling.
*
* The function assumes the availability of 2 HTML Elements with the following ids:
* @example
* <span id="YOUR_PREFIX_HERE-status"></span>
* <a id="YOUR_PREFIX_HERE-download-button"></a>
*
* @param downloadUrl
* @param prefix
* @param url url to poll from
* @param prefix identifier used to decide where results or progress messages should be displayed
* @returns {Promise<Response>}
*/
async function poll(url, prefix) {
Expand All @@ -25,11 +31,14 @@ async function poll(url, prefix) {

async function onProgress(response) {
// console.log("progress", response);
const result = await response.json();
setTaskStatus(`${prefix}-status`, `Processing ${result.status}`);
}

async function onValid(response) {
const result = await response.json();
const { status, href } = result;
const { href } = result;
setTaskStatus(`${prefix}-status`, "");
setDownloadLink(`${prefix}-download-button`, href);
setIsBusy(`${prefix}-download-button`, false);
setDisabled(`${prefix}-download-button`, false);
Expand All @@ -42,6 +51,7 @@ async function poll(url, prefix) {
/**
* Displays an error message and disappears the download button
* @param _prefix sketch-map | quality-report
* @param errorText text shown in the error message details
*/
function handleError(_prefix, errorText) {
document.querySelectorAll(`#${prefix} :is(.pending, .success)`)
Expand All @@ -60,19 +70,35 @@ async function poll(url, prefix) {
}

async function onError(response) {
const { status: httpStatus } = response;
const resonseJSON = await response.json();
const errorText = resonseJSON.error;
console.log(response.status, response.statusText, errorText, resonseJSON);
handleError(prefix, errorText);
const {
error: errorText,
status: taskStatus,
} = resonseJSON;
// display error
if (httpStatus === 500) {
handleError(prefix, `${new Date().toISOString()} ${taskStatus} <br>
There was an Internal Server Error.`);
} else {
handleError(prefix, `${new Date().toISOString()} ${taskStatus} <br> ${errorText}`);
}
// remove task status
setTaskStatus(`${prefix}-status`, "");
}

try {
return await PollUntilValid.poll(url, validateFn, 1000, onValid, onProgress, onError);
} catch (e) {
// Network Error or other reason why the request could not be completed
console.log(e);
handleError(prefix, e);
return null;
} catch (error) {
if (error instanceof TypeError) {
// Chrome and Firefox use different Error messages, so it's hard to be more
// specific than checking for TypeError
// see: https://developer.mozilla.org/en-US/docs/Web/API/fetch#exceptions
setTaskStatus(`${prefix}-status`, "NetworkError: RETRYING to get task status");
await PollUntilValid.wait(5000);
return poll(url, prefix);
}
throw error;
}
}

Expand Down
22 changes: 3 additions & 19 deletions client-src/shared/poll/pollUntilValid.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,24 +27,8 @@ class PollUntilValid {
onError = () => {},
) {
do {
let response;
try {
/* eslint-disable no-await-in-loop */
response = await fetch(url);
} catch (error) {
if (error instanceof TypeError) {
// Chrome and Firefox use different Error messages, so it's hard to be more
// specific than checking for TypeError
// see: https://developer.mozilla.org/en-US/docs/Web/API/fetch#exceptions
console.log("NetworkError, continue retrying", error);
await PollUntilValid.wait(5000);
} else {
throw error;
}
}

// eslint-disable-next-line no-continue
if (!response) continue;
/* eslint-disable no-await-in-loop */
const response = await fetch(url);

// if response code is not between 200-299
if (!response.ok) {
Expand All @@ -60,7 +44,7 @@ class PollUntilValid {
return response;
}

/* eslint-enable */
// eslint-disable-next-line no-constant-condition
} while (true);
}

Expand Down
2 changes: 2 additions & 0 deletions sketch_map_tool/templates/create-results.html
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ <h6>Map Quality Check Report</h6>
<a id="quality-report-download-button" href="#" download aria-busy="true"
role="button" disabled="disabled">Download
PDF</a>
<div id="quality-report-status" class="task-status"></div>
</article>
</div>
<div>
Expand Down Expand Up @@ -77,6 +78,7 @@ <h6>Sketch Map Template</h6>
<a id="sketch-map-download-button" href="#" download aria-busy="true"
role="button"
disabled="disabled">Download PDF</a>
<div id="sketch-map-status" class="task-status"></div>
</article>
</div>
</div>
Expand Down
4 changes: 3 additions & 1 deletion sketch_map_tool/templates/digitize-results.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
{% endblock head %}

{% block header_message %}
<div class="circle" style="display: inline-block" ;>2</div>Paper to GIS:
<div class="circle" style="display: inline-block;">2</div>Paper to GIS:
<span style="font-size: smaller">Automatically Digitize Your Sketch&nbsp;Maps</span>
{% endblock %}

Expand Down Expand Up @@ -44,6 +44,7 @@ <h6>Geo-referenced markings as GeoTiffs</h6>
</p>
<a id="raster-data-download-button" href="#" download aria-busy="true"
role="button" disabled="disabled">Download ZIP</a>
<div id="raster-data-status" class="task-status"></div>
</article>
</div>
<div>
Expand Down Expand Up @@ -71,6 +72,7 @@ <h6>Geo-referenced markings as GeoJSON</h6>
<a id="vector-data-download-button" href="#" download aria-busy="true"
role="button"
disabled="disabled">Download GeoJSON</a>
<div id="vector-data-status" class="task-status"></div>
</article>
</div>
</div>
Expand Down

0 comments on commit e7c32dc

Please sign in to comment.