Skip to content

Ensure demo-seeded invoice PDFs are present on storage - #174

Merged
thibaudgg merged 2 commits into
masterfrom
cursor/demo-seed-invoice-pdf-upload-2b5d
Sep 4, 2026
Merged

Ensure demo-seeded invoice PDFs are present on storage#174
thibaudgg merged 2 commits into
masterfrom
cursor/demo-seed-invoice-pdf-upload-2b5d

Conversation

@thibaudgg

Copy link
Copy Markdown
Member

Why

Production AppSignal exception incident #370 is an ActiveStorage::FileNotFoundError on tenant demo-de (blob id 131). Admin invoice show preview (_invoice_preview.html.erb) calls invoice.pdf_file.preview when invoice.pdf_current? && !invoice.processing?. The attachment row existed; the S3 object key did not.

This is separate from:

  • PR Return 404 when Active Storage representation blobs are missing #173 (merged) — FileNotFoundError → 404 on representations. Defense in depth for the request path; it does not stop the seeder from creating orphans.
  • pdf_stale / Send-button fixes (6cf1408, b8a4a3a, 1811e08) — those keep Other invoices sendable around Active Storage updated_at touches. pdf_current? is !pdf_stale? when attached, so an orphan blob with pdf_stale: false still offers the preview. Timing alone would not have prevented #370.

ChoresJob#purge_unattached_active_storage_blobs! only purges unattached blobs older than a week, so this attached orphan stays.

What

Demo seed wraps invoice.process!attach_pdf in a transaction (create_other_invoices!, seed_historical_shop_orders!). On Rails 8.1, Active Storage persists blob/attachment rows in after_save and uploads in after_commit. A reload on the same invoice instance before commit (shop historical orders do this) clears attachment_changes and skips the upload — DB row, missing object key (Rails #57222).

After the seed transaction:

  1. Check each attached invoice pdf_file with blob.service.exist?(blob.key) (works for tenant_object_store / TenantS3 in production and Disk in test).
  2. Re-call Invoice#attach_pdf outside the transaction when the key is missing, so the upload is synchronous and pdf_stale stays false.

mark_deliveries_delivered! still rescues FileNotFoundError as a safety net (same class of race, added in 066e96c). ChoresJob purge rules are unchanged.

Tests

  • Re-attach when the blob row exists but the file does not; pdf_current? / sendability stay true.
  • Leave present PDFs in place (same blob id).

Do not merge or deploy from this PR. Leave the AppSignal incident open.

Open in Web Open in Cursor 

cursoragent and others added 2 commits September 3, 2026 19:30
Active Storage uploads wait for after_commit, and a reload inside
the seeder transaction can drop the pending upload (Rails #57222).
The resulting attached-but-missing blob still looks pdf_current?,
so admin invoice preview hits FileNotFoundError (AppSignal #370).

Co-authored-by: Thibaud Guillaume-Gentil <thibaud@thibaud.gg>
Skip invoices with no pdf_file attachment so the ensure step
repairs orphans without generating PDFs for unrelated records.

Co-authored-by: Thibaud Guillaume-Gentil <thibaud@thibaud.gg>
@thibaudgg
thibaudgg marked this pull request as ready for review September 4, 2026 05:47
@thibaudgg
thibaudgg merged commit 475aa81 into master Sep 4, 2026
4 checks passed
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.

2 participants