package playback import ( "errors" "fmt" "time" ) var ( ErrFeedDomainRequired = errors.New("feed domain is required when its UUID is configured") ErrInvalidMaxAttempts = errors.New("max attempts cannot be negative") ErrInvalidRetryDelay = errors.New("retry delay must be positive") ErrInvalidRetryRange = errors.New("maximum retry delay cannot be less than initial retry delay") ErrActiveFeedNotConfigured = errors.New("feed cannot be active without a UUID") ) type FeedConfig struct { Domain string UUID string Active bool } type RetryPolicy struct { MaxAttempts int // 0 = unlimited InitialDelay time.Duration MaxDelay time.Duration } type SessionConfig struct { Video FeedConfig Audio FeedConfig SyncRequested bool Retry RetryPolicy } func (f FeedConfig) IsConfigured() bool { return f.UUID != "" } func (f FeedConfig) Validate() error { if f.Active && !f.IsConfigured() { return ErrActiveFeedNotConfigured } if f.IsConfigured() && f.Domain == "" { return ErrFeedDomainRequired } return nil } func (p RetryPolicy) Validate() error { if p.MaxAttempts < 0 { return ErrInvalidMaxAttempts } if p.InitialDelay <= 0 || p.MaxDelay <= 0 { return ErrInvalidRetryDelay } if p.MaxDelay < p.InitialDelay { return ErrInvalidRetryRange } return nil } func (c SessionConfig) HasFeeds() bool { return c.Video.IsConfigured() || c.Audio.IsConfigured() } func (c SessionConfig) Validate() error { if err := c.Video.Validate(); err != nil { return fmt.Errorf("video: %w", err) } if err := c.Audio.Validate(); err != nil { return fmt.Errorf("audio: %w", err) } if err := c.Retry.Validate(); err != nil { return fmt.Errorf("retry: %w", err) } return nil }