Fix illustration pipeline: poll background job token to display generated images in UI#158
Conversation
…1-mini to gpt-image-1 Agent-Logs-Url: https://github.com/CyberSecDef/NovelForge/sessions/0f18f183-a633-420c-a80f-24ad8e7364a1 Co-authored-by: CyberSecDef <17597068+CyberSecDef@users.noreply.github.com>
CyberSecDef
left a comment
There was a problem hiding this comment.
the problem was definitively not the image_model, which is set in the environment properly. the images ARE being generated and stored in the exports folder properly. the response from the server after generation is:
{"illustration_token":"18fea0bb-730f-4122-a648-3cccf924dca6"}
but there is no data there to update the UI with the images. I am guessing that after generating the images, there needs to be another step to load the image from the exports folder and update the UI to have those two images displayed.
…mages Agent-Logs-Url: https://github.com/CyberSecDef/NovelForge/sessions/0004c800-39d0-4bb9-a3b4-cb4f5b38327f Co-authored-by: CyberSecDef <17597068+CyberSecDef@users.noreply.github.com>
You're right — the real bug was in the frontend. The backend's Fixed in commit
|
There was a problem hiding this comment.
Pull request overview
This PR fixes the illustration-generation UI flow by treating /generate_illustrations as an async job launcher (returns an illustration_token) and polling the existing /progress/<token> endpoints until results are ready, then rendering the generated images.
Changes:
- Added a frontend polling loop to wait for the illustration background job to reach
done/error, updating in-button status text during execution. - On completion, fetches
/progress/<illustration_token>/fullto retrieve theillustrationsarray and renders it. - Added a dedicated span in the Generate Illustrations button to display live polling status text.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 6 comments.
| File | Description |
|---|---|
static/js/script.js |
Implements polling of /progress/<illustration_token> and updates the illustration rendering flow to use the background-job token. |
templates/index.html |
Adds a spinner label element inside the Generate Illustrations button for live status text during polling. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| $.ajax({ | ||
| url: "/progress/" + illustToken, | ||
| method: "GET", | ||
| success: function (data) { |
There was a problem hiding this comment.
The polling GET requests don’t set a timeout. If a /progress/ request hangs (e.g., stalled connection), neither the success nor error callback will fire, so polling stops and the spinner/export buttons never recover. Add a reasonable timeout for the lightweight poll (and handle timeout in the error path) so the UI can continue retrying or fail gracefully.
| $.ajax({ | ||
| url: "/generate_illustrations", | ||
| method: "POST", | ||
| contentType: "application/json", | ||
| data: JSON.stringify({ token: _progressToken }), | ||
| timeout: 600000, // 10 min timeout for image generations | ||
| success: function (resp) { |
There was a problem hiding this comment.
The initial POST to /generate_illustrations no longer has any timeout. That route should return quickly with an illustration_token; without a timeout a stalled request can leave the UI stuck in “Starting…”. Consider adding a short timeout (and treating timeouts like other transient errors) since the long-running work is now done via polling.
| error: function () { | ||
| // Retry on transient network errors, up to 10 attempts. | ||
| if (retries < 10) { | ||
| setTimeout(function () { | ||
| _pollIllustrationJob(illustToken, retries + 1); | ||
| }, 5000); | ||
| } else { | ||
| showAlert( | ||
| "Lost connection to the server while waiting for illustrations. Please check your connection and try again." | ||
| ); | ||
| $("#illustrations-spinner").addClass("d-none"); | ||
| $("#illustrations-spinner-label").addClass("d-none").text(""); | ||
| _enableExportButtons(); | ||
| } |
There was a problem hiding this comment.
The poll error handler retries all HTTP failures up to 10 times but doesn’t inspect the response. For non-transient errors like 404 {"error":"Unknown token"} (e.g., server restart/eviction), it should stop retrying and surface the server-provided error to the user instead of reporting a generic connectivity issue after 10 attempts.
| $.ajax({ | ||
| url: "/progress/" + illustToken + "/full", | ||
| method: "GET", | ||
| success: function (full) { | ||
| renderIllustrations(full.illustrations || []); | ||
| }, | ||
| error: function () { | ||
| renderIllustrations([]); | ||
| }, | ||
| complete: function () { | ||
| $("#illustrations-spinner").addClass("d-none"); | ||
| $("#illustrations-spinner-label").addClass("d-none").text(""); | ||
| _enableExportButtons(); |
There was a problem hiding this comment.
If fetching /progress//full fails, the code renders an empty gallery without any alert, which can mislead users into thinking “no illustrations were generated” rather than “results couldn’t be retrieved”. Consider showing an error message (and/or keeping the existing gallery) when the full payload request fails.
|
|
||
| $("#btn-generate-illustrations").on("click", function () { | ||
| clearAlerts(); | ||
| var $btn = $(this); |
There was a problem hiding this comment.
var $btn = $(this); is unused in this click handler. Removing it avoids dead code and keeps the handler easier to maintain.
| var $btn = $(this); |
| <h6 class="text-muted mb-2">Illustrations</h6> | ||
| <button class="btn btn-outline-primary" id="btn-generate-illustrations"> | ||
| <span class="spinner-border spinner-border-sm d-none me-2" id="illustrations-spinner"></span> | ||
| <span id="illustrations-spinner-label" class="d-none me-1"></span> |
There was a problem hiding this comment.
This label is updated live during polling but lacks the aria-live pattern used elsewhere in this template (e.g., #progress-label). Adding aria-live="polite" (and optionally role="status") will make progress updates accessible to screen readers.
| <span id="illustrations-spinner-label" class="d-none me-1"></span> | |
| <span id="illustrations-spinner-label" class="d-none me-1" aria-live="polite" role="status"></span> |
After clicking "Generate Illustrations", the backend launches image generation in a background thread and immediately returns
{"illustration_token": "..."}. The frontend'ssuccesscallback was readingresp.illustrationsdirectly from that response (which is always empty), causing the UI to always show "No illustrations were generated."Changes
static/js/script.js: Added_pollIllustrationJob(illustToken, retries)function that:/progress/<illustration_token>every 3 seconds until the job reachesdoneorerrorstatus/progress/<illustration_token>/fullto retrieve theillustrationsarray and passes it torenderIllustrations()templates/index.html: Added<span id="illustrations-spinner-label">inside the Generate button to display live status text during polling