Skip to content

fix(cl2k): defer artwork uploads like posters, and report deferred failures - #491

Merged
chodeus merged 5 commits into
developfrom
fix/cl2k-align-upload-paths
Aug 9, 2026
Merged

fix(cl2k): defer artwork uploads like posters, and report deferred failures#491
chodeus merged 5 commits into
developfrom
fix/cl2k-align-upload-paths

Conversation

@chodeus

@chodeus chodeus commented Aug 9, 2026

Copy link
Copy Markdown
Owner

Summary

Only the poster path deferred its Drive upload; the three asset makers uploaded inline. This aligns all four — and fixes the reason alignment wasn't safe on its own: a deferred upload that failed was reported to the user as success.

Related issue

N/A — found while investigating the duplicate-upload report (#490).

Type of change

  • Bug fix (non-breaking)
  • New feature (non-breaking)
  • Breaking change (config migration, schema, endpoint, or UI behavior)
  • Docs only
  • Refactor / internal cleanup

The silent failure

defer_upload=background_tasks.add_task was wired at exactly one call site, so:

path before after
generate_for_item (poster) deferred deferred
generate_square_art inline deferred
generate_background_art inline deferred
generate_logo_asset inline deferred

A deferred upload has no response left to fail on. The caller is told "queued", and a later failure existed only as a logger.warning. The success check is if not written and not uploaded_folders, and written is non-empty by definition whenever we defer — so a poster whose Drive upload failed outright still reported success.

Aligning the paths without fixing that would have spread the silence to artwork, so both land together.

A deferred failure now logs at error level and sends a failure notification through the same NotificationManager other modules use for async outcomes.

Placement matters here. The report has to sit above the if not uploaded_folders: return early exit — a total failure leaves that list empty, which is precisely the case worth reporting. My first version sat below it and reported nothing; the test now pins that.

What didn't need changing

The frontend. All five save paths already share savedToast, which reads upload_pending and shows "— uploading to Drive…". Artwork picks that up for free. The API success messages were aligned to the poster's wording for consistency of the response itself.

Deliberately unchanged

/retext and the season batch still upload inline. Inline is the safer trade-off — errors return to the caller — and deferral exists only because rclone outruns the 30s request timeout on multi-folder poster saves. Worth aligning later if timeouts start biting there.

Also unchanged: deferral still requires a local copy. A Drive-only save stages a temp file and deletes it in finally, so a background task would find nothing to upload — those stay inline regardless of path, which the tests document.

Testing

  • 4 tests: every interactive endpoint accepts background_tasks, every generator accepts defer_upload, a deferred failure notifies and logs at error level, and a clean upload stays quiet.
  • The failure test drives the deferred closure directly — the same call BackgroundTasks makes after the response — and asserts nothing is reported before it runs.
  • ruff clean; 228 cl2k tests pass. Branch isolation stays additions-only.

Summary by CodeRabbit

  • New Features

    • Artwork and logo generation uploads can now continue in the background, allowing faster responses.
    • Clear upload-in-progress messages are shown when processing continues after the response.
    • Deferred uploads use current configuration and routing settings.
  • Bug Fixes

    • Upload, configuration, and routing failures are now logged and reported with relevant asset details.
    • Improved consistency across poster, square-art, background-art, and logo-asset generation workflows.
  • Tests

    • Added coverage for deferred uploads, successful processing, and failure notifications.

…ilures

Only the poster path deferred its Drive upload; the three asset makers uploaded
inline. Align them — but deferral is only safe once failures are reported,
because a deferred upload has no response left to fail on. The caller is told
"queued", and until now a later failure existed solely as a log line: the
success check is `not written and not uploaded_folders`, and `written` is
non-empty by definition whenever we defer, so it always returned success.

A deferred failure now logs at error level and sends a failure notification
through the same NotificationManager other modules use for async outcomes. That
report has to sit ABOVE the `if not uploaded_folders: return` early exit — a
total failure leaves that list empty, which is exactly the case worth telling
the user about.

The API messages match the poster's "— uploading to Drive" wording, and the
frontend needs no change: all five save paths already share savedToast, which
reads upload_pending.

Unchanged by design: /retext and the season batch still upload inline. Inline is
the safer trade-off (errors return to the caller); deferral exists only because
rclone outruns the 30s request timeout.
@coderabbitai

coderabbitai Bot commented Aug 9, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

You’ve reached a temporary PR review limit under our Fair Usage Limits Policy.

Your recent review volume is higher than typical usage, so adaptive limits are currently applied.

Next review available in: 49 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: e2464c3a-c1c7-4980-9528-ddd57d9271df

📥 Commits

Reviewing files that changed from the base of the PR and between eaa31cf and 9035eee.

📒 Files selected for processing (1)
  • tests/test_cl2k_upload_deferral.py
📝 Walkthrough

Walkthrough

Interactive square-art, background-art, and logo-asset endpoints now defer Drive uploads through BackgroundTasks. Generators forward deferral callbacks and configuration to persistence. Deferred failures log and notify with upload details.

Changes

Artwork upload deferral

Layer / File(s) Summary
Interactive endpoint wiring
backend/api/cl2k_maker.py
Interactive artwork endpoints accept BackgroundTasks, schedule deferred uploads, and return an upload-in-progress response when needed.
Generator persistence and failure handling
backend/modules/cl2k_maker.py
Artwork generators forward defer_upload and full_config to persistence. Deferred upload, configuration reload, and route resolution failures are logged and reported through NotificationManager.
Deferred upload validation
tests/test_cl2k_upload_deferral.py
Tests cover signatures, deferred execution, successful uploads without notifications, upload failures, configuration reload failures, and route removal.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant ArtworkEndpoint
  participant ArtworkGenerator
  participant BackgroundTasks
  participant NotificationManager
  Client->>ArtworkEndpoint: request artwork generation
  ArtworkEndpoint->>ArtworkGenerator: generate with deferred upload callback
  ArtworkGenerator->>BackgroundTasks: schedule Drive upload
  ArtworkEndpoint-->>Client: return upload-in-progress response
  BackgroundTasks->>ArtworkGenerator: execute upload
  ArtworkGenerator->>NotificationManager: report upload failure
Loading

Possibly related PRs

  • chodeus/chub#405: Adds the deferred Drive-upload mechanism for poster generation, which this change extends to other artwork endpoints.
  • chodeus/chub#470: Changes Drive subfolder creation and routing used by the deferred upload path.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main changes: deferring artwork uploads and reporting deferred failures.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/cl2k-align-upload-paths

Comment @coderabbitai help to get the list of available commands.

@chodeus

chodeus commented Aug 9, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 9, 2026

Copy link
Copy Markdown
⚠️ Action not completed

Review rate limited.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@chodeus

chodeus commented Aug 9, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 9, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@backend/modules/cl2k_maker.py`:
- Around line 1018-1036: Update the deferred upload flow around load_config() so
configuration-load exceptions are captured as upload failures instead of
returning before reporting. Record the failure in upload_errors and route it
through the existing logger and NotificationManager failure path, while
preserving the queued-success response already returned by the API. Add a
regression test that schedules the task, makes load_config() raise, and verifies
error-level logging plus failure notification.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: c8626656-5bef-45e6-8d45-9b7652ade424

📥 Commits

Reviewing files that changed from the base of the PR and between cc2b236 and 78e3bf7.

📒 Files selected for processing (3)
  • backend/api/cl2k_maker.py
  • backend/modules/cl2k_maker.py
  • tests/test_cl2k_upload_deferral.py

Comment thread backend/modules/cl2k_maker.py Outdated
A deferred upload has no response left to fail on, so any path that returns
without uploading reads to the user as success. Three such paths existed; the
earlier commit fixed only the one at the bottom.

- upload failures (already fixed)
- the config reload failing — logged a warning and returned ABOVE the report
- routing changing so nothing claims the type — an INFO log, while the response
  had promised "uploading to Drive"

All three now go through one _report_deferred_failure(), which also takes the
request-time full_config: when the reload is what failed, the notification
cannot depend on that same reload succeeding.

The second and third were found by sweeping the function for the shape after the
first was reported, rather than waiting for review to surface them one at a
time. Each has a regression test, and the config-reload one was confirmed to
fail against the old silent return.
@chodeus

chodeus commented Aug 9, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 9, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@tests/test_cl2k_upload_deferral.py`:
- Around line 178-193: Update
test_losing_the_route_before_the_task_runs_is_reported to assert the captured
errors list contains an entry with "FAILED", matching the error-level logging
check used by test_a_failed_config_reload_is_reported_not_swallowed. Keep the
existing notification assertions unchanged.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: b984b76c-e8d6-48d5-93df-52577ef5308c

📥 Commits

Reviewing files that changed from the base of the PR and between 78e3bf7 and eaa31cf.

📒 Files selected for processing (2)
  • backend/modules/cl2k_maker.py
  • tests/test_cl2k_upload_deferral.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • backend/modules/cl2k_maker.py

Comment thread tests/test_cl2k_upload_deferral.py
The lost-route test captured logger.error but never asserted on it, so that
path could regress to info or warning and still pass — it checked half the
reporting contract.

Sweeping the file for the same shape found a second one: the success test
asserted no notification but not the absence of a failure log, so a regression
could report a failure through the log alone and go unnoticed. Both directions
are now pinned, and downgrading the error log to warning was confirmed to fail
the suite.
@chodeus
chodeus merged commit abb2fc3 into develop Aug 9, 2026
12 checks passed
@chodeus
chodeus deleted the fix/cl2k-align-upload-paths branch August 9, 2026 09:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant