Skip to content

feat: separate live and vod quality for watched channels#1203

Open
Zibbp wants to merge 3 commits into
mainfrom
separate-quality-live
Open

feat: separate live and vod quality for watched channels#1203
Zibbp wants to merge 3 commits into
mainfrom
separate-quality-live

Conversation

@Zibbp

@Zibbp Zibbp commented Jun 3, 2026

Copy link
Copy Markdown
Owner

Closes #1190

Adds a separate quality for live and vod/video archives in watched channels. Live quality is backfilled on first run.

@coderabbitai

coderabbitai Bot commented Jun 3, 2026

Copy link
Copy Markdown

Review Change Stack

Important

Review skipped

Review was skipped due to path filters

⛔ Files ignored due to path filters (1)
  • go.sum is excluded by !**/*.sum

CodeRabbit blocks several paths by default. You can override this behavior by explicitly including those paths in the path filters. For example, including **/dist/** will override the default block on the dist directory, by removing the pattern from both the lists.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 5b0e2082-cd6c-456c-8916-44990138b6d0

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Walkthrough

This PR adds a separate vod_resolution field to the Live watched-channel configuration, allowing video-on-demand archive quality to be configured independently from live stream quality. The field is persisted to the database, exposed in HTTP requests, wired through service-layer create/update operations with automatic defaulting, and integrated into the frontend admin UI with split live vs. VOD resolution controls.

Changes

Add VOD Resolution Configuration Field

Layer / File(s) Summary
Entity schema definition and ORM code generation
ent/schema/live.go, ent/live.go, ent/live/live.go, ent/live/where.go, ent/migrate/schema.go, ent/runtime.go
vod_resolution is added as an optional string field in the schema with default "best". All entity hydration, SQL scanning, query predicates, constants, column definitions, and runtime descriptor wiring are generated to support the new field.
Create, update, and mutation builders
ent/live_create.go, ent/live_update.go, ent/mutation.go
Create, update, and upsert builder methods are added for vod_resolution alongside defaulting logic and mutation field plumbing. The mutation struct now includes vod_resolution storage and introspection APIs.
HTTP request types and handler wiring
internal/transport/http/live.go
vod_resolution field is added to both AddWatchedChannelRequest and UpdateWatchedChannelRequest. Both handlers wire the request field through to the service-layer Live DTO.
Service-layer persistence and archive quality selection
internal/live/live.go, internal/live/clip.go, internal/live/vod.go
The Live DTO gains VodResolution field. Create and update operations default vod_resolution to resolution when empty. Clip and VOD archival now use VodResolution instead of Resolution when selecting archive quality.
Database schema backfill helper
internal/database/database.go
After schema creation, a conditional backfill populates the new vod_resolution column from resolution where the value is empty or null. Helper functions check column existence and execute the backfill SQL.
Frontend watched channel hook and state
frontend/app/hooks/useWatchedChannels.ts
WatchedChannel interface extends with vod_resolution: string. Both create and edit API calls now include vod_resolution in their payloads.
Frontend drawer component with split resolution controls
frontend/app/components/admin/watched/DrawerContent.tsx
The single resolution input is split into two controls: one for live resolution, one for VOD resolution. Form initialization and submit paths include both fields with appropriate fallback logic.
Translation strings for resolution labels
frontend/messages/en.json, frontend/messages/de.json, frontend/messages/uk.json
New translation keys liveResolutionLabel and vodResolutionLabel are added to support the split resolution UI in English, German, and Ukrainian.
Generated API documentation
docs/docs.go, docs/swagger.json
Swagger schema definitions for ent.Live, http.AddWatchedChannelRequest, and http.UpdateWatchedChannelRequest are updated to document the new vod_resolution field with enum constraints and descriptions.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The PR title 'feat: separate live and vod quality for watched channels' clearly and concisely describes the main change: separating quality settings for live and VOD archives.
Description check ✅ Passed The PR description is related to the changeset, referencing issue #1190 and explaining the feature adds separate quality settings for live and VOD archives with backfilling.
Linked Issues check ✅ Passed The PR implements issue #1190 requirements: adds separate quality settings for live watching versus VOD archiving, includes backfill logic, and updates both backend and frontend to support the new vod_resolution field.
Out of Scope Changes check ✅ Passed All changes are directly related to implementing separate live and VOD quality settings: schema additions, API layer updates, database migrations, frontend UI changes, and data backfill logic.
Docstring Coverage ✅ Passed Docstring coverage is 89.66% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch separate-quality-live

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@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: 2

🤖 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 `@docs/docs.go`:
- Around line 5853-5865: The docs' vod_resolution enum in docs.go doesn't match
the backend utils.VodQuality contract: update the enum values used by
vod_resolution to exactly match utils.VodQuality (use numeric strings like
"1440", "1080", "720", "480", "360", "160", plus "best", "audio", and include
"source") and make the same change in the second occurrence (the block
referenced around the second location). Edit the vod_resolution enums in docs.go
so they align with the utils.VodQuality symbol values used by the backend to
avoid request/validation mismatches.

In `@internal/database/database.go`:
- Around line 101-109: The current migration adds vod_resolution with DEFAULT
"best" so backfillLiveVodResolution never matches; either (A) change the
migration path: add the vod_resolution column without a DEFAULT, run
backfillLiveVodResolution to set vod_resolution = resolution for existing rows,
then ALTER the column to set DEFAULT 'best' for future inserts (locate the logic
around client.Schema.Create and ent/schema/live.go/ent/migrate/schema.go to
implement this), or (B) change backfillLiveVodResolution to treat the existing
DEFAULT value as a placeholder by updating rows where vod_resolution IS NULL OR
vod_resolution = '' OR vod_resolution = 'best' to vod_resolution = resolution;
also ensure columnExists properly propagates errors (it should return false on
error) so the backfill runs when appropriate.
🪄 Autofix (Beta)

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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: fb1348d3-5244-4615-ac7a-f62c134ed9cc

📥 Commits

Reviewing files that changed from the base of the PR and between 32b8911 and 340b1db.

⛔ Files ignored due to path filters (1)
  • go.sum is excluded by !**/*.sum
📒 Files selected for processing (22)
  • docs/docs.go
  • docs/swagger.json
  • docs/swagger.yaml
  • ent/live.go
  • ent/live/live.go
  • ent/live/where.go
  • ent/live_create.go
  • ent/live_update.go
  • ent/migrate/schema.go
  • ent/mutation.go
  • ent/runtime.go
  • ent/schema/live.go
  • frontend/app/components/admin/watched/DrawerContent.tsx
  • frontend/app/hooks/useWatchedChannels.ts
  • frontend/messages/de.json
  • frontend/messages/en.json
  • frontend/messages/uk.json
  • internal/database/database.go
  • internal/live/clip.go
  • internal/live/live.go
  • internal/live/vod.go
  • internal/transport/http/live.go

Comment thread docs/docs.go
Comment thread internal/database/database.go

@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.

🧹 Nitpick comments (1)
internal/database/database.go (1)

183-183: ⚡ Quick win

Error-handling tradeoff noted: consider retry or fail-loud on persistent errors.

Returning false on error prioritizes correctness on first boot (when the column doesn't exist and the backfill is required) over safety on subsequent boots (if the check transiently fails when the column already exists, the backfill runs again and could overwrite rows where users explicitly set vod_resolution = 'best').

For a one-time migration this is reasonable—the warning log provides operator visibility, and transient failures on later boots are rare. However, for additional resilience, consider:

  • Retrying the query a few times before returning false, or
  • Logging at Error level and treating persistent query failure as a fatal migration precondition (since we can't safely decide whether to backfill without knowing the column state).
🤖 Prompt for 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.

In `@internal/database/database.go` at line 183, The code that checks whether the
vod_resolution column exists (the function that currently returns false on query
error in internal/database/database.go) should not silently treat a query error
as “no column”; either implement a small retry loop (e.g., 3 attempts with short
backoff) around the existence query and only return false after retries fail, or
escalate on persistent failure by logging at Error level and returning an
explicit fatal error instead of false so callers can abort the
migration/backfill; update the function handling the vod_resolution existence
check to perform retries or return an error, and ensure callers adjust to handle
the error path accordingly.
🤖 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.

Nitpick comments:
In `@internal/database/database.go`:
- Line 183: The code that checks whether the vod_resolution column exists (the
function that currently returns false on query error in
internal/database/database.go) should not silently treat a query error as “no
column”; either implement a small retry loop (e.g., 3 attempts with short
backoff) around the existence query and only return false after retries fail, or
escalate on persistent failure by logging at Error level and returning an
explicit fatal error instead of false so callers can abort the
migration/backfill; update the function handling the vod_resolution existence
check to perform retries or return an error, and ensure callers adjust to handle
the error path accordingly.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: bc6e48b9-2c5b-46c3-a2a9-0e5bc551525b

📥 Commits

Reviewing files that changed from the base of the PR and between 340b1db and 3ecff24.

📒 Files selected for processing (2)
  • docs/docs.go
  • internal/database/database.go
✅ Files skipped from review due to trivial changes (1)
  • docs/docs.go

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.

Can't Watch Live and Archive same channel with different Quality Settings.

1 participant