After transcript caching (ADR-021) and the Shorts filter (ADR-023), the remaining caption waste is the first fetch on every new video of a channel that never has English captions — each costs one rate-limited fetch to resolve to "none", and on a throttled IP churns the backoff machinery first. Remember, per (user, channel), a streak of consecutive no-caption outcomes (channel_caption_state, migration 016, RLS-scoped). Once it reaches TAPIR_CHANNEL_CAPTIONLESS_THRESHOLD (default 5) the channel is suppressed — videos discovered/listed but not caption-fetched — for TAPIR_CHANNEL_CAPTIONLESS_WINDOW (default 14d), then one is re-probed (auto-recovery). A successful fetch resets the streak; a 429 does not count; an explicit manual request bypasses suppression. threshold=0 disables. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
31 lines
1.6 KiB
SQL
31 lines
1.6 KiB
SQL
-- Migration 016: per-(user, channel) caption-availability memory (ADR-024).
|
|
--
|
|
-- Some channels never publish English captions (foreign-language news, music,
|
|
-- etc.). Each of their new videos still costs ONE rate-limited caption fetch
|
|
-- (ADR-014) before resolving to "none" — and on a throttled egress IP that fetch
|
|
-- may 429 and churn through the backoff machinery first. This table remembers
|
|
-- channels that repeatedly yield no captions so discovery can stop attempting
|
|
-- their videos, freeing the scarce fetch budget for channels that do have them.
|
|
--
|
|
-- consecutive_none counts no-caption outcomes in a row; a successful fetch resets
|
|
-- it to 0. Once it crosses the threshold the channel is suppressed until
|
|
-- captionless_until, after which one video is re-probed (auto-recovery for a
|
|
-- channel that starts adding captions). Per-user + RLS-scoped, consistent with
|
|
-- the rest of the user-owned schema (subscriptions are per-user; ADR-012).
|
|
CREATE TABLE channel_caption_state (
|
|
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
|
channel_id TEXT NOT NULL,
|
|
consecutive_none INT NOT NULL DEFAULT 0,
|
|
captionless_until TIMESTAMPTZ,
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
PRIMARY KEY (user_id, channel_id)
|
|
);
|
|
|
|
CREATE INDEX idx_channel_caption_state_user_id ON channel_caption_state(user_id);
|
|
|
|
ALTER TABLE channel_caption_state ENABLE ROW LEVEL SECURITY;
|
|
ALTER TABLE channel_caption_state FORCE ROW LEVEL SECURITY;
|
|
CREATE POLICY channel_caption_state_isolation ON channel_caption_state
|
|
FOR ALL
|
|
USING (user_id = current_setting('tapir.current_user_id', true)::uuid);
|