feat(usecase): read stored transcript before fetching (ADR-021)
The engine now resolves transcripts store-first: a stored transcript — including a stored SourceNone — is summarized without touching YouTube, so re-analysis never re-fetches. On a miss it fetches through the source (caption call still gated, ADR-014) and persists the terminal outcome for the next analysis by any user. A transient SourceRateLimited is surfaced to the runner for per-user backoff but never cached, so persistence can never mask a 429 as a permanent "no transcript". The TranscriptStore is optional (nil → fetch every time), keeping the pure-core and scaffold wiring valid. cmd/tapir wires the store as both summary sink and transcript cache, so `tapir run` and the web summarize path (incl. paste + onboarding) all share the dedup. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -63,7 +63,12 @@ func buildProcessor(cfg config.Config, st *store.Store) (*usecase.Engine, error)
|
||||
}
|
||||
sum := summarizer.New(primary, nil)
|
||||
|
||||
return usecase.NewEngine(src, sum, st), nil
|
||||
// The store is both the summary sink and the shared transcript cache (ADR-021):
|
||||
// the engine reads stored transcripts before any caption fetch and writes
|
||||
// resolved ones back, so re-analysis never re-touches YouTube.
|
||||
eng := usecase.NewEngine(src, sum, st)
|
||||
eng.Transcripts = st
|
||||
return eng, nil
|
||||
}
|
||||
|
||||
// engineProcessor adapts the engine (which works in terms of a domain.Video) to
|
||||
|
||||
Reference in New Issue
Block a user