package web import ( "context" "sync" "gitea.d-ma.be/mathias/tapir/internal/domain" ) // Processor runs the core summarization use case for a single already-discovered // video — resolve its transcript, summarize, deliver to the store. *usecase.Engine // wrapped with the store satisfies it (wired in cmd/tapir). Optional on App: a nil // Processor means queue-only — the "Summarize" button only flips the DB flag and // the next `tapir run` does the work. type Processor interface { ProcessVideo(ctx context.Context, userID, videoID string) error } // VideoFetcher resolves an arbitrary YouTube video id to its metadata for the // paste-a-URL flow (Feature 2). It is a Data API call, NOT the rate-limited // caption path. Returns domain.ErrVideoNotFound for a deleted/private/typo'd id. // cmd/tapir wires a per-user YouTube adapter; nil disables the paste route. type VideoFetcher interface { FetchVideo(ctx context.Context, userID, videoID string) (domain.Video, error) } // ProcessingSet tracks the (user, video) ids currently being summarized in-process // so the status endpoint can show the animation until the summary lands. It is // ephemeral (single-instance Stage-1): a restart drops it, and the DB holds the // durable state — the summary is present, or summarize_requested is still set so // `tapir run` retries. The zero value is ready to use; methods are concurrency-safe. type ProcessingSet struct { m sync.Map } // Add marks a key in-flight. func (p *ProcessingSet) Add(key string) { p.m.Store(key, struct{}{}) } // Remove clears a key once its summarization finishes (success or failure). func (p *ProcessingSet) Remove(key string) { p.m.Delete(key) } // Has reports whether a key is currently in-flight. func (p *ProcessingSet) Has(key string) bool { _, ok := p.m.Load(key) return ok } // processingKey scopes the in-flight key by user so one user's summarization is // never confused with another's for the same video id. func processingKey(userID, videoID string) string { return userID + "|" + videoID }