Skip to content

No dead cards on the Open Wall: no padding past page one, no refused frames - #383

Merged
widgetii merged 1 commit into
masterfrom
wall-no-dead-cards
Oct 3, 2026
Merged

widgetii merged 1 commit into
masterfrom
wall-no-dead-cards

Conversation

@widgetii

@widgetii widgetii commented Oct 3, 2026

Copy link
Copy Markdown
Member

On 2026-10-03 /open-wall/2 showed four cameras followed by cards that looked dead:

  • Five "No signal / stay tuned" cards were padding. The gallery padded every page to nine (a copy of the old page), so the last page of a full wall — 22 cameras, 18 a page — read as cameras that had gone dark. None of the five was a camera.
  • One card was a camera whose only upload had been refused (hi3516dv100, 2.2.10.29-ultimate, one HEIF in two days). The gallery listed each camera's newest frame with or without a picture, so it was a blank card sized "x". Why it was refused could not be found: the reason lived only in the log of a container a deploy had since replaced, and the file is deleted on refusal.

Change

  • galleryBlanks (lib/wall-route.ts): "no signal" cards only on a wall of one page (fewer than nine cameras); never past page one.
  • snapshots.Store: the gallery (LatestPerCamera), a camera's permalink (ByCameraToken) and a camera's day (DayOf) leave out a refused frame and show the one before it; a camera with no picture is not listed. A frame still being published is shown, as before.
  • refused_reason on the row (migration 023), written by MarkRefused.
  • Conformance: frames() uploads a real picture by default. The suite's JPEG is a header and padding, which the wall refuses; three gallery tests had been passing on refused frames.

Tests: galleryBlanks (vitest), TestARefusedFrameIsNotShown (gallery, permalink, day, reason), conformance suite green, bin/conformance --mutations: all 6 mutations killed.

Dev: deployed (service + bundle) with 21 test cameras uploading production pictures and one whose only upload is refused (refused_reason = "JPEG: marker expected"). Page 2: three cameras, no padding cards, pagination; the refused camera on neither page.

…frames

On 2026-10-03 /open-wall/2 showed four cameras and six cards that looked
dead. Five were padding: the gallery padded every page to nine with "no
signal / stay tuned", a copy of the old page, so the last page of a full
wall read as cameras gone dark. The sixth was a camera whose only upload in
two days had been refused: the gallery listed each camera's newest frame
with or without a picture, so it was a blank card sized "x".

- galleryBlanks: "no signal" cards only on a wall of one page.
- The gallery, a camera's permalink and a camera's day leave out a refused
  frame and show the one before it; a camera with no picture is not shown.
  A frame still being published is shown, as before.
- Why a frame was refused is kept on its row (refused_reason, migration
  023). That camera's reason was only in the log of a container a deploy
  had since replaced, and its file is deleted on refusal.
- The conformance suite uploads a real picture by default: its JPEG is a
  header and padding, which the wall refuses, and refused frames are no
  longer shown.
@qodo-free-for-open-source-projects

Copy link
Copy Markdown

PR Summary by Qodo

Hide refused frames and remove padding from multi-page walls

🐞 Bug fix 🧪 Tests 🕐 20-40 Minutes

Grey Divider

AI Description

• Show placeholder cards only when the entire wall fits on one page.
• Exclude refused frames from gallery, camera, and day views while retaining refusal reasons.
• Use publishable pictures in conformance tests and cover refused-frame fallback.
Diagram

graph TD
  Processor["Variant Processor"] --> DB[("Snapshots DB")] --> Store["Snapshot Queries"] --> API["Wall API"] --> Gallery["Gallery UI"] --> Blanks["Placeholder Rule"]
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Add an explicit refusal status
  • ➕ Makes refusal independent of the current generated-at and missing-width convention.
  • ➖ Requires a broader schema and processing change, including handling existing rows.

Recommendation: Use the PR's shared store-level visibility predicate for this fix: it keeps gallery, permalink, and day results consistent without duplicating filters in API handlers. An explicit refusal status could clarify the model later, but is not necessary to eliminate these dead cards.

Files changed (9) +121 / -23

Bug fix (5) +39 / -14
Wall.tsxLimit no-signal cards to single-page walls +4/-4

Limit no-signal cards to single-page walls

• Gallery rendering now calculates placeholder cards from both tile count and total page count instead of padding every page to nine.

frontend/apps/site/src/components/wall/Wall.tsx

wall-route.tsAdd a gallery placeholder-count helper +12/-0

Add a gallery placeholder-count helper

• Introduces galleryBlanks, which pads single-page walls to nine cards but returns no placeholders for multi-page walls.

frontend/apps/site/src/lib/wall-route.ts

023_refused_reason.sqlPersist snapshot refusal reasons +6/-0

Persist snapshot refusal reasons

• Adds a nullable refused_reason column so the reason remains available after the refused file is deleted and container logs disappear.

service/internal/db/migrations/023_refused_reason.sql

store.goExclude refused frames from wall-facing snapshot queries +15/-8

Exclude refused frames from wall-facing snapshot queries

• Applies one visibility predicate to gallery, camera-token, and day queries while retaining frames still being published. MarkRefused now stores the refusal reason on the snapshot row.

service/internal/snapshots/store.go

variants.goPass variant refusal reasons to snapshot storage +2/-2

Pass variant refusal reasons to snapshot storage

• Extends the worker's store contract and passes ErrRefused.Reason when closing a refused frame, preserving the existing file-purge behavior.

service/internal/variants/variants.go

Tests (4) +82 / -9
wall-route.test.tsCover single-page and paginated placeholder counts +15/-1

Cover single-page and paginated placeholder counts

• Adds tests that preserve padding on a quiet single-page wall and prohibit it when the wall has multiple pages.

frontend/apps/site/src/lib/wall-route.test.ts

wall_api_test.goUpload publishable pictures in wall conformance tests +7/-6

Upload publishable pictures in wall conformance tests

• The default frame helper now uploads a real picture rather than a JPEG header with padding that the wall refuses. A gallery assertion derives its expected byte count from that picture.

service/conformance/wall_api_test.go

snapshots_test.goVerify refused-frame fallback and retained reason +59/-1

Verify refused-frame fallback and retained reason

• Tests that gallery, camera permalink, and day queries skip refused frames, fall back to an earlier shown frame, and omit cameras with only refused frames. Also checks that pending frames remain visible and the refusal reason is saved.

service/internal/snapshots/snapshots_test.go

variants_test.goAdapt the variant test store to the refusal contract +1/-1

Adapt the variant test store to the refusal contract

• Updates the fake store's MarkRefused signature to accept a reason so variant tests continue to exercise the worker contract.

service/internal/variants/variants_test.go

@qodo-free-for-open-source-projects

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (0)

Grey Divider

Great, no issues found!

Qodo reviewed your code and found no material issues that require review

Grey Divider

Tip of the day
💡 Did you know, you can copy the agent prompt from any finding and feed it to your IDE agent

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

@widgetii
widgetii merged commit d4dc134 into master Oct 3, 2026
4 checks passed
@widgetii
widgetii deleted the wall-no-dead-cards branch October 3, 2026 15:23
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